Compare commits
1 Commits
master
...
patch-brig
Author | SHA1 | Date | |
---|---|---|---|
a67028ec39
|
63
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
63
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -1,63 +0,0 @@
|
|||||||
name: Bug inside BungeeCord
|
|
||||||
description: Create a bug report about a problem inside BungeeCord.
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
#### Report a bug inside bungeecord
|
|
||||||
Issues happening with forks of BungeeCord should **not** be reported here.
|
|
||||||
- type: input
|
|
||||||
id: bungee-version
|
|
||||||
attributes:
|
|
||||||
label: Bungeecord version
|
|
||||||
description: The output of the /bungee command (or just the bungee build number) (execute in bungeecord console for easy text copy)
|
|
||||||
placeholder: e.g. git:BungeeCord-Bootstrap:1.xx-SNAPSHOT:xxxxxxx:xxxx
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: input
|
|
||||||
id: server-version
|
|
||||||
attributes:
|
|
||||||
label: Server version
|
|
||||||
description: The output of the /version command (execute in server console for easy text copy)
|
|
||||||
placeholder: "e.g. git-Spigot-xxxxxxx-xxxxxxx (MC: 1.x.x)"
|
|
||||||
- type: input
|
|
||||||
id: client-version
|
|
||||||
attributes:
|
|
||||||
label: Client version
|
|
||||||
description: Minecraft Client Version
|
|
||||||
placeholder: e.g. 1.18.2
|
|
||||||
- type: textarea
|
|
||||||
id: bungee-plugins
|
|
||||||
attributes:
|
|
||||||
label: Bungeecord plugins
|
|
||||||
description: Please list all BungeeCord plugins you are using.
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: the-bug
|
|
||||||
attributes:
|
|
||||||
label: The bug
|
|
||||||
description: Please describe the bug. Include **details** you find neccessary. If you just have a question, please ask it in [SpigotMC Forums](https://www.spigotmc.org) and not here.
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: logs
|
|
||||||
attributes:
|
|
||||||
label: Log output (links)
|
|
||||||
description: Please put your log output inbetween three backticks (```` ``` ````). Upload your log files to [gist.github.com](https://gist.github.com) and put them in here.
|
|
||||||
placeholder: |
|
|
||||||
```
|
|
||||||
log output
|
|
||||||
```
|
|
||||||
- type: checkboxes
|
|
||||||
id: checkboxes
|
|
||||||
attributes:
|
|
||||||
label: Checking
|
|
||||||
options:
|
|
||||||
- label: I am using BungeeCord and **not a fork**. Issues with forks should not be reported here.
|
|
||||||
required: true
|
|
||||||
- label: I think this is **not** an issue with a bungeecord plugin.
|
|
||||||
required: true
|
|
||||||
- label: I have not read these checkboxes and therefore I just ticked them all.
|
|
||||||
- label: This is not a question or plugin creation help request.
|
|
||||||
required: true
|
|
14
.github/ISSUE_TEMPLATE/config.yml
vendored
14
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,14 +0,0 @@
|
|||||||
blank_issues_enabled: false
|
|
||||||
contact_links:
|
|
||||||
- name: Configuration help
|
|
||||||
url: https://www.spigotmc.org/forums/bungeecord-help.70/create-thread
|
|
||||||
about: Help for configuring bungeecord will only be answered in spigotmc.org forums.
|
|
||||||
- name: I have a problem with a bungee plugin
|
|
||||||
url: https://www.spigotmc.org/forums/bungeecord-plugin-help.71/create-thread
|
|
||||||
about: Help about plugins can be recieved in spigotmc.org forums.
|
|
||||||
- name: Questions and discussions
|
|
||||||
url: https://www.spigotmc.org/forums/bungeecord-discussion.21/create-thread
|
|
||||||
about: spigotmc.org forums are the best place to ask your questions regarding bungeecord.
|
|
||||||
- name: Plugin creation help
|
|
||||||
url: https://www.spigotmc.org/forums/bungeecord-plugin-development.23/create-thread
|
|
||||||
about: Plugin creation help for bungee plugins can be recieved in spigotmc.org forums.
|
|
36
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
36
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
@@ -1,36 +0,0 @@
|
|||||||
name: Feature request
|
|
||||||
description: Suggest a feature which bungeecord should include.
|
|
||||||
body:
|
|
||||||
- type: textarea
|
|
||||||
id: the-feature
|
|
||||||
attributes:
|
|
||||||
label: Feature description
|
|
||||||
description: Please describe your feature or improvement. Please include **details**.
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: goal
|
|
||||||
attributes:
|
|
||||||
label: Goal of the feature
|
|
||||||
description: What is the goal of your feature?
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: alternatives
|
|
||||||
attributes:
|
|
||||||
label: Unfitting alternatives
|
|
||||||
description: What alternatives have you considered and why are they not sufficient for your use case?
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: checkboxes
|
|
||||||
id: checkboxes
|
|
||||||
attributes:
|
|
||||||
label: Checking
|
|
||||||
options:
|
|
||||||
- label: This is not a question or plugin creation help request.
|
|
||||||
required: true
|
|
||||||
- label: This is a **feature or improvement request**.
|
|
||||||
required: true
|
|
||||||
- label: I have not read these checkboxes and therefore I just ticked them all.
|
|
||||||
- label: I did not use this form to report a bug.
|
|
||||||
required: true
|
|
27
.github/dependabot.yml
vendored
27
.github/dependabot.yml
vendored
@@ -1,27 +0,0 @@
|
|||||||
version: 2
|
|
||||||
|
|
||||||
updates:
|
|
||||||
- package-ecosystem: "maven"
|
|
||||||
directory: "/"
|
|
||||||
schedule:
|
|
||||||
interval: "daily"
|
|
||||||
open-pull-requests-limit: 50
|
|
||||||
ignore:
|
|
||||||
# Synchronised with Minecraft
|
|
||||||
- dependency-name: "com.google.code.gson:gson"
|
|
||||||
# 9.x has performance issues (see, eg, checkstyle/checkstyle#10934) and 10.x is incompatible
|
|
||||||
- dependency-name: "com.puppycrawl.tools:checkstyle"
|
|
||||||
# Newer versions have issues, see #1909 and #2050
|
|
||||||
- dependency-name: "jline:jline"
|
|
||||||
# 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"
|
|
||||||
# Used with maven-resolver dependencies; 2.0 update breaks other providers
|
|
||||||
- dependency-name: "org.slf4j:slf4j-api"
|
|
||||||
update-types: ["version-update:semver-major"]
|
|
||||||
|
|
||||||
- package-ecosystem: "github-actions"
|
|
||||||
directory: "/"
|
|
||||||
schedule:
|
|
||||||
interval: "daily"
|
|
||||||
open-pull-requests-limit: 50
|
|
10
.github/workflows/maven.yml
vendored
10
.github/workflows/maven.yml
vendored
@@ -4,20 +4,18 @@ on: [push, pull_request]
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
matrix:
|
||||||
java: [8, 11, 17, 21, 25-ea]
|
java: [8, 11]
|
||||||
|
|
||||||
name: Java ${{ matrix.java }}
|
name: Java ${{ matrix.java }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-java@v4
|
- uses: actions/setup-java@v1
|
||||||
with:
|
with:
|
||||||
distribution: zulu
|
|
||||||
java-version: ${{ matrix.java }}
|
java-version: ${{ matrix.java }}
|
||||||
- run: java -version && mvn --version
|
- run: java -version && mvn --version
|
||||||
- run: mvn --activate-profiles dist --no-transfer-progress package
|
- run: mvn --activate-profiles dist --no-transfer-progress package
|
||||||
|
6
.gitmodules
vendored
6
.gitmodules
vendored
@@ -1,6 +0,0 @@
|
|||||||
[submodule "native/mbedtls"]
|
|
||||||
path = native/mbedtls
|
|
||||||
url = https://github.com/ARMmbed/mbedtls.git
|
|
||||||
[submodule "native/zlib"]
|
|
||||||
path = native/zlib
|
|
||||||
url = https://github.com/cloudflare/zlib.git
|
|
@@ -23,4 +23,4 @@ Binaries
|
|||||||
--------
|
--------
|
||||||
Precompiled binaries are available for end users on [Jenkins](https://www.spigotmc.org/go/bungeecord-dl).
|
Precompiled binaries are available for end users on [Jenkins](https://www.spigotmc.org/go/bungeecord-dl).
|
||||||
|
|
||||||
(c) 2012-2025 SpigotMC Pty. Ltd.
|
(c) 2012-2020 SpigotMC Pty. Ltd.
|
||||||
|
34
api/pom.xml
34
api/pom.xml
@@ -6,13 +6,13 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>net.md-5</groupId>
|
<groupId>net.md-5</groupId>
|
||||||
<artifactId>bungeecord-parent</artifactId>
|
<artifactId>bungeecord-parent</artifactId>
|
||||||
<version>1.21-R0.4-SNAPSHOT</version>
|
<version>1.16-R0.4-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<groupId>net.md-5</groupId>
|
<groupId>net.md-5</groupId>
|
||||||
<artifactId>bungeecord-api</artifactId>
|
<artifactId>bungeecord-api</artifactId>
|
||||||
<version>1.21-R0.4-SNAPSHOT</version>
|
<version>1.16-R0.4-SNAPSHOT</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>BungeeCord-API</name>
|
<name>BungeeCord-API</name>
|
||||||
@@ -31,12 +31,6 @@
|
|||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>net.md-5</groupId>
|
|
||||||
<artifactId>bungeecord-dialog</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.md-5</groupId>
|
<groupId>net.md-5</groupId>
|
||||||
<artifactId>bungeecord-event</artifactId>
|
<artifactId>bungeecord-event</artifactId>
|
||||||
@@ -52,33 +46,13 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.netty</groupId>
|
<groupId>io.netty</groupId>
|
||||||
<artifactId>netty-transport-native-unix-common</artifactId>
|
<artifactId>netty-transport-native-unix-common</artifactId>
|
||||||
|
<version>${netty.version}</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.maven</groupId>
|
|
||||||
<artifactId>maven-resolver-provider</artifactId>
|
|
||||||
<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.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.9.18</version>
|
|
||||||
<!-- not part of the API proper -->
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.yaml</groupId>
|
<groupId>org.yaml</groupId>
|
||||||
<artifactId>snakeyaml</artifactId>
|
<artifactId>snakeyaml</artifactId>
|
||||||
<version>2.2</version>
|
<version>1.26</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
@@ -7,7 +7,6 @@ import java.net.InetSocketAddress;
|
|||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -69,17 +68,6 @@ public class Util
|
|||||||
return String.format( "0x%02X", i );
|
return String.format( "0x%02X", i );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Formats an char as a unicode value.
|
|
||||||
*
|
|
||||||
* @param c the character to format
|
|
||||||
* @return the unicode representation of the character
|
|
||||||
*/
|
|
||||||
public static String unicode(char c)
|
|
||||||
{
|
|
||||||
return "\\u" + String.format( "%04x", (int) c ).toUpperCase( Locale.ROOT );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a pretty one line version of a {@link Throwable}. Useful for
|
* Constructs a pretty one line version of a {@link Throwable}. Useful for
|
||||||
* debugging.
|
* debugging.
|
||||||
@@ -88,24 +76,11 @@ public class Util
|
|||||||
* @return a string representing information about the {@link Throwable}
|
* @return a string representing information about the {@link Throwable}
|
||||||
*/
|
*/
|
||||||
public static String exception(Throwable t)
|
public static String exception(Throwable t)
|
||||||
{
|
|
||||||
return exception( t, true );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a pretty one line version of a {@link Throwable}. Useful for
|
|
||||||
* debugging.
|
|
||||||
*
|
|
||||||
* @param t the {@link Throwable} to format.
|
|
||||||
* @param includeLineNumbers whether to include line numbers
|
|
||||||
* @return a string representing information about the {@link Throwable}
|
|
||||||
*/
|
|
||||||
public static String exception(Throwable t, boolean includeLineNumbers)
|
|
||||||
{
|
{
|
||||||
// TODO: We should use clear manually written exceptions
|
// TODO: We should use clear manually written exceptions
|
||||||
StackTraceElement[] trace = t.getStackTrace();
|
StackTraceElement[] trace = t.getStackTrace();
|
||||||
return t.getClass().getSimpleName() + " : " + t.getMessage()
|
return t.getClass().getSimpleName() + " : " + t.getMessage()
|
||||||
+ ( ( includeLineNumbers && trace.length > 0 ) ? " @ " + t.getStackTrace()[0].getClassName() + ":" + t.getStackTrace()[0].getLineNumber() : "" );
|
+ ( ( trace.length > 0 ) ? " @ " + t.getStackTrace()[0].getClassName() + ":" + t.getStackTrace()[0].getLineNumber() : "" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String csv(Iterable<?> objects)
|
public static String csv(Iterable<?> objects)
|
||||||
@@ -113,16 +88,6 @@ public class Util
|
|||||||
return format( objects, ", " );
|
return format( objects, ", " );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a string of objects, each separated by a separator.
|
|
||||||
*
|
|
||||||
* @param objects the objects to join
|
|
||||||
* @param separators the separator
|
|
||||||
* @return joined string
|
|
||||||
* @see String#join(java.lang.CharSequence, java.lang.Iterable)
|
|
||||||
* @deprecated use {@link String} join methods
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public static String format(Iterable<?> objects, String separators)
|
public static String format(Iterable<?> objects, String separators)
|
||||||
{
|
{
|
||||||
return Joiner.on( separators ).join( objects );
|
return Joiner.on( separators ).join( objects );
|
||||||
|
@@ -28,13 +28,18 @@ public abstract class AbstractReconnectHandler implements ReconnectHandler
|
|||||||
|
|
||||||
public static ServerInfo getForcedHost(PendingConnection con)
|
public static ServerInfo getForcedHost(PendingConnection con)
|
||||||
{
|
{
|
||||||
String forced = ( con.getVirtualHost() == null ) ? null : con.getListener().getForcedHosts().get( con.getVirtualHost().getHostString() );
|
if ( con.getVirtualHost() == null )
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String forced = con.getListener().getForcedHosts().get( con.getVirtualHost().getHostString() );
|
||||||
|
|
||||||
if ( forced == null && con.getListener().isForceDefault() )
|
if ( forced == null && con.getListener().isForceDefault() )
|
||||||
{
|
{
|
||||||
forced = con.getListener().getDefaultServer();
|
forced = con.getListener().getDefaultServer();
|
||||||
}
|
}
|
||||||
return ( forced == null ) ? null : ProxyServer.getInstance().getServerInfo( forced );
|
return ProxyServer.getInstance().getServerInfo( forced );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract ServerInfo getStoredServer(ProxiedPlayer player);
|
protected abstract ServerInfo getStoredServer(ProxiedPlayer player);
|
||||||
|
@@ -1,10 +1,9 @@
|
|||||||
package net.md_5.bungee.api;
|
package net.md_5.bungee.api;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
import com.google.common.io.BaseEncoding;
|
import com.google.common.io.BaseEncoding;
|
||||||
import com.google.gson.TypeAdapter;
|
import com.google.gson.TypeAdapter;
|
||||||
|
import com.google.gson.internal.bind.TypeAdapters;
|
||||||
import com.google.gson.stream.JsonReader;
|
import com.google.gson.stream.JsonReader;
|
||||||
import com.google.gson.stream.JsonToken;
|
|
||||||
import com.google.gson.stream.JsonWriter;
|
import com.google.gson.stream.JsonWriter;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
@@ -27,26 +26,13 @@ public class Favicon
|
|||||||
@Override
|
@Override
|
||||||
public void write(JsonWriter out, Favicon value) throws IOException
|
public void write(JsonWriter out, Favicon value) throws IOException
|
||||||
{
|
{
|
||||||
if ( value == null )
|
TypeAdapters.STRING.write( out, value == null ? null : value.getEncoded() );
|
||||||
{
|
|
||||||
out.nullValue();
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
out.value( value.getEncoded() );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Favicon read(JsonReader in) throws IOException
|
public Favicon read(JsonReader in) throws IOException
|
||||||
{
|
{
|
||||||
JsonToken peek = in.peek();
|
String enc = TypeAdapters.STRING.read( in );
|
||||||
if ( peek == JsonToken.NULL )
|
|
||||||
{
|
|
||||||
in.nextNull();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
String enc = in.nextString();
|
|
||||||
return enc == null ? null : create( enc );
|
return enc == null ? null : create( enc );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -73,7 +59,6 @@ public class Favicon
|
|||||||
*/
|
*/
|
||||||
public static Favicon create(BufferedImage image)
|
public static Favicon create(BufferedImage image)
|
||||||
{
|
{
|
||||||
Preconditions.checkArgument( image != null, "image is null" );
|
|
||||||
// check size
|
// check size
|
||||||
if ( image.getWidth() != 64 || image.getHeight() != 64 )
|
if ( image.getWidth() != 64 || image.getHeight() != 64 )
|
||||||
{
|
{
|
||||||
|
@@ -16,7 +16,6 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
|
|||||||
import net.md_5.bungee.api.plugin.Plugin;
|
import net.md_5.bungee.api.plugin.Plugin;
|
||||||
import net.md_5.bungee.api.plugin.PluginManager;
|
import net.md_5.bungee.api.plugin.PluginManager;
|
||||||
import net.md_5.bungee.api.scheduler.TaskScheduler;
|
import net.md_5.bungee.api.scheduler.TaskScheduler;
|
||||||
import net.md_5.bungee.protocol.channel.BungeeChannelInitializer;
|
|
||||||
|
|
||||||
public abstract class ProxyServer
|
public abstract class ProxyServer
|
||||||
{
|
{
|
||||||
@@ -312,56 +311,4 @@ public abstract class ProxyServer
|
|||||||
*/
|
*/
|
||||||
public abstract Title createTitle();
|
public abstract Title createTitle();
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the unsafe methods of this class.
|
|
||||||
*
|
|
||||||
* @return the unsafe method interface
|
|
||||||
*/
|
|
||||||
public abstract Unsafe unsafe();
|
|
||||||
|
|
||||||
public interface Unsafe
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the frontend channel initializer
|
|
||||||
*
|
|
||||||
* @return the frontend channel initializer
|
|
||||||
*/
|
|
||||||
BungeeChannelInitializer getFrontendChannelInitializer();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the frontend channel initializer of this proxy
|
|
||||||
*
|
|
||||||
* @param channelInitializer the frontend channelInitializer to set
|
|
||||||
*/
|
|
||||||
void setFrontendChannelInitializer(BungeeChannelInitializer channelInitializer);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the backend channel initializer
|
|
||||||
*
|
|
||||||
* @return the backend channel initializer
|
|
||||||
*/
|
|
||||||
BungeeChannelInitializer getBackendChannelInitializer();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the backend channel initializer of this proxy
|
|
||||||
*
|
|
||||||
* @param channelInitializer the backend channelInitializer to set
|
|
||||||
*/
|
|
||||||
void setBackendChannelInitializer(BungeeChannelInitializer channelInitializer);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the server info channel initializer
|
|
||||||
*
|
|
||||||
* @return the server info channel initializer
|
|
||||||
*/
|
|
||||||
BungeeChannelInitializer getServerInfoChannelInitializer();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the server info channel initializer of this proxy
|
|
||||||
*
|
|
||||||
* @param channelInitializer the server info channelInitializer to set
|
|
||||||
*/
|
|
||||||
void setServerInfoChannelInitializer(BungeeChannelInitializer channelInitializer);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -105,13 +105,13 @@ public class ServerPing
|
|||||||
@Deprecated
|
@Deprecated
|
||||||
public ServerPing(Protocol version, Players players, String description, String favicon)
|
public ServerPing(Protocol version, Players players, String description, String favicon)
|
||||||
{
|
{
|
||||||
this( version, players, TextComponent.fromLegacy( description ), favicon == null ? null : Favicon.create( favicon ) );
|
this( version, players, new TextComponent( TextComponent.fromLegacyText( description ) ), favicon == null ? null : Favicon.create( favicon ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public ServerPing(Protocol version, Players players, String description, Favicon favicon)
|
public ServerPing(Protocol version, Players players, String description, Favicon favicon)
|
||||||
{
|
{
|
||||||
this( version, players, TextComponent.fromLegacy( description ), favicon );
|
this( version, players, new TextComponent( TextComponent.fromLegacyText( description ) ), favicon );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@@ -139,7 +139,7 @@ public class ServerPing
|
|||||||
@Deprecated
|
@Deprecated
|
||||||
public void setDescription(String description)
|
public void setDescription(String description)
|
||||||
{
|
{
|
||||||
this.description = TextComponent.fromLegacy( description );
|
this.description = new TextComponent( TextComponent.fromLegacyText( description ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
|
@@ -84,15 +84,5 @@ public interface Connection
|
|||||||
* @param packet the packet to send
|
* @param packet the packet to send
|
||||||
*/
|
*/
|
||||||
void sendPacket(DefinedPacket packet);
|
void sendPacket(DefinedPacket packet);
|
||||||
|
|
||||||
/**
|
|
||||||
* Queue a packet to this connection.
|
|
||||||
* If the packet is not registered for the connections current encoder protocol, it will be queued until it is,
|
|
||||||
* otherwise it will be sent immediately.
|
|
||||||
*
|
|
||||||
* @param packet the packet to be queued
|
|
||||||
* @throws UnsupportedOperationException if used for a PendingConnection
|
|
||||||
*/
|
|
||||||
void sendPacketQueued(DefinedPacket packet);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,9 +2,7 @@ package net.md_5.bungee.api.connection;
|
|||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import net.md_5.bungee.api.config.ListenerInfo;
|
import net.md_5.bungee.api.config.ListenerInfo;
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a user attempting to log into the proxy.
|
* Represents a user attempting to log into the proxy.
|
||||||
@@ -91,40 +89,4 @@ public interface PendingConnection extends Connection
|
|||||||
* @return Whether the client is using a legacy client.
|
* @return Whether the client is using a legacy client.
|
||||||
*/
|
*/
|
||||||
boolean isLegacy();
|
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);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends a login payload request to the client.
|
|
||||||
*
|
|
||||||
* @param channel the channel to send this data via
|
|
||||||
* @param data the data to send
|
|
||||||
* @return a {@link CompletableFuture} that will be completed when the Login
|
|
||||||
* Payload response is received. If the Vanilla client doesn't know the
|
|
||||||
* channel, the {@link CompletableFuture} will complete with a null value
|
|
||||||
* @throws IllegalStateException if the player's version is not at least
|
|
||||||
* 1.13
|
|
||||||
*/
|
|
||||||
@ApiStatus.Experimental
|
|
||||||
CompletableFuture<byte[]> sendData(String channel, byte[] data);
|
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,6 @@ package net.md_5.bungee.api.connection;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import net.md_5.bungee.api.Callback;
|
import net.md_5.bungee.api.Callback;
|
||||||
import net.md_5.bungee.api.ChatMessageType;
|
import net.md_5.bungee.api.ChatMessageType;
|
||||||
import net.md_5.bungee.api.CommandSender;
|
import net.md_5.bungee.api.CommandSender;
|
||||||
@@ -12,13 +11,11 @@ import net.md_5.bungee.api.SkinConfiguration;
|
|||||||
import net.md_5.bungee.api.Title;
|
import net.md_5.bungee.api.Title;
|
||||||
import net.md_5.bungee.api.chat.BaseComponent;
|
import net.md_5.bungee.api.chat.BaseComponent;
|
||||||
import net.md_5.bungee.api.config.ServerInfo;
|
import net.md_5.bungee.api.config.ServerInfo;
|
||||||
import net.md_5.bungee.api.dialog.Dialog;
|
|
||||||
import net.md_5.bungee.api.event.ServerConnectEvent;
|
import net.md_5.bungee.api.event.ServerConnectEvent;
|
||||||
import net.md_5.bungee.api.score.Scoreboard;
|
import net.md_5.bungee.api.score.Scoreboard;
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a player whose connection is being connected to somewhere else,
|
* Represents a player who's connection is being connected to somewhere else,
|
||||||
* whether it be a remote or embedded server.
|
* whether it be a remote or embedded server.
|
||||||
*/
|
*/
|
||||||
public interface ProxiedPlayer extends Connection, CommandSender
|
public interface ProxiedPlayer extends Connection, CommandSender
|
||||||
@@ -60,7 +57,8 @@ public interface ProxiedPlayer extends Connection, CommandSender
|
|||||||
String getDisplayName();
|
String getDisplayName();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets this player's display name to be used by proxy commands and plugins.
|
* Sets this players display name to be used as their nametag and tab list
|
||||||
|
* name.
|
||||||
*
|
*
|
||||||
* @param name the name to set
|
* @param name the name to set
|
||||||
*/
|
*/
|
||||||
@@ -337,77 +335,6 @@ public interface ProxiedPlayer extends Connection, CommandSender
|
|||||||
* Get the {@link Scoreboard} that belongs to this player.
|
* Get the {@link Scoreboard} that belongs to this player.
|
||||||
*
|
*
|
||||||
* @return this player's {@link Scoreboard}
|
* @return this player's {@link Scoreboard}
|
||||||
* @deprecated for internal use only, setters will not have the expected
|
|
||||||
* effect, will not update client state, and may corrupt proxy state
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
Scoreboard getScoreboard();
|
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);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the client brand of this player.
|
|
||||||
* If the player has not sent a brand packet yet, it will return null.
|
|
||||||
*
|
|
||||||
* @return the brand of the client, or null if not received yet
|
|
||||||
*/
|
|
||||||
String getClientBrand();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear the player's open dialog.
|
|
||||||
*
|
|
||||||
* @throws IllegalStateException if the players version is not at least
|
|
||||||
* 1.21.6
|
|
||||||
*/
|
|
||||||
@ApiStatus.Experimental
|
|
||||||
void clearDialog();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show a dialog to the player.
|
|
||||||
*
|
|
||||||
* @param dialog the dialog to show
|
|
||||||
* @throws IllegalStateException if the players version is not at least
|
|
||||||
* 1.21.6
|
|
||||||
*/
|
|
||||||
@ApiStatus.Experimental
|
|
||||||
void showDialog(Dialog dialog);
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,157 @@
|
|||||||
|
package net.md_5.bungee.api.event;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.arguments.ArgumentType;
|
||||||
|
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
||||||
|
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||||
|
import com.mojang.brigadier.builder.ArgumentBuilder;
|
||||||
|
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
||||||
|
import com.mojang.brigadier.suggestion.SuggestionProvider;
|
||||||
|
import com.mojang.brigadier.tree.CommandNode;
|
||||||
|
import com.mojang.brigadier.tree.RootCommandNode;
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
import net.md_5.bungee.api.CommandSender;
|
||||||
|
import net.md_5.bungee.api.connection.Connection;
|
||||||
|
import net.md_5.bungee.api.plugin.Command;
|
||||||
|
import net.md_5.bungee.api.plugin.Plugin;
|
||||||
|
import net.md_5.bungee.api.plugin.PluginManager;
|
||||||
|
import net.md_5.bungee.api.plugin.TabExecutor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event called when a downstream server (on 1.13+) sends the command structure
|
||||||
|
* to a player, but before BungeeCord adds the dummy command nodes of
|
||||||
|
* registered commands.
|
||||||
|
* <p>
|
||||||
|
* BungeeCord will not overwrite the modifications made by the listeners.
|
||||||
|
*
|
||||||
|
* <h2>Usage example</h2>
|
||||||
|
* Here is a usage example of this event, to declare a command structure.
|
||||||
|
* This illustrates the commands /server and /send of Bungee.
|
||||||
|
* <pre>
|
||||||
|
* event.getRoot().addChild( LiteralArgumentBuilder.<CommandSender>literal( "server" )
|
||||||
|
* .requires( sender -> sender.hasPermission( "bungeecord.command.server" ) )
|
||||||
|
* .executes( a -> 0 )
|
||||||
|
* .then( RequiredArgumentBuilder.argument( "serverName", StringArgumentType.greedyString() )
|
||||||
|
* .suggests( SuggestionRegistry.ASK_SERVER )
|
||||||
|
* )
|
||||||
|
* .build()
|
||||||
|
* );
|
||||||
|
* event.getRoot().addChild( LiteralArgumentBuilder.<CommandSender>literal( "send" )
|
||||||
|
* .requires( sender -> sender.hasPermission( "bungeecord.command.send" ) )
|
||||||
|
* .then( RequiredArgumentBuilder.argument( "playerName", StringArgumentType.word() )
|
||||||
|
* .suggests( SuggestionRegistry.ASK_SERVER )
|
||||||
|
* .then( RequiredArgumentBuilder.argument( "serverName", StringArgumentType.greedyString() )
|
||||||
|
* .suggests( SuggestionRegistry.ASK_SERVER )
|
||||||
|
* )
|
||||||
|
* )
|
||||||
|
* .build()
|
||||||
|
* );
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* <h2>Flag a {@link CommandNode} as executable or not</h2>
|
||||||
|
* The implementation of a {@link com.mojang.brigadier.Command Command} used in
|
||||||
|
* {@link ArgumentBuilder#executes(com.mojang.brigadier.Command)} will never be
|
||||||
|
* executed. This will only tell to the client if the current node is
|
||||||
|
* executable or not.
|
||||||
|
* <ul>
|
||||||
|
* <li>
|
||||||
|
* {@code builder.executes(null)} (default) to mark the node as not
|
||||||
|
* executable.
|
||||||
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* {@code builder.executes(a -> 0)}, or any non null argument, to mark
|
||||||
|
* the node as executable (the child arguments are displayed as
|
||||||
|
* optional).
|
||||||
|
* </li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <h2>{@link CommandNode}’s suggestions management</h2>
|
||||||
|
* The implementation of a SuggestionProvider used in
|
||||||
|
* {@link RequiredArgumentBuilder#suggests(SuggestionProvider)} will never be
|
||||||
|
* executed. This will only tell to the client how to deal with the
|
||||||
|
* auto-completion of the argument.
|
||||||
|
* <ul>
|
||||||
|
* <li>
|
||||||
|
* {@code builder.suggests(null)} (default) to disable auto-completion
|
||||||
|
* for this argument.
|
||||||
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* {@code builder.suggests(SuggestionRegistry.ALL_RECIPES)} to suggest
|
||||||
|
* Minecraft’s recipes.
|
||||||
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* {@code builder.suggests(SuggestionRegistry.AVAILABLE_SOUNDS)} to
|
||||||
|
* suggest Minecraft’s default sound identifiers.
|
||||||
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* {@code builder.suggests(SuggestionRegistry.SUMMONABLE_ENTITIES)} to
|
||||||
|
* suggest Minecraft’s default summonable entities identifiers.
|
||||||
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* {@code builder.suggests(SuggestionRegistry.ASK_SERVER)}, or any
|
||||||
|
* other non null argument, to make the Minecraft client ask
|
||||||
|
* auto-completion to the server. Any specified implementation of
|
||||||
|
* {@link SuggestionProvider} will never be executed.
|
||||||
|
* </li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <h2>Argument types</h2>
|
||||||
|
* When building a new argument command node using
|
||||||
|
* {@link RequiredArgumentBuilder#argument(String, ArgumentType)}, you have to
|
||||||
|
* specify an {@link ArgumentType}. You can use all subclasses of
|
||||||
|
* {@link ArgumentType} provided with brigadier (for instance,
|
||||||
|
* {@link StringArgumentType} or {@link IntegerArgumentType}), or call any
|
||||||
|
* {@code ArgumentRegistry.minecraft*()} methods to use a {@code minecraft:*}
|
||||||
|
* argument type.
|
||||||
|
*
|
||||||
|
* <h2>Limitations with brigadier API</h2>
|
||||||
|
* This event is only used for the client to show command syntax, suggest
|
||||||
|
* sub-commands and color the arguments in the chat box. The command execution
|
||||||
|
* needs to be implemented using {@link PluginManager#registerCommand(Plugin,
|
||||||
|
* Command)} and the server-side tab-completion using {@link TabCompleteEvent}
|
||||||
|
* or {@link TabExecutor}.
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class CommandsDeclareEvent extends TargetedEvent
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Wether or not the command tree is modified by this event.
|
||||||
|
*
|
||||||
|
* If this value is set to true, BungeeCord will ensure that the
|
||||||
|
* modifications made in the command tree, will be sent to the player.
|
||||||
|
* If this is false, the modifications may not be taken into account.
|
||||||
|
*
|
||||||
|
* When calling {@link #getRoot()}, this value is automatically set
|
||||||
|
* to true.
|
||||||
|
*/
|
||||||
|
@Setter(value = AccessLevel.NONE)
|
||||||
|
private boolean modified = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The root command node of the command structure that will be send to the
|
||||||
|
* player.
|
||||||
|
*/
|
||||||
|
private final RootCommandNode<CommandSender> root;
|
||||||
|
|
||||||
|
public CommandsDeclareEvent(Connection sender, Connection receiver, RootCommandNode<CommandSender> root)
|
||||||
|
{
|
||||||
|
super( sender, receiver );
|
||||||
|
this.root = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The root command node of the command structure that will be send to the
|
||||||
|
* player.
|
||||||
|
* @return The root command node
|
||||||
|
*/
|
||||||
|
public RootCommandNode<CommandSender> getRoot()
|
||||||
|
{
|
||||||
|
modified = true;
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
}
|
@@ -1,39 +0,0 @@
|
|||||||
package net.md_5.bungee.api.event;
|
|
||||||
|
|
||||||
import com.google.gson.JsonElement;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
import lombok.ToString;
|
|
||||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
|
||||||
import net.md_5.bungee.api.plugin.Cancellable;
|
|
||||||
import net.md_5.bungee.api.plugin.Event;
|
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called after a {@link ProxiedPlayer} runs a custom action from a chat event
|
|
||||||
* or form submission.
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@ToString(callSuper = false)
|
|
||||||
@EqualsAndHashCode(callSuper = false)
|
|
||||||
@ApiStatus.Experimental
|
|
||||||
public class CustomClickEvent extends Event implements Cancellable
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Player who clicked.
|
|
||||||
*/
|
|
||||||
private final ProxiedPlayer player;
|
|
||||||
/**
|
|
||||||
* Custom action ID.
|
|
||||||
*/
|
|
||||||
private final String id;
|
|
||||||
/**
|
|
||||||
* The data as submitted.
|
|
||||||
*/
|
|
||||||
private final JsonElement data;
|
|
||||||
/**
|
|
||||||
* Cancelled state.
|
|
||||||
*/
|
|
||||||
private boolean cancelled;
|
|
||||||
}
|
|
@@ -1,7 +1,9 @@
|
|||||||
package net.md_5.bungee.api.event;
|
package net.md_5.bungee.api.event;
|
||||||
|
|
||||||
|
import lombok.AccessLevel;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.Setter;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
import net.md_5.bungee.api.Callback;
|
import net.md_5.bungee.api.Callback;
|
||||||
import net.md_5.bungee.api.chat.BaseComponent;
|
import net.md_5.bungee.api.chat.BaseComponent;
|
||||||
@@ -25,7 +27,8 @@ public class LoginEvent extends AsyncEvent<LoginEvent> implements Cancellable
|
|||||||
/**
|
/**
|
||||||
* Message to use when kicking if this event is canceled.
|
* Message to use when kicking if this event is canceled.
|
||||||
*/
|
*/
|
||||||
private BaseComponent reason;
|
@Setter(AccessLevel.NONE)
|
||||||
|
private BaseComponent[] cancelReasonComponents;
|
||||||
/**
|
/**
|
||||||
* Connection attempting to login.
|
* Connection attempting to login.
|
||||||
*/
|
*/
|
||||||
@@ -39,44 +42,28 @@ public class LoginEvent extends AsyncEvent<LoginEvent> implements Cancellable
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @return reason to be displayed
|
* @return reason to be displayed
|
||||||
* @deprecated use component methods instead
|
* @deprecated Use component methods instead.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public String getCancelReason()
|
public String getCancelReason()
|
||||||
{
|
{
|
||||||
return TextComponent.toLegacyText( getReason() );
|
return BaseComponent.toLegacyText( getCancelReasonComponents() );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param cancelReason reason to be displayed
|
* @param cancelReason reason to be displayed
|
||||||
* @deprecated use component methods instead
|
* @deprecated Use
|
||||||
|
* {@link #setCancelReason(net.md_5.bungee.api.chat.BaseComponent...)}
|
||||||
|
* instead.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void setCancelReason(String cancelReason)
|
public void setCancelReason(String cancelReason)
|
||||||
{
|
{
|
||||||
setReason( TextComponent.fromLegacy( cancelReason ) );
|
setCancelReason( TextComponent.fromLegacyText( cancelReason ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return reason to be displayed
|
|
||||||
* @deprecated use single component methods instead
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public BaseComponent[] getCancelReasonComponents()
|
|
||||||
{
|
|
||||||
return new BaseComponent[]
|
|
||||||
{
|
|
||||||
getReason()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param cancelReason reason to be displayed
|
|
||||||
* @deprecated use single component methods instead
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public void setCancelReason(BaseComponent... cancelReason)
|
public void setCancelReason(BaseComponent... cancelReason)
|
||||||
{
|
{
|
||||||
setReason( TextComponent.fromArray( cancelReason ) );
|
this.cancelReasonComponents = cancelReason;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,9 +3,8 @@ package net.md_5.bungee.api.event;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
import net.md_5.bungee.api.Callback;
|
|
||||||
import net.md_5.bungee.api.config.ServerInfo;
|
|
||||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
|
import net.md_5.bungee.api.plugin.Event;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event called as soon as a connection has a {@link ProxiedPlayer} and is ready
|
* Event called as soon as a connection has a {@link ProxiedPlayer} and is ready
|
||||||
@@ -14,22 +13,11 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
|
|||||||
@Data
|
@Data
|
||||||
@ToString(callSuper = false)
|
@ToString(callSuper = false)
|
||||||
@EqualsAndHashCode(callSuper = false)
|
@EqualsAndHashCode(callSuper = false)
|
||||||
public class PostLoginEvent extends AsyncEvent<PostLoginEvent>
|
public class PostLoginEvent extends Event
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The player involved with this event.
|
* The player involved with this event.
|
||||||
*/
|
*/
|
||||||
private final ProxiedPlayer player;
|
private final ProxiedPlayer player;
|
||||||
/**
|
|
||||||
* The server to which the player will initially be connected.
|
|
||||||
*/
|
|
||||||
private ServerInfo target;
|
|
||||||
|
|
||||||
public PostLoginEvent(ProxiedPlayer player, ServerInfo target, Callback<PostLoginEvent> done)
|
|
||||||
{
|
|
||||||
super( done );
|
|
||||||
this.player = player;
|
|
||||||
this.target = target;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,9 @@
|
|||||||
package net.md_5.bungee.api.event;
|
package net.md_5.bungee.api.event;
|
||||||
|
|
||||||
|
import lombok.AccessLevel;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.Setter;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
import net.md_5.bungee.api.Callback;
|
import net.md_5.bungee.api.Callback;
|
||||||
import net.md_5.bungee.api.chat.BaseComponent;
|
import net.md_5.bungee.api.chat.BaseComponent;
|
||||||
@@ -30,7 +32,8 @@ public class PreLoginEvent extends AsyncEvent<PreLoginEvent> implements Cancella
|
|||||||
/**
|
/**
|
||||||
* Message to use when kicking if this event is canceled.
|
* Message to use when kicking if this event is canceled.
|
||||||
*/
|
*/
|
||||||
private BaseComponent reason;
|
@Setter(AccessLevel.NONE)
|
||||||
|
private BaseComponent[] cancelReasonComponents;
|
||||||
/**
|
/**
|
||||||
* Connection attempting to login.
|
* Connection attempting to login.
|
||||||
*/
|
*/
|
||||||
@@ -44,44 +47,28 @@ public class PreLoginEvent extends AsyncEvent<PreLoginEvent> implements Cancella
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @return reason to be displayed
|
* @return reason to be displayed
|
||||||
* @deprecated use component methods instead
|
* @deprecated Use component methods instead.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public String getCancelReason()
|
public String getCancelReason()
|
||||||
{
|
{
|
||||||
return BaseComponent.toLegacyText( getReason() );
|
return BaseComponent.toLegacyText( getCancelReasonComponents() );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param cancelReason reason to be displayed
|
* @param cancelReason reason to be displayed
|
||||||
* @deprecated Use component methods instead
|
* @deprecated Use
|
||||||
|
* {@link #setCancelReason(net.md_5.bungee.api.chat.BaseComponent...)}
|
||||||
|
* instead.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void setCancelReason(String cancelReason)
|
public void setCancelReason(String cancelReason)
|
||||||
{
|
{
|
||||||
setReason( TextComponent.fromLegacy( cancelReason ) );
|
setCancelReason( TextComponent.fromLegacyText( cancelReason ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return reason to be displayed
|
|
||||||
* @deprecated use single component methods instead
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public BaseComponent[] getCancelReasonComponents()
|
|
||||||
{
|
|
||||||
return new BaseComponent[]
|
|
||||||
{
|
|
||||||
getReason()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param cancelReason reason to be displayed
|
|
||||||
* @deprecated use single component methods instead
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public void setCancelReason(BaseComponent... cancelReason)
|
public void setCancelReason(BaseComponent... cancelReason)
|
||||||
{
|
{
|
||||||
setReason( TextComponent.fromArray( cancelReason ) );
|
this.cancelReasonComponents = cancelReason;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -8,7 +8,7 @@ import net.md_5.bungee.api.ServerPing;
|
|||||||
import net.md_5.bungee.api.connection.PendingConnection;
|
import net.md_5.bungee.api.connection.PendingConnection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the proxy is queried for status from the server list.
|
* Called when the proxy is pinged with packet 0xFE from the server list.
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@ToString(callSuper = false)
|
@ToString(callSuper = false)
|
||||||
|
@@ -3,7 +3,6 @@ package net.md_5.bungee.api.event;
|
|||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.ToString;
|
|
||||||
import net.md_5.bungee.api.CommandSender;
|
import net.md_5.bungee.api.CommandSender;
|
||||||
import net.md_5.bungee.api.plugin.Event;
|
import net.md_5.bungee.api.plugin.Event;
|
||||||
|
|
||||||
@@ -11,7 +10,6 @@ import net.md_5.bungee.api.plugin.Event;
|
|||||||
* Called when somebody reloads BungeeCord
|
* Called when somebody reloads BungeeCord
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
@ToString(callSuper = false)
|
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@EqualsAndHashCode(callSuper = false)
|
@EqualsAndHashCode(callSuper = false)
|
||||||
public class ProxyReloadEvent extends Event
|
public class ProxyReloadEvent extends Event
|
||||||
|
@@ -9,13 +9,6 @@ import net.md_5.bungee.api.config.ServerInfo;
|
|||||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
import net.md_5.bungee.api.plugin.Event;
|
import net.md_5.bungee.api.plugin.Event;
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the player is disconnected from a server, for example during
|
|
||||||
* server switching.
|
|
||||||
*
|
|
||||||
* If the player is kicked from a server, {@link ServerKickEvent} will be called
|
|
||||||
* instead.
|
|
||||||
*/
|
|
||||||
@Data
|
@Data
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@ToString(callSuper = false)
|
@ToString(callSuper = false)
|
||||||
|
@@ -35,7 +35,7 @@ public class ServerKickEvent extends Event implements Cancellable
|
|||||||
/**
|
/**
|
||||||
* Kick reason.
|
* Kick reason.
|
||||||
*/
|
*/
|
||||||
private BaseComponent reason;
|
private BaseComponent[] kickReasonComponent;
|
||||||
/**
|
/**
|
||||||
* Server to send player to if this event is cancelled.
|
* Server to send player to if this event is cancelled.
|
||||||
*/
|
*/
|
||||||
@@ -63,61 +63,24 @@ public class ServerKickEvent extends Event implements Cancellable
|
|||||||
this( player, player.getServer().getInfo(), kickReasonComponent, cancelServer, state );
|
this( player, player.getServer().getInfo(), kickReasonComponent, cancelServer, state );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public ServerKickEvent(ProxiedPlayer player, ServerInfo kickedFrom, BaseComponent[] kickReasonComponent, ServerInfo cancelServer, State state)
|
public ServerKickEvent(ProxiedPlayer player, ServerInfo kickedFrom, BaseComponent[] kickReasonComponent, ServerInfo cancelServer, State state)
|
||||||
{
|
|
||||||
this( player, kickedFrom, TextComponent.fromArray( kickReasonComponent ), cancelServer, state );
|
|
||||||
}
|
|
||||||
|
|
||||||
public ServerKickEvent(ProxiedPlayer player, ServerInfo kickedFrom, BaseComponent reason, ServerInfo cancelServer, State state)
|
|
||||||
{
|
{
|
||||||
this.player = player;
|
this.player = player;
|
||||||
this.kickedFrom = kickedFrom;
|
this.kickedFrom = kickedFrom;
|
||||||
this.reason = reason;
|
this.kickReasonComponent = kickReasonComponent;
|
||||||
this.cancelServer = cancelServer;
|
this.cancelServer = cancelServer;
|
||||||
this.state = state;
|
this.state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the kick reason
|
|
||||||
* @deprecated use component methods instead
|
|
||||||
*/
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public String getKickReason()
|
public String getKickReason()
|
||||||
{
|
{
|
||||||
return BaseComponent.toLegacyText( getReason() );
|
return BaseComponent.toLegacyText( kickReasonComponent );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param reason the kick reason
|
|
||||||
* @deprecated use component methods instead
|
|
||||||
*/
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void setKickReason(String reason)
|
public void setKickReason(String reason)
|
||||||
{
|
{
|
||||||
this.setReason( TextComponent.fromLegacy( reason ) );
|
kickReasonComponent = TextComponent.fromLegacyText( reason );
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the kick reason
|
|
||||||
* @deprecated use single component methods instead
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public BaseComponent[] getKickReasonComponent()
|
|
||||||
{
|
|
||||||
return new BaseComponent[]
|
|
||||||
{
|
|
||||||
getReason()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param kickReasonComponent the kick reason
|
|
||||||
* @deprecated use single component methods instead
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public void setKickReasonComponent(BaseComponent[] kickReasonComponent)
|
|
||||||
{
|
|
||||||
this.setReason( TextComponent.fromArray( kickReasonComponent ) );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,129 +0,0 @@
|
|||||||
package net.md_5.bungee.api.plugin;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.URLClassLoader;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
import org.apache.maven.repository.internal.MavenRepositorySystemUtils;
|
|
||||||
import org.eclipse.aether.DefaultRepositorySystemSession;
|
|
||||||
import org.eclipse.aether.RepositorySystem;
|
|
||||||
import org.eclipse.aether.artifact.Artifact;
|
|
||||||
import org.eclipse.aether.artifact.DefaultArtifact;
|
|
||||||
import org.eclipse.aether.collection.CollectRequest;
|
|
||||||
import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory;
|
|
||||||
import org.eclipse.aether.graph.Dependency;
|
|
||||||
import org.eclipse.aether.impl.DefaultServiceLocator;
|
|
||||||
import org.eclipse.aether.repository.LocalRepository;
|
|
||||||
import org.eclipse.aether.repository.RemoteRepository;
|
|
||||||
import org.eclipse.aether.repository.RepositoryPolicy;
|
|
||||||
import org.eclipse.aether.resolution.ArtifactResult;
|
|
||||||
import org.eclipse.aether.resolution.DependencyRequest;
|
|
||||||
import org.eclipse.aether.resolution.DependencyResolutionException;
|
|
||||||
import org.eclipse.aether.resolution.DependencyResult;
|
|
||||||
import org.eclipse.aether.spi.connector.RepositoryConnectorFactory;
|
|
||||||
import org.eclipse.aether.spi.connector.transport.TransporterFactory;
|
|
||||||
import org.eclipse.aether.transfer.AbstractTransferListener;
|
|
||||||
import org.eclipse.aether.transfer.TransferCancelledException;
|
|
||||||
import org.eclipse.aether.transfer.TransferEvent;
|
|
||||||
import org.eclipse.aether.transport.http.HttpTransporterFactory;
|
|
||||||
|
|
||||||
class LibraryLoader
|
|
||||||
{
|
|
||||||
|
|
||||||
private static final String REPOSITORY_PROPERTY = "net.md_5.bungee.api.plugin.centralURL";
|
|
||||||
private final Logger logger;
|
|
||||||
private final RepositorySystem repository;
|
|
||||||
private final DefaultRepositorySystemSession session;
|
|
||||||
private final List<RemoteRepository> repositories;
|
|
||||||
|
|
||||||
public LibraryLoader(Logger logger)
|
|
||||||
{
|
|
||||||
this.logger = logger;
|
|
||||||
|
|
||||||
DefaultServiceLocator locator = MavenRepositorySystemUtils.newServiceLocator();
|
|
||||||
locator.addService( RepositoryConnectorFactory.class, BasicRepositoryConnectorFactory.class );
|
|
||||||
locator.addService( TransporterFactory.class, HttpTransporterFactory.class );
|
|
||||||
|
|
||||||
this.repository = locator.getService( RepositorySystem.class );
|
|
||||||
this.session = MavenRepositorySystemUtils.newSession();
|
|
||||||
|
|
||||||
session.setChecksumPolicy( RepositoryPolicy.CHECKSUM_POLICY_FAIL );
|
|
||||||
session.setLocalRepositoryManager( repository.newLocalRepositoryManager( session, new LocalRepository( "libraries" ) ) );
|
|
||||||
session.setTransferListener( new AbstractTransferListener()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void transferStarted(TransferEvent event) throws TransferCancelledException
|
|
||||||
{
|
|
||||||
logger.log( Level.INFO, "Downloading {0}", event.getResource().getRepositoryUrl() + event.getResource().getResourceName() );
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
|
|
||||||
// SPIGOT-7638: Add system properties,
|
|
||||||
// since JdkVersionProfileActivator needs 'java.version' when a profile has the 'jdk' element
|
|
||||||
// otherwise it will silently fail and not resolves the dependencies in the affected pom.
|
|
||||||
session.setSystemProperties( System.getProperties() );
|
|
||||||
session.setReadOnly();
|
|
||||||
|
|
||||||
this.repositories = repository.newResolutionRepositories( session, Arrays.asList( new RemoteRepository.Builder( "central", "default", System.getProperty( REPOSITORY_PROPERTY, "https://repo.maven.apache.org/maven2" ) ).build() ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
public ClassLoader createLoader(PluginDescription desc)
|
|
||||||
{
|
|
||||||
if ( desc.getLibraries().isEmpty() )
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
logger.log( Level.INFO, "[{0}] Loading {1} libraries... please wait", new Object[]
|
|
||||||
{
|
|
||||||
desc.getName(), desc.getLibraries().size()
|
|
||||||
} );
|
|
||||||
|
|
||||||
List<Dependency> dependencies = new ArrayList<>();
|
|
||||||
for ( String library : desc.getLibraries() )
|
|
||||||
{
|
|
||||||
Artifact artifact = new DefaultArtifact( library );
|
|
||||||
Dependency dependency = new Dependency( artifact, null );
|
|
||||||
|
|
||||||
dependencies.add( dependency );
|
|
||||||
}
|
|
||||||
|
|
||||||
DependencyResult result;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
result = repository.resolveDependencies( session, new DependencyRequest( new CollectRequest( (Dependency) null, dependencies, repositories ), null ) );
|
|
||||||
} catch ( DependencyResolutionException ex )
|
|
||||||
{
|
|
||||||
throw new RuntimeException( "Error resolving libraries", ex );
|
|
||||||
}
|
|
||||||
|
|
||||||
List<URL> jarFiles = new ArrayList<>();
|
|
||||||
for ( ArtifactResult artifact : result.getArtifactResults() )
|
|
||||||
{
|
|
||||||
File file = artifact.getArtifact().getFile();
|
|
||||||
|
|
||||||
URL url;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
url = file.toURI().toURL();
|
|
||||||
} catch ( MalformedURLException ex )
|
|
||||||
{
|
|
||||||
throw new AssertionError( ex );
|
|
||||||
}
|
|
||||||
|
|
||||||
jarFiles.add( url );
|
|
||||||
logger.log( Level.INFO, "[{0}] Loaded library {1}", new Object[]
|
|
||||||
{
|
|
||||||
desc.getName(), file
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
|
|
||||||
URLClassLoader loader = new URLClassLoader( jarFiles.toArray( new URL[ 0 ] ) );
|
|
||||||
|
|
||||||
return loader;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,23 +1,12 @@
|
|||||||
package net.md_5.bungee.api.plugin;
|
package net.md_5.bungee.api.plugin;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.common.io.ByteStreams;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLClassLoader;
|
import java.net.URLClassLoader;
|
||||||
import java.security.CodeSigner;
|
|
||||||
import java.security.CodeSource;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.CopyOnWriteArraySet;
|
import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
import java.util.jar.JarEntry;
|
|
||||||
import java.util.jar.JarFile;
|
|
||||||
import java.util.jar.Manifest;
|
|
||||||
import lombok.ToString;
|
|
||||||
import net.md_5.bungee.api.ProxyServer;
|
import net.md_5.bungee.api.ProxyServer;
|
||||||
|
|
||||||
@ToString(of = "desc")
|
|
||||||
final class PluginClassloader extends URLClassLoader
|
final class PluginClassloader extends URLClassLoader
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -25,10 +14,6 @@ final class PluginClassloader extends URLClassLoader
|
|||||||
//
|
//
|
||||||
private final ProxyServer proxy;
|
private final ProxyServer proxy;
|
||||||
private final PluginDescription desc;
|
private final PluginDescription desc;
|
||||||
private final JarFile jar;
|
|
||||||
private final Manifest manifest;
|
|
||||||
private final URL url;
|
|
||||||
private final ClassLoader libraryLoader;
|
|
||||||
//
|
//
|
||||||
private Plugin plugin;
|
private Plugin plugin;
|
||||||
|
|
||||||
@@ -37,18 +22,11 @@ final class PluginClassloader extends URLClassLoader
|
|||||||
ClassLoader.registerAsParallelCapable();
|
ClassLoader.registerAsParallelCapable();
|
||||||
}
|
}
|
||||||
|
|
||||||
public PluginClassloader(ProxyServer proxy, PluginDescription desc, File file, ClassLoader libraryLoader) throws IOException
|
public PluginClassloader(ProxyServer proxy, PluginDescription desc, URL[] urls)
|
||||||
{
|
{
|
||||||
super( new URL[]
|
super( urls );
|
||||||
{
|
|
||||||
file.toURI().toURL()
|
|
||||||
} );
|
|
||||||
this.proxy = proxy;
|
this.proxy = proxy;
|
||||||
this.desc = desc;
|
this.desc = desc;
|
||||||
this.jar = new JarFile( file );
|
|
||||||
this.manifest = jar.getManifest();
|
|
||||||
this.url = file.toURI().toURL();
|
|
||||||
this.libraryLoader = libraryLoader;
|
|
||||||
|
|
||||||
allLoaders.add( this );
|
allLoaders.add( this );
|
||||||
}
|
}
|
||||||
@@ -56,34 +34,17 @@ final class PluginClassloader extends URLClassLoader
|
|||||||
@Override
|
@Override
|
||||||
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
|
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
|
||||||
{
|
{
|
||||||
return loadClass0( name, resolve, true, true );
|
return loadClass0( name, resolve, true );
|
||||||
}
|
}
|
||||||
|
|
||||||
private Class<?> loadClass0(String name, boolean resolve, boolean checkOther, boolean checkLibraries) throws ClassNotFoundException
|
private Class<?> loadClass0(String name, boolean resolve, boolean checkOther) throws ClassNotFoundException
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Class<?> result = super.loadClass( name, resolve );
|
return super.loadClass( name, resolve );
|
||||||
|
|
||||||
// SPIGOT-6749: Library classes will appear in the above, but we don't want to return them to other plugins
|
|
||||||
if ( checkOther || result.getClassLoader() == this )
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
} catch ( ClassNotFoundException ex )
|
} catch ( ClassNotFoundException ex )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( checkLibraries && libraryLoader != null )
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return libraryLoader.loadClass( name );
|
|
||||||
} catch ( ClassNotFoundException ex )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( checkOther )
|
if ( checkOther )
|
||||||
{
|
{
|
||||||
for ( PluginClassloader loader : allLoaders )
|
for ( PluginClassloader loader : allLoaders )
|
||||||
@@ -92,81 +53,16 @@ final class PluginClassloader extends URLClassLoader
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return loader.loadClass0( name, resolve, false, proxy.getPluginManager().isTransitiveDepend( desc, loader.desc ) );
|
return loader.loadClass0( name, resolve, false );
|
||||||
} catch ( ClassNotFoundException ex )
|
} catch ( ClassNotFoundException ex )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ClassNotFoundException( name );
|
throw new ClassNotFoundException( name );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Class<?> findClass(String name) throws ClassNotFoundException
|
|
||||||
{
|
|
||||||
String path = name.replace( '.', '/' ).concat( ".class" );
|
|
||||||
JarEntry entry = jar.getJarEntry( path );
|
|
||||||
|
|
||||||
if ( entry != null )
|
|
||||||
{
|
|
||||||
byte[] classBytes;
|
|
||||||
|
|
||||||
try ( InputStream is = jar.getInputStream( entry ) )
|
|
||||||
{
|
|
||||||
classBytes = ByteStreams.toByteArray( is );
|
|
||||||
} catch ( IOException ex )
|
|
||||||
{
|
|
||||||
throw new ClassNotFoundException( name, ex );
|
|
||||||
}
|
|
||||||
|
|
||||||
int dot = name.lastIndexOf( '.' );
|
|
||||||
if ( dot != -1 )
|
|
||||||
{
|
|
||||||
String pkgName = name.substring( 0, dot );
|
|
||||||
if ( getPackage( pkgName ) == null )
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if ( manifest != null )
|
|
||||||
{
|
|
||||||
definePackage( pkgName, manifest, url );
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
definePackage( pkgName, null, null, null, null, null, null, null );
|
|
||||||
}
|
|
||||||
} catch ( IllegalArgumentException ex )
|
|
||||||
{
|
|
||||||
if ( getPackage( pkgName ) == null )
|
|
||||||
{
|
|
||||||
throw new IllegalStateException( "Cannot find package " + pkgName );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CodeSigner[] signers = entry.getCodeSigners();
|
|
||||||
CodeSource source = new CodeSource( url, signers );
|
|
||||||
|
|
||||||
return defineClass( name, classBytes, 0, classBytes.length, source );
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.findClass( name );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() throws IOException
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
super.close();
|
|
||||||
} finally
|
|
||||||
{
|
|
||||||
jar.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void init(Plugin plugin)
|
void init(Plugin plugin)
|
||||||
{
|
{
|
||||||
Preconditions.checkArgument( plugin != null, "plugin" );
|
Preconditions.checkArgument( plugin != null, "plugin" );
|
||||||
|
@@ -2,8 +2,6 @@ package net.md_5.bungee.api.plugin;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -50,8 +48,4 @@ public class PluginDescription
|
|||||||
* Optional description.
|
* Optional description.
|
||||||
*/
|
*/
|
||||||
private String description = null;
|
private String description = null;
|
||||||
/**
|
|
||||||
* Optional libraries.
|
|
||||||
*/
|
|
||||||
private List<String> libraries = new LinkedList<>();
|
|
||||||
}
|
}
|
||||||
|
@@ -4,12 +4,10 @@ import com.google.common.base.Preconditions;
|
|||||||
import com.google.common.collect.ArrayListMultimap;
|
import com.google.common.collect.ArrayListMultimap;
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
import com.google.common.eventbus.Subscribe;
|
import com.google.common.eventbus.Subscribe;
|
||||||
import com.google.common.graph.GraphBuilder;
|
|
||||||
import com.google.common.graph.Graphs;
|
|
||||||
import com.google.common.graph.MutableGraph;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.net.URL;
|
||||||
import java.net.URLClassLoader;
|
import java.net.URLClassLoader;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -23,10 +21,6 @@ import java.util.Locale;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
import java.util.concurrent.locks.Lock;
|
|
||||||
import java.util.concurrent.locks.ReadWriteLock;
|
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|
||||||
import java.util.jar.JarEntry;
|
import java.util.jar.JarEntry;
|
||||||
import java.util.jar.JarFile;
|
import java.util.jar.JarFile;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@@ -37,7 +31,6 @@ import net.md_5.bungee.api.ProxyServer;
|
|||||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
import net.md_5.bungee.event.EventBus;
|
import net.md_5.bungee.event.EventBus;
|
||||||
import net.md_5.bungee.event.EventHandler;
|
import net.md_5.bungee.event.EventHandler;
|
||||||
import org.yaml.snakeyaml.LoaderOptions;
|
|
||||||
import org.yaml.snakeyaml.Yaml;
|
import org.yaml.snakeyaml.Yaml;
|
||||||
import org.yaml.snakeyaml.constructor.Constructor;
|
import org.yaml.snakeyaml.constructor.Constructor;
|
||||||
import org.yaml.snakeyaml.introspector.PropertyUtils;
|
import org.yaml.snakeyaml.introspector.PropertyUtils;
|
||||||
@@ -56,40 +49,24 @@ public final class PluginManager
|
|||||||
private final Yaml yaml;
|
private final Yaml yaml;
|
||||||
private final EventBus eventBus;
|
private final EventBus eventBus;
|
||||||
private final Map<String, Plugin> plugins = new LinkedHashMap<>();
|
private final Map<String, Plugin> plugins = new LinkedHashMap<>();
|
||||||
private final MutableGraph<String> dependencyGraph = GraphBuilder.directed().build();
|
|
||||||
private final LibraryLoader libraryLoader;
|
|
||||||
private final Map<String, Command> commandMap = new HashMap<>();
|
private final Map<String, Command> commandMap = new HashMap<>();
|
||||||
private Map<String, PluginDescription> toLoad = new HashMap<>();
|
private Map<String, PluginDescription> toLoad = new HashMap<>();
|
||||||
private final Multimap<Plugin, Command> commandsByPlugin = ArrayListMultimap.create();
|
private final Multimap<Plugin, Command> commandsByPlugin = ArrayListMultimap.create();
|
||||||
private final Multimap<Plugin, Listener> listenersByPlugin = ArrayListMultimap.create();
|
private final Multimap<Plugin, Listener> listenersByPlugin = ArrayListMultimap.create();
|
||||||
|
|
||||||
private final ReadWriteLock commandsLock = new ReentrantReadWriteLock();
|
|
||||||
private final Lock listenersLock = new ReentrantLock();
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public PluginManager(ProxyServer proxy)
|
public PluginManager(ProxyServer proxy)
|
||||||
{
|
{
|
||||||
this.proxy = proxy;
|
this.proxy = proxy;
|
||||||
|
|
||||||
// Ignore unknown entries in the plugin descriptions
|
// Ignore unknown entries in the plugin descriptions
|
||||||
Constructor yamlConstructor = new Constructor( new LoaderOptions() );
|
Constructor yamlConstructor = new Constructor();
|
||||||
PropertyUtils propertyUtils = yamlConstructor.getPropertyUtils();
|
PropertyUtils propertyUtils = yamlConstructor.getPropertyUtils();
|
||||||
propertyUtils.setSkipMissingProperties( true );
|
propertyUtils.setSkipMissingProperties( true );
|
||||||
yamlConstructor.setPropertyUtils( propertyUtils );
|
yamlConstructor.setPropertyUtils( propertyUtils );
|
||||||
yaml = new Yaml( yamlConstructor );
|
yaml = new Yaml( yamlConstructor );
|
||||||
|
|
||||||
eventBus = new EventBus( proxy.getLogger() );
|
eventBus = new EventBus( proxy.getLogger() );
|
||||||
|
|
||||||
LibraryLoader libraryLoader = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
libraryLoader = new LibraryLoader( proxy.getLogger() );
|
|
||||||
} catch ( NoClassDefFoundError ex )
|
|
||||||
{
|
|
||||||
// Provided depends were not added back
|
|
||||||
proxy.getLogger().warning( "Could not initialize LibraryLoader (missing dependencies?)" );
|
|
||||||
}
|
|
||||||
this.libraryLoader = libraryLoader;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -99,9 +76,6 @@ public final class PluginManager
|
|||||||
* @param command the command to register
|
* @param command the command to register
|
||||||
*/
|
*/
|
||||||
public void registerCommand(Plugin plugin, Command command)
|
public void registerCommand(Plugin plugin, Command command)
|
||||||
{
|
|
||||||
commandsLock.writeLock().lock();
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
commandMap.put( command.getName().toLowerCase( Locale.ROOT ), command );
|
commandMap.put( command.getName().toLowerCase( Locale.ROOT ), command );
|
||||||
for ( String alias : command.getAliases() )
|
for ( String alias : command.getAliases() )
|
||||||
@@ -109,10 +83,6 @@ public final class PluginManager
|
|||||||
commandMap.put( alias.toLowerCase( Locale.ROOT ), command );
|
commandMap.put( alias.toLowerCase( Locale.ROOT ), command );
|
||||||
}
|
}
|
||||||
commandsByPlugin.put( plugin, command );
|
commandsByPlugin.put( plugin, command );
|
||||||
} finally
|
|
||||||
{
|
|
||||||
commandsLock.writeLock().unlock();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -121,16 +91,9 @@ public final class PluginManager
|
|||||||
* @param command the command to unregister
|
* @param command the command to unregister
|
||||||
*/
|
*/
|
||||||
public void unregisterCommand(Command command)
|
public void unregisterCommand(Command command)
|
||||||
{
|
|
||||||
commandsLock.writeLock().lock();
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
while ( commandMap.values().remove( command ) );
|
while ( commandMap.values().remove( command ) );
|
||||||
commandsByPlugin.values().remove( command );
|
commandsByPlugin.values().remove( command );
|
||||||
} finally
|
|
||||||
{
|
|
||||||
commandsLock.writeLock().unlock();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -139,9 +102,6 @@ public final class PluginManager
|
|||||||
* @param plugin the plugin to register the commands of
|
* @param plugin the plugin to register the commands of
|
||||||
*/
|
*/
|
||||||
public void unregisterCommands(Plugin plugin)
|
public void unregisterCommands(Plugin plugin)
|
||||||
{
|
|
||||||
commandsLock.writeLock().lock();
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
for ( Iterator<Command> it = commandsByPlugin.get( plugin ).iterator(); it.hasNext(); )
|
for ( Iterator<Command> it = commandsByPlugin.get( plugin ).iterator(); it.hasNext(); )
|
||||||
{
|
{
|
||||||
@@ -149,10 +109,6 @@ public final class PluginManager
|
|||||||
while ( commandMap.values().remove( command ) );
|
while ( commandMap.values().remove( command ) );
|
||||||
it.remove();
|
it.remove();
|
||||||
}
|
}
|
||||||
} finally
|
|
||||||
{
|
|
||||||
commandsLock.writeLock().unlock();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Command getCommandIfEnabled(String commandName, CommandSender sender)
|
private Command getCommandIfEnabled(String commandName, CommandSender sender)
|
||||||
@@ -165,14 +121,7 @@ public final class PluginManager
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
commandsLock.readLock().lock();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return commandMap.get( commandLower );
|
return commandMap.get( commandLower );
|
||||||
} finally
|
|
||||||
{
|
|
||||||
commandsLock.readLock().unlock();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -360,7 +309,6 @@ public final class PluginManager
|
|||||||
status = false;
|
status = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencyGraph.putEdge( plugin.getName(), dependName );
|
|
||||||
if ( !status )
|
if ( !status )
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
@@ -372,7 +320,10 @@ public final class PluginManager
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
URLClassLoader loader = new PluginClassloader( proxy, plugin, plugin.getFile(), ( libraryLoader != null ) ? libraryLoader.createLoader( plugin ) : null );
|
URLClassLoader loader = new PluginClassloader( proxy, plugin, new URL[]
|
||||||
|
{
|
||||||
|
plugin.getFile().toURI().toURL()
|
||||||
|
} );
|
||||||
Class<?> main = loader.loadClass( plugin.getMain() );
|
Class<?> main = loader.loadClass( plugin.getMain() );
|
||||||
Plugin clazz = (Plugin) main.getDeclaredConstructor().newInstance();
|
Plugin clazz = (Plugin) main.getDeclaredConstructor().newInstance();
|
||||||
|
|
||||||
@@ -384,7 +335,7 @@ public final class PluginManager
|
|||||||
} );
|
} );
|
||||||
} catch ( Throwable t )
|
} catch ( Throwable t )
|
||||||
{
|
{
|
||||||
proxy.getLogger().log( Level.WARNING, "Error loading plugin " + plugin.getName(), t );
|
proxy.getLogger().log( Level.WARNING, "Error enabling plugin " + plugin.getName(), t );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -468,9 +419,6 @@ public final class PluginManager
|
|||||||
* @param listener the listener to register events for
|
* @param listener the listener to register events for
|
||||||
*/
|
*/
|
||||||
public void registerListener(Plugin plugin, Listener listener)
|
public void registerListener(Plugin plugin, Listener listener)
|
||||||
{
|
|
||||||
listenersLock.lock();
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
for ( Method method : listener.getClass().getDeclaredMethods() )
|
for ( Method method : listener.getClass().getDeclaredMethods() )
|
||||||
{
|
{
|
||||||
@@ -479,10 +427,6 @@ public final class PluginManager
|
|||||||
}
|
}
|
||||||
eventBus.register( listener );
|
eventBus.register( listener );
|
||||||
listenersByPlugin.put( plugin, listener );
|
listenersByPlugin.put( plugin, listener );
|
||||||
} finally
|
|
||||||
{
|
|
||||||
listenersLock.unlock();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -491,16 +435,9 @@ public final class PluginManager
|
|||||||
* @param listener the listener to unregister
|
* @param listener the listener to unregister
|
||||||
*/
|
*/
|
||||||
public void unregisterListener(Listener listener)
|
public void unregisterListener(Listener listener)
|
||||||
{
|
|
||||||
listenersLock.lock();
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
eventBus.unregister( listener );
|
eventBus.unregister( listener );
|
||||||
listenersByPlugin.values().remove( listener );
|
listenersByPlugin.values().remove( listener );
|
||||||
} finally
|
|
||||||
{
|
|
||||||
listenersLock.unlock();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -509,19 +446,12 @@ public final class PluginManager
|
|||||||
* @param plugin target plugin
|
* @param plugin target plugin
|
||||||
*/
|
*/
|
||||||
public void unregisterListeners(Plugin plugin)
|
public void unregisterListeners(Plugin plugin)
|
||||||
{
|
|
||||||
listenersLock.lock();
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
for ( Iterator<Listener> it = listenersByPlugin.get( plugin ).iterator(); it.hasNext(); )
|
for ( Iterator<Listener> it = listenersByPlugin.get( plugin ).iterator(); it.hasNext(); )
|
||||||
{
|
{
|
||||||
eventBus.unregister( it.next() );
|
eventBus.unregister( it.next() );
|
||||||
it.remove();
|
it.remove();
|
||||||
}
|
}
|
||||||
} finally
|
|
||||||
{
|
|
||||||
listenersLock.unlock();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -530,29 +460,7 @@ public final class PluginManager
|
|||||||
* @return commands
|
* @return commands
|
||||||
*/
|
*/
|
||||||
public Collection<Map.Entry<String, Command>> getCommands()
|
public Collection<Map.Entry<String, Command>> getCommands()
|
||||||
{
|
|
||||||
commandsLock.readLock().lock();
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
return Collections.unmodifiableCollection( commandMap.entrySet() );
|
return Collections.unmodifiableCollection( commandMap.entrySet() );
|
||||||
} finally
|
|
||||||
{
|
|
||||||
commandsLock.readLock().unlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isTransitiveDepend(PluginDescription plugin, PluginDescription depend)
|
|
||||||
{
|
|
||||||
Preconditions.checkArgument( plugin != null, "plugin" );
|
|
||||||
Preconditions.checkArgument( depend != null, "depend" );
|
|
||||||
|
|
||||||
if ( dependencyGraph.nodes().contains( plugin.getName() ) )
|
|
||||||
{
|
|
||||||
if ( Graphs.reachableNodes( dependencyGraph, plugin.getName() ).contains( depend.getName() ) )
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,37 +1,22 @@
|
|||||||
package net.md_5.bungee.util;
|
package net.md_5.bungee.util;
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.Hash;
|
import gnu.trove.strategy.HashingStrategy;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
class CaseInsensitiveHashingStrategy implements Hash.Strategy<String>
|
class CaseInsensitiveHashingStrategy implements HashingStrategy
|
||||||
{
|
{
|
||||||
|
|
||||||
static final CaseInsensitiveHashingStrategy INSTANCE = new CaseInsensitiveHashingStrategy();
|
static final CaseInsensitiveHashingStrategy INSTANCE = new CaseInsensitiveHashingStrategy();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode(String object)
|
public int computeHashCode(Object object)
|
||||||
{
|
{
|
||||||
if ( object == null )
|
return ( (String) object ).toLowerCase( Locale.ROOT ).hashCode();
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return object.toLowerCase( Locale.ROOT ).hashCode();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(String o1, String o2)
|
public boolean equals(Object o1, Object o2)
|
||||||
{
|
{
|
||||||
if ( o1 == o2 )
|
return o1.equals( o2 ) || ( o1 instanceof String && o2 instanceof String && ( (String) o1 ).toLowerCase( Locale.ROOT ).equals( ( (String) o2 ).toLowerCase( Locale.ROOT ) ) );
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( o1 == null || o2 == null )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return o1.equals( o2 ) || o1.toLowerCase( Locale.ROOT ).equals( o2.toLowerCase( Locale.ROOT ) );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
package net.md_5.bungee.util;
|
package net.md_5.bungee.util;
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap;
|
import gnu.trove.map.hash.TCustomHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class CaseInsensitiveMap<V> extends Object2ObjectOpenCustomHashMap<String, V>
|
public class CaseInsensitiveMap<V> extends TCustomHashMap<String, V>
|
||||||
{
|
{
|
||||||
|
|
||||||
public CaseInsensitiveMap()
|
public CaseInsensitiveMap()
|
||||||
@@ -13,6 +13,6 @@ public class CaseInsensitiveMap<V> extends Object2ObjectOpenCustomHashMap<String
|
|||||||
|
|
||||||
public CaseInsensitiveMap(Map<? extends String, ? extends V> map)
|
public CaseInsensitiveMap(Map<? extends String, ? extends V> map)
|
||||||
{
|
{
|
||||||
super( map, CaseInsensitiveHashingStrategy.INSTANCE );
|
super( CaseInsensitiveHashingStrategy.INSTANCE, map );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
package net.md_5.bungee.util;
|
package net.md_5.bungee.util;
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectOpenCustomHashSet;
|
import gnu.trove.set.hash.TCustomHashSet;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
public class CaseInsensitiveSet extends ObjectOpenCustomHashSet<String>
|
public class CaseInsensitiveSet extends TCustomHashSet<String>
|
||||||
{
|
{
|
||||||
|
|
||||||
public CaseInsensitiveSet()
|
public CaseInsensitiveSet()
|
||||||
@@ -13,6 +13,6 @@ public class CaseInsensitiveSet extends ObjectOpenCustomHashSet<String>
|
|||||||
|
|
||||||
public CaseInsensitiveSet(Collection<? extends String> collection)
|
public CaseInsensitiveSet(Collection<? extends String> collection)
|
||||||
{
|
{
|
||||||
super( collection, CaseInsensitiveHashingStrategy.INSTANCE );
|
super( CaseInsensitiveHashingStrategy.INSTANCE, collection );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,13 +1,12 @@
|
|||||||
package net.md_5.bungee.api;
|
package net.md_5.bungee.api;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import net.md_5.bungee.api.config.ServerInfo;
|
import net.md_5.bungee.api.config.ServerInfo;
|
||||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
import net.md_5.bungee.api.event.ServerConnectEvent;
|
import net.md_5.bungee.api.event.ServerConnectEvent;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class ServerConnectRequestTest
|
public class ServerConnectRequestTest
|
||||||
{
|
{
|
||||||
@@ -79,15 +78,15 @@ public class ServerConnectRequestTest
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@Test
|
@Test(expected = NullPointerException.class)
|
||||||
public void testNullTarget()
|
public void testNullTarget()
|
||||||
{
|
{
|
||||||
assertThrows( NullPointerException.class, () -> ServerConnectRequest.builder().target( null ).reason( ServerConnectEvent.Reason.JOIN_PROXY ).build() );
|
ServerConnectRequest.builder().target( null ).reason( ServerConnectEvent.Reason.JOIN_PROXY ).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(expected = NullPointerException.class)
|
||||||
public void testNullReason()
|
public void testNullReason()
|
||||||
{
|
{
|
||||||
assertThrows( NullPointerException.class, () -> ServerConnectRequest.builder().target( DUMMY_INFO ).reason( null ).build() );
|
ServerConnectRequest.builder().target( DUMMY_INFO ).reason( null ).build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,38 +1,63 @@
|
|||||||
package net.md_5.bungee.util;
|
package net.md_5.bungee.util;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
import io.netty.channel.unix.DomainSocketAddress;
|
import io.netty.channel.unix.DomainSocketAddress;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.util.stream.Stream;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import net.md_5.bungee.Util;
|
import net.md_5.bungee.Util;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
import org.junit.Assert;
|
||||||
import org.junit.jupiter.params.provider.Arguments;
|
import org.junit.Test;
|
||||||
import org.junit.jupiter.params.provider.MethodSource;
|
import org.junit.runner.RunWith;
|
||||||
|
import org.junit.runners.Parameterized;
|
||||||
|
import org.junit.runners.Parameterized.Parameters;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
|
@RunWith(Parameterized.class)
|
||||||
public class AddressParseTest
|
public class AddressParseTest
|
||||||
{
|
{
|
||||||
|
|
||||||
public static Stream<Arguments> data()
|
@Parameters
|
||||||
|
public static Collection<Object[]> data()
|
||||||
{
|
{
|
||||||
return Stream.of(
|
return Arrays.asList( new Object[][]
|
||||||
Arguments.of( "127.0.0.1", "127.0.0.1", Util.DEFAULT_PORT ),
|
{
|
||||||
Arguments.of( "127.0.0.1:1337", "127.0.0.1", 1337 ),
|
{
|
||||||
Arguments.of( "[::1]", "0:0:0:0:0:0:0:1", Util.DEFAULT_PORT ),
|
"127.0.0.1", "127.0.0.1", Util.DEFAULT_PORT
|
||||||
Arguments.of( "[0:0:0:0::1]", "0:0:0:0:0:0:0:1", Util.DEFAULT_PORT ),
|
},
|
||||||
Arguments.of( "[0:0:0:0:0:0:0:1]", "0:0:0:0:0:0:0:1", Util.DEFAULT_PORT ),
|
{
|
||||||
Arguments.of( "[::1]:1337", "0:0:0:0:0:0:0:1", 1337 ),
|
"127.0.0.1:1337", "127.0.0.1", 1337
|
||||||
Arguments.of( "[0:0:0:0::1]:1337", "0:0:0:0:0:0:0:1", 1337 ),
|
},
|
||||||
Arguments.of( "[0:0:0:0:0:0:0:1]:1337", "0:0:0:0:0:0:0:1", 1337 ),
|
{
|
||||||
Arguments.of( "unix:///var/run/bungee.sock", "/var/run/bungee.sock", -1 )
|
"[::1]", "0:0:0:0:0:0:0:1", Util.DEFAULT_PORT
|
||||||
);
|
},
|
||||||
|
{
|
||||||
|
"[0:0:0:0::1]", "0:0:0:0:0:0:0:1", Util.DEFAULT_PORT
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"[0:0:0:0:0:0:0:1]", "0:0:0:0:0:0:0:1", Util.DEFAULT_PORT
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"[::1]:1337", "0:0:0:0:0:0:0:1", 1337
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"[0:0:0:0::1]:1337", "0:0:0:0:0:0:0:1", 1337
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"[0:0:0:0:0:0:0:1]:1337", "0:0:0:0:0:0:0:1", 1337
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"unix:///var/run/bungee.sock", "/var/run/bungee.sock", -1
|
||||||
}
|
}
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
private final String line;
|
||||||
|
private final String host;
|
||||||
|
private final int port;
|
||||||
|
|
||||||
@ParameterizedTest
|
@Test
|
||||||
@MethodSource("data")
|
public void test()
|
||||||
public void test(String line, String host, int port)
|
|
||||||
{
|
{
|
||||||
SocketAddress parsed = Util.getAddr( line );
|
SocketAddress parsed = Util.getAddr( line );
|
||||||
|
|
||||||
@@ -40,14 +65,14 @@ public class AddressParseTest
|
|||||||
{
|
{
|
||||||
InetSocketAddress tcp = (InetSocketAddress) parsed;
|
InetSocketAddress tcp = (InetSocketAddress) parsed;
|
||||||
|
|
||||||
assertEquals( host, tcp.getHostString() );
|
Assert.assertEquals( host, tcp.getHostString() );
|
||||||
assertEquals( port, tcp.getPort() );
|
Assert.assertEquals( port, tcp.getPort() );
|
||||||
} else if ( parsed instanceof DomainSocketAddress )
|
} else if ( parsed instanceof DomainSocketAddress )
|
||||||
{
|
{
|
||||||
DomainSocketAddress unix = (DomainSocketAddress) parsed;
|
DomainSocketAddress unix = (DomainSocketAddress) parsed;
|
||||||
|
|
||||||
assertEquals( host, unix.path() );
|
Assert.assertEquals( host, unix.path() );
|
||||||
assertEquals( -1, port );
|
Assert.assertEquals( -1, port );
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
throw new AssertionError( "Unknown socket " + parsed );
|
throw new AssertionError( "Unknown socket " + parsed );
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
package net.md_5.bungee.util;
|
package net.md_5.bungee.util;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import org.junit.Assert;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class CaseInsensitiveTest
|
public class CaseInsensitiveTest
|
||||||
{
|
{
|
||||||
@@ -13,12 +13,12 @@ public class CaseInsensitiveTest
|
|||||||
CaseInsensitiveMap<Object> map = new CaseInsensitiveMap<>();
|
CaseInsensitiveMap<Object> map = new CaseInsensitiveMap<>();
|
||||||
|
|
||||||
map.put( "FOO", obj );
|
map.put( "FOO", obj );
|
||||||
assertTrue( map.containsKey( "foo" ) ); // Assert that contains is case insensitive
|
Assert.assertTrue( map.contains( "foo" ) ); // Assert that contains is case insensitive
|
||||||
assertTrue( map.entrySet().iterator().next().getKey().equals( "FOO" ) ); // Assert that case is preserved
|
Assert.assertTrue( map.entrySet().iterator().next().getKey().equals( "FOO" ) ); // Assert that case is preserved
|
||||||
|
|
||||||
// Assert that remove is case insensitive
|
// Assert that remove is case insensitive
|
||||||
map.remove( "FoO" );
|
map.remove( "FoO" );
|
||||||
assertFalse( map.containsKey( "foo" ) );
|
Assert.assertFalse( map.contains( "foo" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -27,8 +27,8 @@ public class CaseInsensitiveTest
|
|||||||
CaseInsensitiveSet set = new CaseInsensitiveSet();
|
CaseInsensitiveSet set = new CaseInsensitiveSet();
|
||||||
|
|
||||||
set.add( "FOO" );
|
set.add( "FOO" );
|
||||||
assertTrue( set.contains( "foo" ) ); // Assert that contains is case insensitive
|
Assert.assertTrue( set.contains( "foo" ) ); // Assert that contains is case insensitive
|
||||||
set.remove( "FoO" );
|
set.remove( "FoO" );
|
||||||
assertFalse( set.contains( "foo" ) ); // Assert that remove is case insensitive
|
Assert.assertFalse( set.contains( "foo" ) ); // Assert that remove is case insensitive
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
package net.md_5.bungee.util;
|
package net.md_5.bungee.util;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import net.md_5.bungee.Util;
|
import net.md_5.bungee.Util;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
public class UUIDTest
|
public class UUIDTest
|
||||||
{
|
{
|
||||||
@@ -13,7 +13,7 @@ public class UUIDTest
|
|||||||
{
|
{
|
||||||
UUID uuid = UUID.fromString( "af74a02d-19cb-445b-b07f-6866a861f783" );
|
UUID uuid = UUID.fromString( "af74a02d-19cb-445b-b07f-6866a861f783" );
|
||||||
UUID uuid1 = Util.getUUID( "af74a02d19cb445bb07f6866a861f783" );
|
UUID uuid1 = Util.getUUID( "af74a02d19cb445bb07f6866a861f783" );
|
||||||
assertEquals( uuid, uuid1 );
|
Assert.assertEquals( uuid, uuid1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -23,7 +23,7 @@ public class UUIDTest
|
|||||||
{
|
{
|
||||||
UUID expected = UUID.randomUUID();
|
UUID expected = UUID.randomUUID();
|
||||||
UUID actual = Util.getUUID( expected.toString().replace( "-", "" ) );
|
UUID actual = Util.getUUID( expected.toString().replace( "-", "" ) );
|
||||||
assertEquals( expected, actual, "Could not parse UUID " + expected );
|
Assert.assertEquals( "Could not parse UUID " + expected, expected, actual );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,13 +6,13 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>net.md-5</groupId>
|
<groupId>net.md-5</groupId>
|
||||||
<artifactId>bungeecord-parent</artifactId>
|
<artifactId>bungeecord-parent</artifactId>
|
||||||
<version>1.21-R0.4-SNAPSHOT</version>
|
<version>1.16-R0.4-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<groupId>net.md-5</groupId>
|
<groupId>net.md-5</groupId>
|
||||||
<artifactId>bungeecord-bootstrap</artifactId>
|
<artifactId>bungeecord-bootstrap</artifactId>
|
||||||
<version>1.21-R0.4-SNAPSHOT</version>
|
<version>1.16-R0.4-SNAPSHOT</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>BungeeCord-Bootstrap</name>
|
<name>BungeeCord-Bootstrap</name>
|
||||||
@@ -41,14 +41,13 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
<version>3.4.1</version>
|
<version>3.2.0</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<archive>
|
<archive>
|
||||||
<manifestEntries>
|
<manifestEntries>
|
||||||
<Main-Class>net.md_5.bungee.Bootstrap</Main-Class>
|
<Main-Class>net.md_5.bungee.Bootstrap</Main-Class>
|
||||||
<Implementation-Version>${describe}</Implementation-Version>
|
<Implementation-Version>${describe}</Implementation-Version>
|
||||||
<Specification-Version>${maven.build.timestamp}</Specification-Version>
|
<Specification-Version>${maven.build.timestamp}</Specification-Version>
|
||||||
<Enable-Native-Access>ALL-UNNAMED</Enable-Native-Access>
|
|
||||||
</manifestEntries>
|
</manifestEntries>
|
||||||
</archive>
|
</archive>
|
||||||
</configuration>
|
</configuration>
|
||||||
@@ -56,7 +55,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
<version>3.5.3</version>
|
<version>3.2.3</version>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<phase>package</phase>
|
<phase>package</phase>
|
||||||
@@ -80,34 +79,4 @@
|
|||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
<profiles>
|
|
||||||
<profile>
|
|
||||||
<id>jdk-9-release</id>
|
|
||||||
<activation>
|
|
||||||
<jdk>[9,)</jdk>
|
|
||||||
</activation>
|
|
||||||
<properties>
|
|
||||||
<maven.compiler.release>6</maven.compiler.release>
|
|
||||||
</properties>
|
|
||||||
</profile>
|
|
||||||
<profile>
|
|
||||||
<id>jdk-12-release</id>
|
|
||||||
<activation>
|
|
||||||
<jdk>[12,)</jdk>
|
|
||||||
</activation>
|
|
||||||
<properties>
|
|
||||||
<maven.compiler.release>7</maven.compiler.release>
|
|
||||||
</properties>
|
|
||||||
</profile>
|
|
||||||
<profile>
|
|
||||||
<id>jdk-20-release</id>
|
|
||||||
<activation>
|
|
||||||
<jdk>[20,)</jdk>
|
|
||||||
</activation>
|
|
||||||
<properties>
|
|
||||||
<maven.compiler.release>8</maven.compiler.release>
|
|
||||||
</properties>
|
|
||||||
</profile>
|
|
||||||
</profiles>
|
|
||||||
</project>
|
</project>
|
||||||
|
@@ -6,13 +6,13 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>net.md-5</groupId>
|
<groupId>net.md-5</groupId>
|
||||||
<artifactId>bungeecord-parent</artifactId>
|
<artifactId>bungeecord-parent</artifactId>
|
||||||
<version>1.21-R0.4-SNAPSHOT</version>
|
<version>1.16-R0.4-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<groupId>net.md-5</groupId>
|
<groupId>net.md-5</groupId>
|
||||||
<artifactId>bungeecord-chat</artifactId>
|
<artifactId>bungeecord-chat</artifactId>
|
||||||
<version>1.21-R0.4-SNAPSHOT</version>
|
<version>1.16-R0.4-SNAPSHOT</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>BungeeCord-Chat</name>
|
<name>BungeeCord-Chat</name>
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.code.gson</groupId>
|
<groupId>com.google.code.gson</groupId>
|
||||||
<artifactId>gson</artifactId>
|
<artifactId>gson</artifactId>
|
||||||
<version>2.11.0</version>
|
<version>2.8.0</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
@@ -244,7 +244,7 @@ public final class ChatColor
|
|||||||
public static ChatColor of(String string)
|
public static ChatColor of(String string)
|
||||||
{
|
{
|
||||||
Preconditions.checkArgument( string != null, "string cannot be null" );
|
Preconditions.checkArgument( string != null, "string cannot be null" );
|
||||||
if ( string.length() == 7 && string.charAt( 0 ) == '#' )
|
if ( string.startsWith( "#" ) && string.length() == 7 )
|
||||||
{
|
{
|
||||||
int rgb;
|
int rgb;
|
||||||
try
|
try
|
||||||
@@ -300,7 +300,7 @@ public final class ChatColor
|
|||||||
@Deprecated
|
@Deprecated
|
||||||
public static ChatColor[] values()
|
public static ChatColor[] values()
|
||||||
{
|
{
|
||||||
return BY_CHAR.values().toArray( new ChatColor[ 0 ] );
|
return BY_CHAR.values().toArray( new ChatColor[ BY_CHAR.values().size() ] );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -1,10 +1,8 @@
|
|||||||
package net.md_5.bungee.api.chat;
|
package net.md_5.bungee.api.chat;
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
@@ -22,10 +20,38 @@ public abstract class BaseComponent
|
|||||||
BaseComponent parent;
|
BaseComponent parent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The component's style.
|
* The color of this component and any child components (unless overridden)
|
||||||
*/
|
*/
|
||||||
@Getter
|
private ChatColor color;
|
||||||
private ComponentStyle style = new ComponentStyle();
|
/**
|
||||||
|
* 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;
|
||||||
/**
|
/**
|
||||||
* The text to insert into the chat when this component (and child
|
* The text to insert into the chat when this component (and child
|
||||||
* components) are clicked while pressing the shift key
|
* components) are clicked while pressing the shift key
|
||||||
@@ -52,12 +78,6 @@ public abstract class BaseComponent
|
|||||||
@Getter
|
@Getter
|
||||||
private HoverEvent hoverEvent;
|
private HoverEvent hoverEvent;
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether this component rejects previous formatting
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private transient boolean reset;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default constructor.
|
* Default constructor.
|
||||||
*
|
*
|
||||||
@@ -127,35 +147,31 @@ public abstract class BaseComponent
|
|||||||
}
|
}
|
||||||
if ( retention == FormatRetention.FORMATTING || retention == FormatRetention.ALL )
|
if ( retention == FormatRetention.FORMATTING || retention == FormatRetention.ALL )
|
||||||
{
|
{
|
||||||
if ( replace || !style.hasColor() )
|
if ( replace || color == null )
|
||||||
{
|
{
|
||||||
setColor( component.getColorRaw() );
|
setColor( component.getColorRaw() );
|
||||||
}
|
}
|
||||||
if ( replace || !style.hasShadowColor() )
|
if ( replace || font == null )
|
||||||
{
|
|
||||||
setShadowColor( component.getShadowColorRaw() );
|
|
||||||
}
|
|
||||||
if ( replace || !style.hasFont() )
|
|
||||||
{
|
{
|
||||||
setFont( component.getFontRaw() );
|
setFont( component.getFontRaw() );
|
||||||
}
|
}
|
||||||
if ( replace || style.isBoldRaw() == null )
|
if ( replace || bold == null )
|
||||||
{
|
{
|
||||||
setBold( component.isBoldRaw() );
|
setBold( component.isBoldRaw() );
|
||||||
}
|
}
|
||||||
if ( replace || style.isItalicRaw() == null )
|
if ( replace || italic == null )
|
||||||
{
|
{
|
||||||
setItalic( component.isItalicRaw() );
|
setItalic( component.isItalicRaw() );
|
||||||
}
|
}
|
||||||
if ( replace || style.isUnderlinedRaw() == null )
|
if ( replace || underlined == null )
|
||||||
{
|
{
|
||||||
setUnderlined( component.isUnderlinedRaw() );
|
setUnderlined( component.isUnderlinedRaw() );
|
||||||
}
|
}
|
||||||
if ( replace || style.isStrikethroughRaw() == null )
|
if ( replace || strikethrough == null )
|
||||||
{
|
{
|
||||||
setStrikethrough( component.isStrikethroughRaw() );
|
setStrikethrough( component.isStrikethroughRaw() );
|
||||||
}
|
}
|
||||||
if ( replace || style.isObfuscatedRaw() == null )
|
if ( replace || obfuscated == null )
|
||||||
{
|
{
|
||||||
setObfuscated( component.isObfuscatedRaw() );
|
setObfuscated( component.isObfuscatedRaw() );
|
||||||
}
|
}
|
||||||
@@ -181,7 +197,6 @@ public abstract class BaseComponent
|
|||||||
if ( retention == FormatRetention.EVENTS || retention == FormatRetention.NONE )
|
if ( retention == FormatRetention.EVENTS || retention == FormatRetention.NONE )
|
||||||
{
|
{
|
||||||
setColor( null );
|
setColor( null );
|
||||||
setShadowColor( null );
|
|
||||||
setBold( null );
|
setBold( null );
|
||||||
setItalic( null );
|
setItalic( null );
|
||||||
setUnderlined( null );
|
setUnderlined( null );
|
||||||
@@ -245,32 +260,6 @@ public abstract class BaseComponent
|
|||||||
return builder.toString();
|
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.
|
|
||||||
* <p>
|
|
||||||
* <b>Warning: This should be a color, not formatting code (ie,
|
|
||||||
* {@link ChatColor#color} should not be null).</b>
|
|
||||||
*
|
|
||||||
* @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
|
* 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}
|
* component doesn't have one. {@link net.md_5.bungee.api.ChatColor#WHITE}
|
||||||
@@ -280,7 +269,7 @@ public abstract class BaseComponent
|
|||||||
*/
|
*/
|
||||||
public ChatColor getColor()
|
public ChatColor getColor()
|
||||||
{
|
{
|
||||||
if ( !style.hasColor() )
|
if ( color == null )
|
||||||
{
|
{
|
||||||
if ( parent == null )
|
if ( parent == null )
|
||||||
{
|
{
|
||||||
@@ -288,7 +277,7 @@ public abstract class BaseComponent
|
|||||||
}
|
}
|
||||||
return parent.getColor();
|
return parent.getColor();
|
||||||
}
|
}
|
||||||
return style.getColor();
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -299,57 +288,7 @@ public abstract class BaseComponent
|
|||||||
*/
|
*/
|
||||||
public ChatColor getColorRaw()
|
public ChatColor getColorRaw()
|
||||||
{
|
{
|
||||||
return style.getColor();
|
return color;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set this component's shadow color.
|
|
||||||
*
|
|
||||||
* @param color the component shadow color, or null to use the default
|
|
||||||
*/
|
|
||||||
public void setShadowColor(Color color)
|
|
||||||
{
|
|
||||||
this.style.setShadowColor( color );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the shadow color of this component. This uses the parent's shadow color if this
|
|
||||||
* component doesn't have one. null is returned if no shadow color is found.
|
|
||||||
*
|
|
||||||
* @return the shadow color of this component
|
|
||||||
*/
|
|
||||||
public Color getShadowColor()
|
|
||||||
{
|
|
||||||
if ( !style.hasShadowColor() )
|
|
||||||
{
|
|
||||||
if ( parent == null )
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return parent.getShadowColor();
|
|
||||||
}
|
|
||||||
return style.getShadowColor();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the shadow color of this component without checking the parents
|
|
||||||
* shadow color. May return null
|
|
||||||
*
|
|
||||||
* @return the shadow color of this component
|
|
||||||
*/
|
|
||||||
public Color getShadowColorRaw()
|
|
||||||
{
|
|
||||||
return style.getShadowColor();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -360,7 +299,7 @@ public abstract class BaseComponent
|
|||||||
*/
|
*/
|
||||||
public String getFont()
|
public String getFont()
|
||||||
{
|
{
|
||||||
if ( !style.hasFont() )
|
if ( font == null )
|
||||||
{
|
{
|
||||||
if ( parent == null )
|
if ( parent == null )
|
||||||
{
|
{
|
||||||
@@ -368,7 +307,7 @@ public abstract class BaseComponent
|
|||||||
}
|
}
|
||||||
return parent.getFont();
|
return parent.getFont();
|
||||||
}
|
}
|
||||||
return style.getFont();
|
return font;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -379,17 +318,7 @@ public abstract class BaseComponent
|
|||||||
*/
|
*/
|
||||||
public String getFontRaw()
|
public String getFontRaw()
|
||||||
{
|
{
|
||||||
return style.getFont();
|
return font;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -401,11 +330,11 @@ public abstract class BaseComponent
|
|||||||
*/
|
*/
|
||||||
public boolean isBold()
|
public boolean isBold()
|
||||||
{
|
{
|
||||||
if ( style.isBoldRaw() == null )
|
if ( bold == null )
|
||||||
{
|
{
|
||||||
return parent != null && parent.isBold();
|
return parent != null && parent.isBold();
|
||||||
}
|
}
|
||||||
return style.isBold();
|
return bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -416,17 +345,7 @@ public abstract class BaseComponent
|
|||||||
*/
|
*/
|
||||||
public Boolean isBoldRaw()
|
public Boolean isBoldRaw()
|
||||||
{
|
{
|
||||||
return style.isBoldRaw();
|
return bold;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -438,11 +357,11 @@ public abstract class BaseComponent
|
|||||||
*/
|
*/
|
||||||
public boolean isItalic()
|
public boolean isItalic()
|
||||||
{
|
{
|
||||||
if ( style.isItalicRaw() == null )
|
if ( italic == null )
|
||||||
{
|
{
|
||||||
return parent != null && parent.isItalic();
|
return parent != null && parent.isItalic();
|
||||||
}
|
}
|
||||||
return style.isItalic();
|
return italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -453,17 +372,7 @@ public abstract class BaseComponent
|
|||||||
*/
|
*/
|
||||||
public Boolean isItalicRaw()
|
public Boolean isItalicRaw()
|
||||||
{
|
{
|
||||||
return style.isItalicRaw();
|
return italic;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -475,11 +384,11 @@ public abstract class BaseComponent
|
|||||||
*/
|
*/
|
||||||
public boolean isUnderlined()
|
public boolean isUnderlined()
|
||||||
{
|
{
|
||||||
if ( style.isUnderlinedRaw() == null )
|
if ( underlined == null )
|
||||||
{
|
{
|
||||||
return parent != null && parent.isUnderlined();
|
return parent != null && parent.isUnderlined();
|
||||||
}
|
}
|
||||||
return style.isUnderlined();
|
return underlined;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -490,18 +399,7 @@ public abstract class BaseComponent
|
|||||||
*/
|
*/
|
||||||
public Boolean isUnderlinedRaw()
|
public Boolean isUnderlinedRaw()
|
||||||
{
|
{
|
||||||
return style.isUnderlinedRaw();
|
return underlined;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -513,11 +411,11 @@ public abstract class BaseComponent
|
|||||||
*/
|
*/
|
||||||
public boolean isStrikethrough()
|
public boolean isStrikethrough()
|
||||||
{
|
{
|
||||||
if ( style.isStrikethroughRaw() == null )
|
if ( strikethrough == null )
|
||||||
{
|
{
|
||||||
return parent != null && parent.isStrikethrough();
|
return parent != null && parent.isStrikethrough();
|
||||||
}
|
}
|
||||||
return style.isStrikethrough();
|
return strikethrough;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -528,17 +426,7 @@ public abstract class BaseComponent
|
|||||||
*/
|
*/
|
||||||
public Boolean isStrikethroughRaw()
|
public Boolean isStrikethroughRaw()
|
||||||
{
|
{
|
||||||
return style.isStrikethroughRaw();
|
return strikethrough;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -550,11 +438,11 @@ public abstract class BaseComponent
|
|||||||
*/
|
*/
|
||||||
public boolean isObfuscated()
|
public boolean isObfuscated()
|
||||||
{
|
{
|
||||||
if ( style.isObfuscatedRaw() == null )
|
if ( obfuscated == null )
|
||||||
{
|
{
|
||||||
return parent != null && parent.isObfuscated();
|
return parent != null && parent.isObfuscated();
|
||||||
}
|
}
|
||||||
return style.isObfuscated();
|
return obfuscated;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -565,52 +453,7 @@ public abstract class BaseComponent
|
|||||||
*/
|
*/
|
||||||
public Boolean isObfuscatedRaw()
|
public Boolean isObfuscatedRaw()
|
||||||
{
|
{
|
||||||
return style.isObfuscatedRaw();
|
return obfuscated;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.hasShadowColor() )
|
|
||||||
{
|
|
||||||
setShadowColor( style.getShadowColor() );
|
|
||||||
}
|
|
||||||
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)
|
public void setExtra(List<BaseComponent> components)
|
||||||
@@ -649,16 +492,6 @@ public abstract class BaseComponent
|
|||||||
extra.add( component );
|
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
|
* Returns whether the component has any formatting or events applied to it
|
||||||
*
|
*
|
||||||
@@ -666,8 +499,10 @@ public abstract class BaseComponent
|
|||||||
*/
|
*/
|
||||||
public boolean hasFormatting()
|
public boolean hasFormatting()
|
||||||
{
|
{
|
||||||
return hasStyle() || insertion != null
|
return color != null || font != null || bold != null
|
||||||
|| hoverEvent != null || clickEvent != null;
|
|| italic != null || underlined != null
|
||||||
|
|| strikethrough != null || obfuscated != null
|
||||||
|
|| insertion != null || hoverEvent != null || clickEvent != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -678,11 +513,11 @@ public abstract class BaseComponent
|
|||||||
public String toPlainText()
|
public String toPlainText()
|
||||||
{
|
{
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
toPlainText( new LimitedStringVisitor( builder, Short.MAX_VALUE ) );
|
toPlainText( builder );
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
void toPlainText(StringVisitor builder)
|
void toPlainText(StringBuilder builder)
|
||||||
{
|
{
|
||||||
if ( extra != null )
|
if ( extra != null )
|
||||||
{
|
{
|
||||||
@@ -702,11 +537,11 @@ public abstract class BaseComponent
|
|||||||
public String toLegacyText()
|
public String toLegacyText()
|
||||||
{
|
{
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
toLegacyText( new LimitedStringVisitor( builder, Short.MAX_VALUE ) );
|
toLegacyText( builder );
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
void toLegacyText(StringVisitor builder)
|
void toLegacyText(StringBuilder builder)
|
||||||
{
|
{
|
||||||
if ( extra != null )
|
if ( extra != null )
|
||||||
{
|
{
|
||||||
@@ -717,7 +552,7 @@ public abstract class BaseComponent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void addFormat(StringVisitor builder)
|
void addFormat(StringBuilder builder)
|
||||||
{
|
{
|
||||||
builder.append( getColor() );
|
builder.append( getColor() );
|
||||||
if ( isBold() )
|
if ( isBold() )
|
||||||
@@ -741,35 +576,4 @@ public abstract class BaseComponent
|
|||||||
builder.append( ChatColor.MAGIC );
|
builder.append( ChatColor.MAGIC );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
protected static interface StringVisitor
|
|
||||||
{
|
|
||||||
|
|
||||||
void append(String s);
|
|
||||||
|
|
||||||
default void append(Object obj)
|
|
||||||
{
|
|
||||||
append( String.valueOf( obj ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Data
|
|
||||||
protected static class LimitedStringVisitor implements StringVisitor
|
|
||||||
{
|
|
||||||
|
|
||||||
private final StringBuilder builder;
|
|
||||||
private final int maxLength;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void append(String s)
|
|
||||||
{
|
|
||||||
if ( builder.length() >= maxLength )
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException( "String exceeded maximum length " + maxLength );
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.append( s );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -4,14 +4,12 @@ import lombok.EqualsAndHashCode;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@ToString
|
@ToString
|
||||||
@EqualsAndHashCode
|
@EqualsAndHashCode
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@ApiStatus.NonExtendable
|
public final class ClickEvent
|
||||||
public class ClickEvent
|
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -54,19 +52,11 @@ public class ClickEvent
|
|||||||
* {@link net.md_5.bungee.api.chat.ClickEvent#value} in a book.
|
* {@link net.md_5.bungee.api.chat.ClickEvent#value} in a book.
|
||||||
*/
|
*/
|
||||||
CHANGE_PAGE,
|
CHANGE_PAGE,
|
||||||
/**
|
|
||||||
* Must use subclass ShowDialogClickEvent.
|
|
||||||
*/
|
|
||||||
SHOW_DIALOG,
|
|
||||||
/**
|
/**
|
||||||
* Copy the string given by
|
* Copy the string given by
|
||||||
* {@link net.md_5.bungee.api.chat.ClickEvent#value} into the player's
|
* {@link net.md_5.bungee.api.chat.ClickEvent#value} into the player's
|
||||||
* clipboard.
|
* clipboard.
|
||||||
*/
|
*/
|
||||||
COPY_TO_CLIPBOARD,
|
COPY_TO_CLIPBOARD
|
||||||
/**
|
|
||||||
* Must use subclass {@link ClickEventCustom}.
|
|
||||||
*/
|
|
||||||
CUSTOM,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,30 +0,0 @@
|
|||||||
package net.md_5.bungee.api.chat;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
import lombok.ToString;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Click event which sends a custom payload to the server.
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@ToString(callSuper = true)
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
public class ClickEventCustom extends ClickEvent
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The custom payload.
|
|
||||||
*/
|
|
||||||
private final String payload;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param id identifier for the event (lower case, no special characters)
|
|
||||||
* @param payload custom payload
|
|
||||||
*/
|
|
||||||
public ClickEventCustom(String id, String payload)
|
|
||||||
{
|
|
||||||
super( ClickEvent.Action.CUSTOM, id );
|
|
||||||
this.payload = payload;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -57,7 +57,7 @@ public final class ComponentBuilder
|
|||||||
*/
|
*/
|
||||||
public ComponentBuilder(ComponentBuilder original)
|
public ComponentBuilder(ComponentBuilder original)
|
||||||
{
|
{
|
||||||
this( original.parts.toArray( new BaseComponent[ 0 ] ) );
|
this( original.parts.toArray( new BaseComponent[ original.parts.size() ] ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -161,7 +161,7 @@ public final class ComponentBuilder
|
|||||||
previous = dummy;
|
previous = dummy;
|
||||||
dummy = null;
|
dummy = null;
|
||||||
}
|
}
|
||||||
if ( previous != null && !component.isReset() )
|
if ( previous != null )
|
||||||
{
|
{
|
||||||
component.copyFormatting( previous, retention, false );
|
component.copyFormatting( previous, retention, false );
|
||||||
}
|
}
|
||||||
@@ -204,33 +204,6 @@ public final class ComponentBuilder
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Appends the {@link TranslationProvider} object to the builder and makes
|
|
||||||
* the last element the current target for formatting. The components will
|
|
||||||
* have all the formatting from previous part.
|
|
||||||
*
|
|
||||||
* @param translatable the translatable object to append
|
|
||||||
* @return this ComponentBuilder for chaining
|
|
||||||
*/
|
|
||||||
public ComponentBuilder append(TranslationProvider translatable)
|
|
||||||
{
|
|
||||||
return append( translatable, FormatRetention.ALL );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Appends the {@link TranslationProvider} object to the builder and makes
|
|
||||||
* the last element the current target for formatting. You can specify the
|
|
||||||
* amount of formatting retained from previous part.
|
|
||||||
*
|
|
||||||
* @param translatable the translatable object to append
|
|
||||||
* @param retention the formatting to retain
|
|
||||||
* @return this ComponentBuilder for chaining
|
|
||||||
*/
|
|
||||||
public ComponentBuilder append(TranslationProvider translatable, FormatRetention retention)
|
|
||||||
{
|
|
||||||
return append( translatable.asTranslatableComponent(), retention );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Appends the text to the builder and makes it the current target for
|
* Appends the text to the builder and makes it the current target for
|
||||||
* formatting. The text will have all the formatting from previous part.
|
* formatting. The text will have all the formatting from previous part.
|
||||||
@@ -423,18 +396,6 @@ public final class ComponentBuilder
|
|||||||
return this;
|
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.
|
* Sets the insertion text for the current part.
|
||||||
*
|
*
|
||||||
@@ -493,32 +454,9 @@ public final class ComponentBuilder
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the component built by this builder. If this builder is empty, an
|
|
||||||
* empty text component will be returned.
|
|
||||||
*
|
|
||||||
* @return the component
|
|
||||||
*/
|
|
||||||
public BaseComponent build()
|
|
||||||
{
|
|
||||||
TextComponent base = new TextComponent();
|
|
||||||
if ( !parts.isEmpty() )
|
|
||||||
{
|
|
||||||
List<BaseComponent> cloned = new ArrayList<>( parts );
|
|
||||||
cloned.replaceAll( BaseComponent::duplicate );
|
|
||||||
base.setExtra( cloned );
|
|
||||||
}
|
|
||||||
return base;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the components needed to display the message created by this
|
* Returns the components needed to display the message created by this
|
||||||
* builder.git
|
* builder.git
|
||||||
* <p>
|
|
||||||
* <strong>NOTE:</strong> {@link #build()} is preferred as it will
|
|
||||||
* consolidate all components into a single BaseComponent with extra
|
|
||||||
* contents as opposed to an array of components which is non-standard and
|
|
||||||
* may result in unexpected behavior.
|
|
||||||
*
|
*
|
||||||
* @return the created components
|
* @return the created components
|
||||||
*/
|
*/
|
||||||
|
@@ -1,263 +0,0 @@
|
|||||||
package net.md_5.bungee.api.chat;
|
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
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.
|
|
||||||
* <p>
|
|
||||||
* <b>Warning: This should be a color, not formatting code (ie,
|
|
||||||
* {@link ChatColor#color} should not be null).</b>
|
|
||||||
*/
|
|
||||||
private ChatColor color;
|
|
||||||
/**
|
|
||||||
* The shadow color of this style.
|
|
||||||
*/
|
|
||||||
private Color shadowColor;
|
|
||||||
/**
|
|
||||||
* 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 shadow color of this style. May return null.
|
|
||||||
*
|
|
||||||
* @return the shadow color of this style, or null if default color
|
|
||||||
*/
|
|
||||||
public Color getShadowColor()
|
|
||||||
{
|
|
||||||
return shadowColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether or not this style has a shadow color set.
|
|
||||||
*
|
|
||||||
* @return whether a shadow color is set
|
|
||||||
*/
|
|
||||||
public boolean hasShadowColor()
|
|
||||||
{
|
|
||||||
return ( shadowColor != 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 && shadowColor == null && font == null && bold == null
|
|
||||||
&& italic == null && underlined == null
|
|
||||||
&& strikethrough == null && obfuscated == null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ComponentStyle clone()
|
|
||||||
{
|
|
||||||
return new ComponentStyle( color, shadowColor, 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 )
|
|
||||||
.shadowColor( other.shadowColor )
|
|
||||||
.font( other.font )
|
|
||||||
.bold( other.bold )
|
|
||||||
.italic( other.italic )
|
|
||||||
.underlined( other.underlined )
|
|
||||||
.strikethrough( other.strikethrough )
|
|
||||||
.obfuscated( other.obfuscated );
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,140 +0,0 @@
|
|||||||
package net.md_5.bungee.api.chat;
|
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
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 Color shadowColor;
|
|
||||||
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 shadow color.
|
|
||||||
*
|
|
||||||
* @param shadowColor the shadow color to set, or null to use the default
|
|
||||||
* @return this ComponentStyleBuilder for chaining
|
|
||||||
*/
|
|
||||||
public ComponentStyleBuilder shadowColor(Color shadowColor)
|
|
||||||
{
|
|
||||||
this.shadowColor = shadowColor;
|
|
||||||
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, shadowColor, font, bold, italic, underlined, strikethrough, obfuscated );
|
|
||||||
}
|
|
||||||
}
|
|
@@ -13,7 +13,7 @@ import net.md_5.bungee.api.chat.hover.content.Content;
|
|||||||
import net.md_5.bungee.api.chat.hover.content.Entity;
|
import net.md_5.bungee.api.chat.hover.content.Entity;
|
||||||
import net.md_5.bungee.api.chat.hover.content.Item;
|
import net.md_5.bungee.api.chat.hover.content.Item;
|
||||||
import net.md_5.bungee.api.chat.hover.content.Text;
|
import net.md_5.bungee.api.chat.hover.content.Text;
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
import net.md_5.bungee.chat.ComponentSerializer;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@ToString
|
@ToString
|
||||||
@@ -34,7 +34,6 @@ public final class HoverEvent
|
|||||||
* Returns whether this hover event is prior to 1.16
|
* Returns whether this hover event is prior to 1.16
|
||||||
*/
|
*/
|
||||||
@Setter
|
@Setter
|
||||||
@ApiStatus.Internal
|
|
||||||
private boolean legacy = false;
|
private boolean legacy = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -72,6 +71,22 @@ public final class HoverEvent
|
|||||||
this.legacy = true;
|
this.legacy = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public BaseComponent[] getValue()
|
||||||
|
{
|
||||||
|
Content content = contents.get( 0 );
|
||||||
|
if ( content instanceof Text && ( (Text) content ).getValue() instanceof BaseComponent[] )
|
||||||
|
{
|
||||||
|
return (BaseComponent[]) ( (Text) content ).getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
TextComponent component = new TextComponent( ComponentSerializer.toString( content ) );
|
||||||
|
return new BaseComponent[]
|
||||||
|
{
|
||||||
|
component
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a content to this hover event.
|
* Adds a content to this hover event.
|
||||||
*
|
*
|
||||||
|
@@ -50,14 +50,14 @@ public final class KeybindComponent extends BaseComponent
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void toPlainText(StringVisitor builder)
|
protected void toPlainText(StringBuilder builder)
|
||||||
{
|
{
|
||||||
builder.append( getKeybind() );
|
builder.append( getKeybind() );
|
||||||
super.toPlainText( builder );
|
super.toPlainText( builder );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void toLegacyText(StringVisitor builder)
|
protected void toLegacyText(StringBuilder builder)
|
||||||
{
|
{
|
||||||
addFormat( builder );
|
addFormat( builder );
|
||||||
builder.append( getKeybind() );
|
builder.append( getKeybind() );
|
||||||
|
@@ -85,14 +85,14 @@ public final class ScoreComponent extends BaseComponent
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void toPlainText(StringVisitor builder)
|
protected void toPlainText(StringBuilder builder)
|
||||||
{
|
{
|
||||||
builder.append( this.value );
|
builder.append( this.value );
|
||||||
super.toPlainText( builder );
|
super.toPlainText( builder );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void toLegacyText(StringVisitor builder)
|
protected void toLegacyText(StringBuilder builder)
|
||||||
{
|
{
|
||||||
addFormat( builder );
|
addFormat( builder );
|
||||||
builder.append( this.value );
|
builder.append( this.value );
|
||||||
|
@@ -33,13 +33,6 @@ public final class SelectorComponent extends BaseComponent
|
|||||||
*/
|
*/
|
||||||
private String selector;
|
private String selector;
|
||||||
|
|
||||||
/**
|
|
||||||
* The separator of multiple selected entities.
|
|
||||||
* <br>
|
|
||||||
* The default is {@code {"color": "gray", "text": ", "}}.
|
|
||||||
*/
|
|
||||||
private BaseComponent separator;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a selector component from the original to clone it.
|
* Creates a selector component from the original to clone it.
|
||||||
*
|
*
|
||||||
@@ -49,17 +42,6 @@ public final class SelectorComponent extends BaseComponent
|
|||||||
{
|
{
|
||||||
super( original );
|
super( original );
|
||||||
setSelector( original.getSelector() );
|
setSelector( original.getSelector() );
|
||||||
setSeparator( original.getSeparator() );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a selector component from the selector
|
|
||||||
*
|
|
||||||
* @param selector the selector as a String
|
|
||||||
*/
|
|
||||||
public SelectorComponent(String selector)
|
|
||||||
{
|
|
||||||
setSelector( selector );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -69,14 +51,14 @@ public final class SelectorComponent extends BaseComponent
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void toPlainText(StringVisitor builder)
|
protected void toPlainText(StringBuilder builder)
|
||||||
{
|
{
|
||||||
builder.append( this.selector );
|
builder.append( this.selector );
|
||||||
super.toPlainText( builder );
|
super.toPlainText( builder );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void toLegacyText(StringVisitor builder)
|
protected void toLegacyText(StringBuilder builder)
|
||||||
{
|
{
|
||||||
addFormat( builder );
|
addFormat( builder );
|
||||||
builder.append( this.selector );
|
builder.append( this.selector );
|
||||||
|
@@ -2,7 +2,6 @@ package net.md_5.bungee.api.chat;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.function.Consumer;
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
@@ -28,41 +27,6 @@ public final class TextComponent extends BaseComponent
|
|||||||
* @param message the text to convert
|
* @param message the text to convert
|
||||||
* @return the components needed to print the message to the client
|
* @return the components needed to print the message to the client
|
||||||
*/
|
*/
|
||||||
public static BaseComponent fromLegacy(String message)
|
|
||||||
{
|
|
||||||
return fromLegacy( message, ChatColor.WHITE );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts the old formatting system that used
|
|
||||||
* {@link net.md_5.bungee.api.ChatColor#COLOR_CHAR} into the new json based
|
|
||||||
* system.
|
|
||||||
*
|
|
||||||
* @param message the text to convert
|
|
||||||
* @param defaultColor color to use when no formatting is to be applied
|
|
||||||
* (i.e. after ChatColor.RESET).
|
|
||||||
* @return the components needed to print the message to the client
|
|
||||||
*/
|
|
||||||
public static BaseComponent fromLegacy(String message, ChatColor defaultColor)
|
|
||||||
{
|
|
||||||
ComponentBuilder componentBuilder = new ComponentBuilder();
|
|
||||||
populateComponentStructure( message, defaultColor, componentBuilder::append );
|
|
||||||
return componentBuilder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts the old formatting system that used
|
|
||||||
* {@link net.md_5.bungee.api.ChatColor#COLOR_CHAR} into the new json based
|
|
||||||
* system.
|
|
||||||
*
|
|
||||||
* @param message the text to convert
|
|
||||||
* @return the components needed to print the message to the client
|
|
||||||
* @deprecated {@link #fromLegacy(String)} is preferred as it will
|
|
||||||
* consolidate all components into a single BaseComponent with extra
|
|
||||||
* contents as opposed to an array of components which is non-standard and
|
|
||||||
* may result in unexpected behavior.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public static BaseComponent[] fromLegacyText(String message)
|
public static BaseComponent[] fromLegacyText(String message)
|
||||||
{
|
{
|
||||||
return fromLegacyText( message, ChatColor.WHITE );
|
return fromLegacyText( message, ChatColor.WHITE );
|
||||||
@@ -77,21 +41,10 @@ public final class TextComponent extends BaseComponent
|
|||||||
* @param defaultColor color to use when no formatting is to be applied
|
* @param defaultColor color to use when no formatting is to be applied
|
||||||
* (i.e. after ChatColor.RESET).
|
* (i.e. after ChatColor.RESET).
|
||||||
* @return the components needed to print the message to the client
|
* @return the components needed to print the message to the client
|
||||||
* @deprecated {@link #fromLegacy(String, ChatColor)} is preferred as it
|
|
||||||
* will consolidate all components into a single BaseComponent with extra
|
|
||||||
* contents as opposed to an array of components which is non-standard and
|
|
||||||
* may result in unexpected behavior.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
public static BaseComponent[] fromLegacyText(String message, ChatColor defaultColor)
|
public static BaseComponent[] fromLegacyText(String message, ChatColor defaultColor)
|
||||||
{
|
{
|
||||||
ArrayList<BaseComponent> components = new ArrayList<>();
|
ArrayList<BaseComponent> components = new ArrayList<BaseComponent>();
|
||||||
populateComponentStructure( message, defaultColor, components::add );
|
|
||||||
return components.toArray( new BaseComponent[ 0 ] );
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void populateComponentStructure(String message, ChatColor defaultColor, Consumer<BaseComponent> appender)
|
|
||||||
{
|
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
TextComponent component = new TextComponent();
|
TextComponent component = new TextComponent();
|
||||||
Matcher matcher = url.matcher( message );
|
Matcher matcher = url.matcher( message );
|
||||||
@@ -141,7 +94,7 @@ public final class TextComponent extends BaseComponent
|
|||||||
component = new TextComponent( old );
|
component = new TextComponent( old );
|
||||||
old.setText( builder.toString() );
|
old.setText( builder.toString() );
|
||||||
builder = new StringBuilder();
|
builder = new StringBuilder();
|
||||||
appender.accept( old );
|
components.add( old );
|
||||||
}
|
}
|
||||||
if ( format == ChatColor.BOLD )
|
if ( format == ChatColor.BOLD )
|
||||||
{
|
{
|
||||||
@@ -158,15 +111,15 @@ public final class TextComponent extends BaseComponent
|
|||||||
} else if ( format == ChatColor.MAGIC )
|
} else if ( format == ChatColor.MAGIC )
|
||||||
{
|
{
|
||||||
component.setObfuscated( true );
|
component.setObfuscated( true );
|
||||||
} else
|
} else if ( format == ChatColor.RESET )
|
||||||
{
|
|
||||||
if ( format == ChatColor.RESET )
|
|
||||||
{
|
{
|
||||||
format = defaultColor;
|
format = defaultColor;
|
||||||
}
|
|
||||||
component = new TextComponent();
|
component = new TextComponent();
|
||||||
component.setColor( format );
|
component.setColor( format );
|
||||||
component.setReset( true );
|
} else
|
||||||
|
{
|
||||||
|
component = new TextComponent();
|
||||||
|
component.setColor( format );
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -184,7 +137,7 @@ public final class TextComponent extends BaseComponent
|
|||||||
component = new TextComponent( old );
|
component = new TextComponent( old );
|
||||||
old.setText( builder.toString() );
|
old.setText( builder.toString() );
|
||||||
builder = new StringBuilder();
|
builder = new StringBuilder();
|
||||||
appender.accept( old );
|
components.add( old );
|
||||||
}
|
}
|
||||||
|
|
||||||
TextComponent old = component;
|
TextComponent old = component;
|
||||||
@@ -193,7 +146,7 @@ public final class TextComponent extends BaseComponent
|
|||||||
component.setText( urlString );
|
component.setText( urlString );
|
||||||
component.setClickEvent( new ClickEvent( ClickEvent.Action.OPEN_URL,
|
component.setClickEvent( new ClickEvent( ClickEvent.Action.OPEN_URL,
|
||||||
urlString.startsWith( "http" ) ? urlString : "http://" + urlString ) );
|
urlString.startsWith( "http" ) ? urlString : "http://" + urlString ) );
|
||||||
appender.accept( component );
|
components.add( component );
|
||||||
i += pos - i - 1;
|
i += pos - i - 1;
|
||||||
component = old;
|
component = old;
|
||||||
continue;
|
continue;
|
||||||
@@ -202,29 +155,9 @@ public final class TextComponent extends BaseComponent
|
|||||||
}
|
}
|
||||||
|
|
||||||
component.setText( builder.toString() );
|
component.setText( builder.toString() );
|
||||||
appender.accept( component );
|
components.add( component );
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
return components.toArray( new BaseComponent[ components.size() ] );
|
||||||
* Internal compatibility method to transform an array of components to a
|
|
||||||
* single component.
|
|
||||||
*
|
|
||||||
* @param components array
|
|
||||||
* @return single component
|
|
||||||
*/
|
|
||||||
public static BaseComponent fromArray(BaseComponent... components)
|
|
||||||
{
|
|
||||||
if ( components == null )
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( components.length == 1 )
|
|
||||||
{
|
|
||||||
return components[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
return new TextComponent( components );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -280,14 +213,14 @@ public final class TextComponent extends BaseComponent
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void toPlainText(StringVisitor builder)
|
protected void toPlainText(StringBuilder builder)
|
||||||
{
|
{
|
||||||
builder.append( text );
|
builder.append( text );
|
||||||
super.toPlainText( builder );
|
super.toPlainText( builder );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void toLegacyText(StringVisitor builder)
|
protected void toLegacyText(StringBuilder builder)
|
||||||
{
|
{
|
||||||
addFormat( builder );
|
addFormat( builder );
|
||||||
builder.append( text );
|
builder.append( text );
|
||||||
@@ -297,6 +230,6 @@ public final class TextComponent extends BaseComponent
|
|||||||
@Override
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
return "TextComponent{text=" + text + ", " + super.toString() + '}';
|
return String.format( "TextComponent{text=%s, %s}", text, super.toString() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -19,7 +19,7 @@ import net.md_5.bungee.chat.TranslationRegistry;
|
|||||||
public final class TranslatableComponent extends BaseComponent
|
public final class TranslatableComponent extends BaseComponent
|
||||||
{
|
{
|
||||||
|
|
||||||
private static final Pattern FORMAT = Pattern.compile( "%(?:(\\d+)\\$)?([A-Za-z%]|$)" );
|
private final Pattern format = Pattern.compile( "%(?:(\\d+)\\$)?([A-Za-z%]|$)" );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The key into the Minecraft locale files to use for the translation. The
|
* The key into the Minecraft locale files to use for the translation. The
|
||||||
@@ -30,10 +30,6 @@ public final class TranslatableComponent extends BaseComponent
|
|||||||
* The components to substitute into the translation
|
* The components to substitute into the translation
|
||||||
*/
|
*/
|
||||||
private List<BaseComponent> with;
|
private List<BaseComponent> with;
|
||||||
/**
|
|
||||||
* The fallback, if the translation is not found
|
|
||||||
*/
|
|
||||||
private String fallback;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a translatable component from the original to clone it.
|
* Creates a translatable component from the original to clone it.
|
||||||
@@ -44,11 +40,10 @@ public final class TranslatableComponent extends BaseComponent
|
|||||||
{
|
{
|
||||||
super( original );
|
super( original );
|
||||||
setTranslate( original.getTranslate() );
|
setTranslate( original.getTranslate() );
|
||||||
setFallback( original.getFallback() );
|
|
||||||
|
|
||||||
if ( original.getWith() != null )
|
if ( original.getWith() != null )
|
||||||
{
|
{
|
||||||
List<BaseComponent> temp = new ArrayList<>();
|
List<BaseComponent> temp = new ArrayList<BaseComponent>();
|
||||||
for ( BaseComponent baseComponent : original.getWith() )
|
for ( BaseComponent baseComponent : original.getWith() )
|
||||||
{
|
{
|
||||||
temp.add( baseComponent.duplicate() );
|
temp.add( baseComponent.duplicate() );
|
||||||
@@ -87,21 +82,6 @@ public final class TranslatableComponent extends BaseComponent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a translatable component with the passed substitutions
|
|
||||||
*
|
|
||||||
* @param translatable the translatable object
|
|
||||||
* @param with the {@link java.lang.String}s and
|
|
||||||
* {@link net.md_5.bungee.api.chat.BaseComponent}s to use into the
|
|
||||||
* translation
|
|
||||||
* @see #translate
|
|
||||||
* @see #setWith(java.util.List)
|
|
||||||
*/
|
|
||||||
public TranslatableComponent(TranslationProvider translatable, Object... with)
|
|
||||||
{
|
|
||||||
this( translatable.getTranslationKey(), with );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a duplicate of this TranslatableComponent.
|
* Creates a duplicate of this TranslatableComponent.
|
||||||
*
|
*
|
||||||
@@ -156,29 +136,24 @@ public final class TranslatableComponent extends BaseComponent
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void toPlainText(StringVisitor builder)
|
protected void toPlainText(StringBuilder builder)
|
||||||
{
|
{
|
||||||
convert( builder, false );
|
convert( builder, false );
|
||||||
super.toPlainText( builder );
|
super.toPlainText( builder );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void toLegacyText(StringVisitor builder)
|
protected void toLegacyText(StringBuilder builder)
|
||||||
{
|
{
|
||||||
convert( builder, true );
|
convert( builder, true );
|
||||||
super.toLegacyText( builder );
|
super.toLegacyText( builder );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void convert(StringVisitor builder, boolean applyFormat)
|
private void convert(StringBuilder builder, boolean applyFormat)
|
||||||
{
|
{
|
||||||
String trans = TranslationRegistry.INSTANCE.translate( translate );
|
String trans = TranslationRegistry.INSTANCE.translate( translate );
|
||||||
|
|
||||||
if ( trans.equals( translate ) && fallback != null )
|
Matcher matcher = format.matcher( trans );
|
||||||
{
|
|
||||||
trans = fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
Matcher matcher = FORMAT.matcher( trans );
|
|
||||||
int position = 0;
|
int position = 0;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while ( matcher.find( position ) )
|
while ( matcher.find( position ) )
|
||||||
|
@@ -1,38 +0,0 @@
|
|||||||
package net.md_5.bungee.api.chat;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An object capable of being translated by the client in a
|
|
||||||
* {@link TranslatableComponent}.
|
|
||||||
*/
|
|
||||||
public interface TranslationProvider
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the translation key.
|
|
||||||
*
|
|
||||||
* @return the translation key
|
|
||||||
*/
|
|
||||||
String getTranslationKey();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get this translatable object as a {@link TranslatableComponent}.
|
|
||||||
*
|
|
||||||
* @return the translatable component
|
|
||||||
*/
|
|
||||||
default TranslatableComponent asTranslatableComponent()
|
|
||||||
{
|
|
||||||
return asTranslatableComponent( (Object[]) null );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get this translatable object as a {@link TranslatableComponent}.
|
|
||||||
*
|
|
||||||
* @param with the {@link String Strings} and
|
|
||||||
* {@link BaseComponent BaseComponents} to use in the translation
|
|
||||||
* @return the translatable component
|
|
||||||
*/
|
|
||||||
default TranslatableComponent asTranslatableComponent(Object... with)
|
|
||||||
{
|
|
||||||
return new TranslatableComponent( this, with );
|
|
||||||
}
|
|
||||||
}
|
|
@@ -0,0 +1,40 @@
|
|||||||
|
package net.md_5.bungee.api.chat.hover.content;
|
||||||
|
|
||||||
|
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.JsonSerializationContext;
|
||||||
|
import com.google.gson.JsonSerializer;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import net.md_5.bungee.api.chat.BaseComponent;
|
||||||
|
|
||||||
|
public class EntitySerializer implements JsonSerializer<Entity>, JsonDeserializer<Entity>
|
||||||
|
{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Entity deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException
|
||||||
|
{
|
||||||
|
JsonObject value = element.getAsJsonObject();
|
||||||
|
|
||||||
|
return new Entity(
|
||||||
|
( value.has( "type" ) ) ? value.get( "type" ).getAsString() : null,
|
||||||
|
value.get( "id" ).getAsString(),
|
||||||
|
( value.has( "name" ) ) ? context.deserialize( value.get( "name" ), BaseComponent.class ) : null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsonElement serialize(Entity content, Type type, JsonSerializationContext context)
|
||||||
|
{
|
||||||
|
JsonObject object = new JsonObject();
|
||||||
|
object.addProperty( "type", ( content.getType() != null ) ? content.getType() : "minecraft:pig" );
|
||||||
|
object.addProperty( "id", content.getId() );
|
||||||
|
if ( content.getName() != null )
|
||||||
|
{
|
||||||
|
object.add( "name", context.serialize( content.getName() ) );
|
||||||
|
}
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
}
|
@@ -23,15 +23,6 @@ public class Text extends Content
|
|||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Text(BaseComponent value)
|
|
||||||
{
|
|
||||||
// For legacy serialization reasons, this has to be an array of components
|
|
||||||
this( new BaseComponent[]
|
|
||||||
{
|
|
||||||
value
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
|
|
||||||
public Text(String value)
|
public Text(String value)
|
||||||
{
|
{
|
||||||
this.value = value;
|
this.value = value;
|
||||||
|
@@ -0,0 +1,207 @@
|
|||||||
|
package net.md_5.bungee.chat;
|
||||||
|
|
||||||
|
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.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.HoverEvent;
|
||||||
|
import net.md_5.bungee.api.chat.hover.content.Content;
|
||||||
|
|
||||||
|
public class BaseComponentSerializer
|
||||||
|
{
|
||||||
|
|
||||||
|
protected void deserialize(JsonObject object, BaseComponent component, JsonDeserializationContext context)
|
||||||
|
{
|
||||||
|
if ( object.has( "color" ) )
|
||||||
|
{
|
||||||
|
component.setColor( ChatColor.of( object.get( "color" ).getAsString() ) );
|
||||||
|
}
|
||||||
|
if ( object.has( "font" ) )
|
||||||
|
{
|
||||||
|
component.setFont( object.get( "font" ).getAsString() );
|
||||||
|
}
|
||||||
|
if ( object.has( "bold" ) )
|
||||||
|
{
|
||||||
|
component.setBold( object.get( "bold" ).getAsBoolean() );
|
||||||
|
}
|
||||||
|
if ( object.has( "italic" ) )
|
||||||
|
{
|
||||||
|
component.setItalic( object.get( "italic" ).getAsBoolean() );
|
||||||
|
}
|
||||||
|
if ( object.has( "underlined" ) )
|
||||||
|
{
|
||||||
|
component.setUnderlined( object.get( "underlined" ).getAsBoolean() );
|
||||||
|
}
|
||||||
|
if ( object.has( "strikethrough" ) )
|
||||||
|
{
|
||||||
|
component.setStrikethrough( object.get( "strikethrough" ).getAsBoolean() );
|
||||||
|
}
|
||||||
|
if ( object.has( "obfuscated" ) )
|
||||||
|
{
|
||||||
|
component.setObfuscated( object.get( "obfuscated" ).getAsBoolean() );
|
||||||
|
}
|
||||||
|
if ( object.has( "insertion" ) )
|
||||||
|
{
|
||||||
|
component.setInsertion( object.get( "insertion" ).getAsString() );
|
||||||
|
}
|
||||||
|
if ( object.has( "extra" ) )
|
||||||
|
{
|
||||||
|
component.setExtra( Arrays.asList( context.<BaseComponent[]>deserialize( object.get( "extra" ), BaseComponent[].class ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
//Events
|
||||||
|
if ( object.has( "clickEvent" ) )
|
||||||
|
{
|
||||||
|
JsonObject event = object.getAsJsonObject( "clickEvent" );
|
||||||
|
component.setClickEvent( new ClickEvent(
|
||||||
|
ClickEvent.Action.valueOf( event.get( "action" ).getAsString().toUpperCase( Locale.ROOT ) ),
|
||||||
|
( event.has( "value" ) ) ? event.get( "value" ).getAsString() : "" ) );
|
||||||
|
}
|
||||||
|
if ( object.has( "hoverEvent" ) )
|
||||||
|
{
|
||||||
|
JsonObject event = object.getAsJsonObject( "hoverEvent" );
|
||||||
|
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( type ) )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
JsonElement contents = event.get( type );
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
// 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 )
|
||||||
|
{
|
||||||
|
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 ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// stop the loop as soon as either one is found
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ( hoverEvent != null )
|
||||||
|
{
|
||||||
|
component.setHoverEvent( hoverEvent );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void serialize(JsonObject object, BaseComponent component, JsonSerializationContext context)
|
||||||
|
{
|
||||||
|
boolean first = false;
|
||||||
|
if ( ComponentSerializer.serializedComponents.get() == null )
|
||||||
|
{
|
||||||
|
first = true;
|
||||||
|
ComponentSerializer.serializedComponents.set( Collections.newSetFromMap( new IdentityHashMap<BaseComponent, Boolean>() ) );
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Preconditions.checkArgument( !ComponentSerializer.serializedComponents.get().contains( component ), "Component loop" );
|
||||||
|
ComponentSerializer.serializedComponents.get().add( component );
|
||||||
|
if ( component.getColorRaw() != null )
|
||||||
|
{
|
||||||
|
object.addProperty( "color", component.getColorRaw().getName() );
|
||||||
|
}
|
||||||
|
if ( component.getFontRaw() != null )
|
||||||
|
{
|
||||||
|
object.addProperty( "font", component.getFontRaw() );
|
||||||
|
}
|
||||||
|
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.getInsertion() != null )
|
||||||
|
{
|
||||||
|
object.addProperty( "insertion", component.getInsertion() );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( component.getExtra() != null )
|
||||||
|
{
|
||||||
|
object.add( "extra", context.serialize( component.getExtra() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
//Events
|
||||||
|
if ( component.getClickEvent() != null )
|
||||||
|
{
|
||||||
|
JsonObject clickEvent = new JsonObject();
|
||||||
|
clickEvent.addProperty( "action", component.getClickEvent().getAction().toString().toLowerCase( Locale.ROOT ) );
|
||||||
|
clickEvent.addProperty( "value", component.getClickEvent().getValue() );
|
||||||
|
object.add( "clickEvent", clickEvent );
|
||||||
|
}
|
||||||
|
if ( component.getHoverEvent() != null )
|
||||||
|
{
|
||||||
|
JsonObject hoverEvent = new JsonObject();
|
||||||
|
hoverEvent.addProperty( "action", component.getHoverEvent().getAction().toString().toLowerCase( Locale.ROOT ) );
|
||||||
|
if ( component.getHoverEvent().isLegacy() )
|
||||||
|
{
|
||||||
|
hoverEvent.add( "value", context.serialize( component.getHoverEvent().getContents().get( 0 ) ) );
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
hoverEvent.add( "contents", context.serialize( ( component.getHoverEvent().getContents().size() == 1 )
|
||||||
|
? component.getHoverEvent().getContents().get( 0 ) : component.getHoverEvent().getContents() ) );
|
||||||
|
}
|
||||||
|
object.add( "hoverEvent", hoverEvent );
|
||||||
|
}
|
||||||
|
} finally
|
||||||
|
{
|
||||||
|
ComponentSerializer.serializedComponents.get().remove( component );
|
||||||
|
if ( first )
|
||||||
|
{
|
||||||
|
ComponentSerializer.serializedComponents.set( null );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
109
chat/src/main/java/net/md_5/bungee/chat/ComponentSerializer.java
Normal file
109
chat/src/main/java/net/md_5/bungee/chat/ComponentSerializer.java
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
package net.md_5.bungee.chat;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
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.JsonParser;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.Set;
|
||||||
|
import net.md_5.bungee.api.chat.BaseComponent;
|
||||||
|
import net.md_5.bungee.api.chat.ItemTag;
|
||||||
|
import net.md_5.bungee.api.chat.KeybindComponent;
|
||||||
|
import net.md_5.bungee.api.chat.ScoreComponent;
|
||||||
|
import net.md_5.bungee.api.chat.SelectorComponent;
|
||||||
|
import net.md_5.bungee.api.chat.TextComponent;
|
||||||
|
import net.md_5.bungee.api.chat.TranslatableComponent;
|
||||||
|
import net.md_5.bungee.api.chat.hover.content.Entity;
|
||||||
|
import net.md_5.bungee.api.chat.hover.content.EntitySerializer;
|
||||||
|
import net.md_5.bungee.api.chat.hover.content.Item;
|
||||||
|
import net.md_5.bungee.api.chat.hover.content.ItemSerializer;
|
||||||
|
import net.md_5.bungee.api.chat.hover.content.Text;
|
||||||
|
import net.md_5.bungee.api.chat.hover.content.TextSerializer;
|
||||||
|
|
||||||
|
public class ComponentSerializer implements JsonDeserializer<BaseComponent>
|
||||||
|
{
|
||||||
|
|
||||||
|
private static final JsonParser JSON_PARSER = new JsonParser();
|
||||||
|
private static final Gson gson = new GsonBuilder().
|
||||||
|
registerTypeAdapter( BaseComponent.class, new ComponentSerializer() ).
|
||||||
|
registerTypeAdapter( TextComponent.class, new TextComponentSerializer() ).
|
||||||
|
registerTypeAdapter( TranslatableComponent.class, new TranslatableComponentSerializer() ).
|
||||||
|
registerTypeAdapter( KeybindComponent.class, new KeybindComponentSerializer() ).
|
||||||
|
registerTypeAdapter( ScoreComponent.class, new ScoreComponentSerializer() ).
|
||||||
|
registerTypeAdapter( SelectorComponent.class, new SelectorComponentSerializer() ).
|
||||||
|
registerTypeAdapter( Entity.class, new EntitySerializer() ).
|
||||||
|
registerTypeAdapter( Text.class, new TextSerializer() ).
|
||||||
|
registerTypeAdapter( Item.class, new ItemSerializer() ).
|
||||||
|
registerTypeAdapter( ItemTag.class, new ItemTag.Serializer() ).
|
||||||
|
create();
|
||||||
|
|
||||||
|
public static final ThreadLocal<Set<BaseComponent>> serializedComponents = new ThreadLocal<Set<BaseComponent>>();
|
||||||
|
|
||||||
|
public static BaseComponent[] parse(String json)
|
||||||
|
{
|
||||||
|
JsonElement jsonElement = JSON_PARSER.parse( json );
|
||||||
|
|
||||||
|
if ( jsonElement.isJsonArray() )
|
||||||
|
{
|
||||||
|
return gson.fromJson( jsonElement, BaseComponent[].class );
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
return new BaseComponent[]
|
||||||
|
{
|
||||||
|
gson.fromJson( jsonElement, BaseComponent.class )
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String toString(Object object)
|
||||||
|
{
|
||||||
|
return gson.toJson( object );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String toString(BaseComponent component)
|
||||||
|
{
|
||||||
|
return gson.toJson( component );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String toString(BaseComponent... components)
|
||||||
|
{
|
||||||
|
if ( components.length == 1 )
|
||||||
|
{
|
||||||
|
return gson.toJson( components[0] );
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
return gson.toJson( new TextComponent( components ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BaseComponent deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
|
||||||
|
{
|
||||||
|
if ( json.isJsonPrimitive() )
|
||||||
|
{
|
||||||
|
return new TextComponent( json.getAsString() );
|
||||||
|
}
|
||||||
|
JsonObject object = json.getAsJsonObject();
|
||||||
|
if ( object.has( "translate" ) )
|
||||||
|
{
|
||||||
|
return context.deserialize( json, TranslatableComponent.class );
|
||||||
|
}
|
||||||
|
if ( object.has( "keybind" ) )
|
||||||
|
{
|
||||||
|
return context.deserialize( json, KeybindComponent.class );
|
||||||
|
}
|
||||||
|
if ( object.has( "score" ) )
|
||||||
|
{
|
||||||
|
return context.deserialize( json, ScoreComponent.class );
|
||||||
|
}
|
||||||
|
if ( object.has( "selector" ) )
|
||||||
|
{
|
||||||
|
return context.deserialize( json, SelectorComponent.class );
|
||||||
|
}
|
||||||
|
return context.deserialize( json, TextComponent.class );
|
||||||
|
}
|
||||||
|
}
|
@@ -13,23 +13,17 @@ import net.md_5.bungee.api.chat.KeybindComponent;
|
|||||||
public class KeybindComponentSerializer extends BaseComponentSerializer implements JsonSerializer<KeybindComponent>, JsonDeserializer<KeybindComponent>
|
public class KeybindComponentSerializer extends BaseComponentSerializer implements JsonSerializer<KeybindComponent>, JsonDeserializer<KeybindComponent>
|
||||||
{
|
{
|
||||||
|
|
||||||
public KeybindComponentSerializer(VersionedComponentSerializer serializer)
|
|
||||||
{
|
|
||||||
super( serializer );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KeybindComponent deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
|
public KeybindComponent deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
|
||||||
{
|
{
|
||||||
JsonObject object = json.getAsJsonObject();
|
JsonObject object = json.getAsJsonObject();
|
||||||
JsonElement keybind = object.get( "keybind" );
|
if ( !object.has( "keybind" ) )
|
||||||
if ( keybind == null )
|
|
||||||
{
|
{
|
||||||
throw new JsonParseException( "Could not parse JSON: missing 'keybind' property" );
|
throw new JsonParseException( "Could not parse JSON: missing 'keybind' property" );
|
||||||
}
|
}
|
||||||
KeybindComponent component = new KeybindComponent();
|
KeybindComponent component = new KeybindComponent();
|
||||||
deserialize( object, component, context );
|
deserialize( object, component, context );
|
||||||
component.setKeybind( keybind.getAsString() );
|
component.setKeybind( object.get( "keybind" ).getAsString() );
|
||||||
return component;
|
return component;
|
||||||
}
|
}
|
||||||
|
|
@@ -13,38 +13,26 @@ import net.md_5.bungee.api.chat.ScoreComponent;
|
|||||||
public class ScoreComponentSerializer extends BaseComponentSerializer implements JsonSerializer<ScoreComponent>, JsonDeserializer<ScoreComponent>
|
public class ScoreComponentSerializer extends BaseComponentSerializer implements JsonSerializer<ScoreComponent>, JsonDeserializer<ScoreComponent>
|
||||||
{
|
{
|
||||||
|
|
||||||
public ScoreComponentSerializer(VersionedComponentSerializer serializer)
|
|
||||||
{
|
|
||||||
super( serializer );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ScoreComponent deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException
|
public ScoreComponent deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException
|
||||||
{
|
{
|
||||||
JsonObject json = element.getAsJsonObject();
|
JsonObject json = element.getAsJsonObject();
|
||||||
JsonObject score = json.getAsJsonObject( "score" );
|
if ( !json.has( "score" ) )
|
||||||
if ( score == null )
|
|
||||||
{
|
{
|
||||||
throw new JsonParseException( "Could not parse JSON: missing 'score' property" );
|
throw new JsonParseException( "Could not parse JSON: missing 'score' property" );
|
||||||
}
|
}
|
||||||
JsonElement nameJson = score.get( "name" );
|
JsonObject score = json.get( "score" ).getAsJsonObject();
|
||||||
if ( nameJson == null )
|
if ( !score.has( "name" ) || !score.has( "objective" ) )
|
||||||
{
|
|
||||||
throw new JsonParseException( "A score component needs at least a name (and an objective)" );
|
|
||||||
}
|
|
||||||
JsonElement objectiveJson = score.get( "objective" );
|
|
||||||
if ( objectiveJson == null )
|
|
||||||
{
|
{
|
||||||
throw new JsonParseException( "A score component needs at least a name and an objective" );
|
throw new JsonParseException( "A score component needs at least a name and an objective" );
|
||||||
}
|
}
|
||||||
|
|
||||||
String name = nameJson.getAsString();
|
String name = score.get( "name" ).getAsString();
|
||||||
String objective = objectiveJson.getAsString();
|
String objective = score.get( "objective" ).getAsString();
|
||||||
ScoreComponent component = new ScoreComponent( name, objective );
|
ScoreComponent component = new ScoreComponent( name, objective );
|
||||||
JsonElement value = score.get( "value" );
|
if ( score.has( "value" ) && !score.get( "value" ).getAsString().isEmpty() )
|
||||||
if ( value != null && !value.getAsString().isEmpty() )
|
|
||||||
{
|
{
|
||||||
component.setValue( value.getAsString() );
|
component.setValue( score.get( "value" ).getAsString() );
|
||||||
}
|
}
|
||||||
|
|
||||||
deserialize( json, component, context );
|
deserialize( json, component, context );
|
@@ -13,28 +13,15 @@ import net.md_5.bungee.api.chat.SelectorComponent;
|
|||||||
public class SelectorComponentSerializer extends BaseComponentSerializer implements JsonSerializer<SelectorComponent>, JsonDeserializer<SelectorComponent>
|
public class SelectorComponentSerializer extends BaseComponentSerializer implements JsonSerializer<SelectorComponent>, JsonDeserializer<SelectorComponent>
|
||||||
{
|
{
|
||||||
|
|
||||||
public SelectorComponentSerializer(VersionedComponentSerializer serializer)
|
|
||||||
{
|
|
||||||
super( serializer );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SelectorComponent deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException
|
public SelectorComponent deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException
|
||||||
{
|
{
|
||||||
JsonObject object = element.getAsJsonObject();
|
JsonObject object = element.getAsJsonObject();
|
||||||
JsonElement selector = object.get( "selector" );
|
if ( !object.has( "selector" ) )
|
||||||
if ( selector == null )
|
|
||||||
{
|
{
|
||||||
throw new JsonParseException( "Could not parse JSON: missing 'selector' property" );
|
throw new JsonParseException( "Could not parse JSON: missing 'selector' property" );
|
||||||
}
|
}
|
||||||
SelectorComponent component = new SelectorComponent( selector.getAsString() );
|
SelectorComponent component = new SelectorComponent( object.get( "selector" ).getAsString() );
|
||||||
|
|
||||||
JsonElement separator = object.get( "separator" );
|
|
||||||
if ( separator != null )
|
|
||||||
{
|
|
||||||
component.setSeparator( serializer.deserialize( separator.getAsString() ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
deserialize( object, component, context );
|
deserialize( object, component, context );
|
||||||
return component;
|
return component;
|
||||||
}
|
}
|
||||||
@@ -45,11 +32,6 @@ public class SelectorComponentSerializer extends BaseComponentSerializer impleme
|
|||||||
JsonObject object = new JsonObject();
|
JsonObject object = new JsonObject();
|
||||||
serialize( object, component, context );
|
serialize( object, component, context );
|
||||||
object.addProperty( "selector", component.getSelector() );
|
object.addProperty( "selector", component.getSelector() );
|
||||||
|
|
||||||
if ( component.getSeparator() != null )
|
|
||||||
{
|
|
||||||
object.addProperty( "separator", serializer.toString( component.getSeparator() ) );
|
|
||||||
}
|
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -8,26 +8,23 @@ import com.google.gson.JsonParseException;
|
|||||||
import com.google.gson.JsonSerializationContext;
|
import com.google.gson.JsonSerializationContext;
|
||||||
import com.google.gson.JsonSerializer;
|
import com.google.gson.JsonSerializer;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.List;
|
||||||
|
import net.md_5.bungee.api.chat.BaseComponent;
|
||||||
import net.md_5.bungee.api.chat.TextComponent;
|
import net.md_5.bungee.api.chat.TextComponent;
|
||||||
|
|
||||||
public class TextComponentSerializer extends BaseComponentSerializer implements JsonSerializer<TextComponent>, JsonDeserializer<TextComponent>
|
public class TextComponentSerializer extends BaseComponentSerializer implements JsonSerializer<TextComponent>, JsonDeserializer<TextComponent>
|
||||||
{
|
{
|
||||||
|
|
||||||
public TextComponentSerializer(VersionedComponentSerializer serializer)
|
|
||||||
{
|
|
||||||
super( serializer );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TextComponent deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
|
public TextComponent deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
|
||||||
{
|
{
|
||||||
TextComponent component = new TextComponent();
|
TextComponent component = new TextComponent();
|
||||||
JsonObject object = json.getAsJsonObject();
|
JsonObject object = json.getAsJsonObject();
|
||||||
JsonElement text = object.get( "text" );
|
if ( !object.has( "text" ) )
|
||||||
if ( text != null )
|
|
||||||
{
|
{
|
||||||
component.setText( text.getAsString() );
|
throw new JsonParseException( "Could not parse JSON: missing 'text' property" );
|
||||||
}
|
}
|
||||||
|
component.setText( object.get( "text" ).getAsString() );
|
||||||
deserialize( object, component, context );
|
deserialize( object, component, context );
|
||||||
return component;
|
return component;
|
||||||
}
|
}
|
||||||
@@ -35,9 +32,13 @@ public class TextComponentSerializer extends BaseComponentSerializer implements
|
|||||||
@Override
|
@Override
|
||||||
public JsonElement serialize(TextComponent src, Type typeOfSrc, JsonSerializationContext context)
|
public JsonElement serialize(TextComponent src, Type typeOfSrc, JsonSerializationContext context)
|
||||||
{
|
{
|
||||||
|
List<BaseComponent> extra = src.getExtra();
|
||||||
JsonObject object = new JsonObject();
|
JsonObject object = new JsonObject();
|
||||||
serialize( object, src, context );
|
|
||||||
object.addProperty( "text", src.getText() );
|
object.addProperty( "text", src.getText() );
|
||||||
|
if ( src.hasFormatting() || ( extra != null && !extra.isEmpty() ) )
|
||||||
|
{
|
||||||
|
serialize( object, src, context );
|
||||||
|
}
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -15,32 +15,20 @@ import net.md_5.bungee.api.chat.TranslatableComponent;
|
|||||||
public class TranslatableComponentSerializer extends BaseComponentSerializer implements JsonSerializer<TranslatableComponent>, JsonDeserializer<TranslatableComponent>
|
public class TranslatableComponentSerializer extends BaseComponentSerializer implements JsonSerializer<TranslatableComponent>, JsonDeserializer<TranslatableComponent>
|
||||||
{
|
{
|
||||||
|
|
||||||
public TranslatableComponentSerializer(VersionedComponentSerializer serializer)
|
|
||||||
{
|
|
||||||
super( serializer );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TranslatableComponent deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
|
public TranslatableComponent deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
|
||||||
{
|
{
|
||||||
TranslatableComponent component = new TranslatableComponent();
|
TranslatableComponent component = new TranslatableComponent();
|
||||||
JsonObject object = json.getAsJsonObject();
|
JsonObject object = json.getAsJsonObject();
|
||||||
deserialize( object, component, context );
|
deserialize( object, component, context );
|
||||||
JsonElement translate = object.get( "translate" );
|
if ( !object.has( "translate" ) )
|
||||||
if ( translate == null )
|
|
||||||
{
|
{
|
||||||
throw new JsonParseException( "Could not parse JSON: missing 'translate' property" );
|
throw new JsonParseException( "Could not parse JSON: missing 'translate' property" );
|
||||||
}
|
}
|
||||||
component.setTranslate( translate.getAsString() );
|
component.setTranslate( object.get( "translate" ).getAsString() );
|
||||||
JsonElement with = object.get( "with" );
|
if ( object.has( "with" ) )
|
||||||
if ( with != null )
|
|
||||||
{
|
{
|
||||||
component.setWith( Arrays.asList( context.deserialize( with, BaseComponent[].class ) ) );
|
component.setWith( Arrays.asList( context.<BaseComponent[]>deserialize( object.get( "with" ), BaseComponent[].class ) ) );
|
||||||
}
|
|
||||||
JsonElement fallback = object.get( "fallback" );
|
|
||||||
if ( fallback != null )
|
|
||||||
{
|
|
||||||
component.setFallback( fallback.getAsString() );
|
|
||||||
}
|
}
|
||||||
return component;
|
return component;
|
||||||
}
|
}
|
||||||
@@ -55,10 +43,6 @@ public class TranslatableComponentSerializer extends BaseComponentSerializer imp
|
|||||||
{
|
{
|
||||||
object.add( "with", context.serialize( src.getWith() ) );
|
object.add( "with", context.serialize( src.getWith() ) );
|
||||||
}
|
}
|
||||||
if ( src.getFallback() != null )
|
|
||||||
{
|
|
||||||
object.addProperty( "fallback", src.getFallback() );
|
|
||||||
}
|
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,11 +1,11 @@
|
|||||||
package net.md_5.bungee.chat;
|
package net.md_5.bungee.chat;
|
||||||
|
|
||||||
|
import com.google.common.base.Charsets;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -102,7 +102,7 @@ public final class TranslationRegistry
|
|||||||
|
|
||||||
public JsonProvider(String resourcePath) throws IOException
|
public JsonProvider(String resourcePath) throws IOException
|
||||||
{
|
{
|
||||||
try ( InputStreamReader rd = new InputStreamReader( JsonProvider.class.getResourceAsStream( resourcePath ), StandardCharsets.UTF_8 ) )
|
try ( InputStreamReader rd = new InputStreamReader( JsonProvider.class.getResourceAsStream( resourcePath ), Charsets.UTF_8 ) )
|
||||||
{
|
{
|
||||||
JsonObject obj = new Gson().fromJson( rd, JsonObject.class );
|
JsonObject obj = new Gson().fromJson( rd, JsonObject.class );
|
||||||
for ( Map.Entry<String, JsonElement> entries : obj.entrySet() )
|
for ( Map.Entry<String, JsonElement> entries : obj.entrySet() )
|
||||||
|
579
chat/src/test/java/net/md_5/bungee/api/chat/ComponentsTest.java
Normal file
579
chat/src/test/java/net/md_5/bungee/api/chat/ComponentsTest.java
Normal file
@@ -0,0 +1,579 @@
|
|||||||
|
package net.md_5.bungee.api.chat;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import net.md_5.bungee.api.ChatColor;
|
||||||
|
import net.md_5.bungee.api.chat.hover.content.Item;
|
||||||
|
import net.md_5.bungee.api.chat.hover.content.Text;
|
||||||
|
import net.md_5.bungee.chat.ComponentSerializer;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class ComponentsTest
|
||||||
|
{
|
||||||
|
|
||||||
|
public static void testDissembleReassemble(BaseComponent[] components)
|
||||||
|
{
|
||||||
|
String json = ComponentSerializer.toString( components );
|
||||||
|
BaseComponent[] parsed = ComponentSerializer.parse( json );
|
||||||
|
Assert.assertEquals( TextComponent.toLegacyText( parsed ), TextComponent.toLegacyText( components ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void testDissembleReassemble(String json)
|
||||||
|
{
|
||||||
|
BaseComponent[] parsed = ComponentSerializer.parse( json );
|
||||||
|
Assert.assertEquals( json, ComponentSerializer.toString( parsed ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testItemParse()
|
||||||
|
{
|
||||||
|
// Declare all commonly used variables for reuse.
|
||||||
|
BaseComponent[] components;
|
||||||
|
TextComponent textComponent;
|
||||||
|
String json;
|
||||||
|
|
||||||
|
textComponent = new TextComponent( "Test" );
|
||||||
|
textComponent.setHoverEvent( new HoverEvent( HoverEvent.Action.SHOW_ITEM, new BaseComponent[]
|
||||||
|
{
|
||||||
|
new TextComponent( "{id:\"minecraft:netherrack\",Count:47b}" )
|
||||||
|
} ) );
|
||||||
|
testDissembleReassemble( new BaseComponent[]
|
||||||
|
{
|
||||||
|
textComponent
|
||||||
|
} );
|
||||||
|
json = "{\"text\":\"Test\",\"hoverEvent\":{\"action\":\"show_item\",\"value\":[{\"text\":\"{id:\\\"minecraft:netherrack\\\",Count:47b}\"}]}}";
|
||||||
|
testDissembleReassemble( json );
|
||||||
|
//////////
|
||||||
|
String hoverVal = "{\"text\":\"{id:\\\"minecraft:dirt\\\",Count:1b}\"}";
|
||||||
|
json = "{\"extra\":[{\"text\":\"[\"},{\"extra\":[{\"translate\":\"block.minecraft.dirt\"}],\"text\":\"\"},{\"text\":\"]\"}],\"hoverEvent\":{\"action\":\"show_item\",\"value\":[" + hoverVal + "]},\"text\":\"\"}";
|
||||||
|
components = ComponentSerializer.parse( json );
|
||||||
|
Text contentText = ( (Text) components[0].getHoverEvent().getContents().get( 0 ) );
|
||||||
|
Assert.assertEquals( hoverVal, ComponentSerializer.toString( (BaseComponent[]) contentText.getValue() ) );
|
||||||
|
testDissembleReassemble( components );
|
||||||
|
//////////
|
||||||
|
TextComponent component1 = new TextComponent( "HoverableText" );
|
||||||
|
String nbt = "{display:{Name:{text:Hello},Lore:[{text:Line_1},{text:Line_2}]},ench:[{id:49,lvl:5}],Unbreakable:1}}";
|
||||||
|
Item contentItem = new Item( "minecraft:wood", 1, ItemTag.ofNbt( nbt ) );
|
||||||
|
HoverEvent hoverEvent = new HoverEvent( HoverEvent.Action.SHOW_ITEM, contentItem );
|
||||||
|
component1.setHoverEvent( hoverEvent );
|
||||||
|
json = ComponentSerializer.toString( component1 );
|
||||||
|
components = ComponentSerializer.parse( json );
|
||||||
|
Item parsedContentItem = ( (Item) components[0].getHoverEvent().getContents().get( 0 ) );
|
||||||
|
Assert.assertEquals( contentItem, parsedContentItem );
|
||||||
|
Assert.assertEquals( contentItem.getCount(), parsedContentItem.getCount() );
|
||||||
|
Assert.assertEquals( contentItem.getId(), parsedContentItem.getId() );
|
||||||
|
Assert.assertEquals( nbt, parsedContentItem.getTag().getNbt() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEmptyComponentBuilder()
|
||||||
|
{
|
||||||
|
ComponentBuilder builder = new ComponentBuilder();
|
||||||
|
|
||||||
|
BaseComponent[] parts = builder.create();
|
||||||
|
Assert.assertEquals( parts.length, 0 );
|
||||||
|
|
||||||
|
for ( int i = 0; i < 3; i++ )
|
||||||
|
{
|
||||||
|
builder.append( "part:" + i );
|
||||||
|
parts = builder.create();
|
||||||
|
Assert.assertEquals( parts.length, i + 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDummyRetaining()
|
||||||
|
{
|
||||||
|
ComponentBuilder builder = new ComponentBuilder();
|
||||||
|
Assert.assertNotNull( builder.getCurrentComponent() );
|
||||||
|
builder.color( ChatColor.GREEN );
|
||||||
|
builder.append( "test ", ComponentBuilder.FormatRetention.ALL );
|
||||||
|
Assert.assertEquals( builder.getCurrentComponent().getColor(), ChatColor.GREEN );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IndexOutOfBoundsException.class)
|
||||||
|
public void testComponentGettingExceptions()
|
||||||
|
{
|
||||||
|
ComponentBuilder builder = new ComponentBuilder();
|
||||||
|
builder.getComponent( -1 );
|
||||||
|
builder.getComponent( 0 );
|
||||||
|
builder.getComponent( 1 );
|
||||||
|
BaseComponent component = new TextComponent( "Hello" );
|
||||||
|
builder.append( component );
|
||||||
|
Assert.assertEquals( builder.getComponent( 0 ), component );
|
||||||
|
builder.getComponent( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testComponentParting()
|
||||||
|
{
|
||||||
|
ComponentBuilder builder = new ComponentBuilder();
|
||||||
|
TextComponent apple = new TextComponent( "apple" );
|
||||||
|
builder.append( apple );
|
||||||
|
Assert.assertEquals( builder.getCurrentComponent(), apple );
|
||||||
|
Assert.assertEquals( builder.getComponent( 0 ), apple );
|
||||||
|
|
||||||
|
TextComponent mango = new TextComponent( "mango" );
|
||||||
|
TextComponent orange = new TextComponent( "orange" );
|
||||||
|
builder.append( mango );
|
||||||
|
builder.append( orange );
|
||||||
|
builder.removeComponent( 1 ); // Removing mango
|
||||||
|
Assert.assertEquals( builder.getComponent( 0 ), apple );
|
||||||
|
Assert.assertEquals( builder.getComponent( 1 ), orange );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testToLegacyFromLegacy()
|
||||||
|
{
|
||||||
|
String text = "§a§lHello §f§kworld§7!";
|
||||||
|
Assert.assertEquals( text, TextComponent.toLegacyText( TextComponent.fromLegacyText( text ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IndexOutOfBoundsException.class)
|
||||||
|
public void testComponentBuilderCursorInvalidPos()
|
||||||
|
{
|
||||||
|
ComponentBuilder builder = new ComponentBuilder();
|
||||||
|
builder.append( new TextComponent( "Apple, " ) );
|
||||||
|
builder.append( new TextComponent( "Orange, " ) );
|
||||||
|
builder.setCursor( -1 );
|
||||||
|
builder.setCursor( 2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testComponentBuilderCursor()
|
||||||
|
{
|
||||||
|
TextComponent t1, t2, t3;
|
||||||
|
ComponentBuilder builder = new ComponentBuilder();
|
||||||
|
Assert.assertEquals( builder.getCursor(), -1 );
|
||||||
|
builder.append( t1 = new TextComponent( "Apple, " ) );
|
||||||
|
Assert.assertEquals( builder.getCursor(), 0 );
|
||||||
|
builder.append( t2 = new TextComponent( "Orange, " ) );
|
||||||
|
builder.append( t3 = new TextComponent( "Mango, " ) );
|
||||||
|
Assert.assertEquals( builder.getCursor(), 2 );
|
||||||
|
|
||||||
|
builder.setCursor( 0 );
|
||||||
|
Assert.assertEquals( builder.getCurrentComponent(), t1 );
|
||||||
|
|
||||||
|
// Test that appending new components updates the position to the new list size
|
||||||
|
// after having previously set it to 0 (first component)
|
||||||
|
builder.append( new TextComponent( "and Grapefruit" ) );
|
||||||
|
Assert.assertEquals( builder.getCursor(), 3 );
|
||||||
|
|
||||||
|
builder.setCursor( 0 );
|
||||||
|
builder.resetCursor();
|
||||||
|
Assert.assertEquals( builder.getCursor(), 3 );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLegacyComponentBuilderAppend()
|
||||||
|
{
|
||||||
|
String text = "§a§lHello §r§kworld§7!";
|
||||||
|
BaseComponent[] components = TextComponent.fromLegacyText( text );
|
||||||
|
BaseComponent[] builderComponents = new ComponentBuilder().append( components ).create();
|
||||||
|
Assert.assertArrayEquals( components, builderComponents );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@Test
|
||||||
|
public void testItemTag()
|
||||||
|
{
|
||||||
|
TextComponent component = new TextComponent( "Hello world" );
|
||||||
|
HoverEvent.ContentItem content = new HoverEvent.ContentItem();
|
||||||
|
content.setId( "minecraft:diamond_sword" );
|
||||||
|
content.setCount( 1 );
|
||||||
|
content.setTag( ItemTag.builder()
|
||||||
|
.ench( new ItemTag.Enchantment( 5, 16 ) )
|
||||||
|
.name( new TextComponent( "Sharp Sword" ) )
|
||||||
|
.unbreakable( true )
|
||||||
|
.lore( new ComponentBuilder( "Line1" ).create() )
|
||||||
|
.lore( new ComponentBuilder( "Line2" ).create() )
|
||||||
|
.build() );
|
||||||
|
HoverEvent event = new HoverEvent( HoverEvent.Action.SHOW_ITEM, content );
|
||||||
|
component.setHoverEvent( event );
|
||||||
|
String serialised = ComponentSerializer.toString( component );
|
||||||
|
BaseComponent[] deserialised = ComponentSerializer.parse( serialised );
|
||||||
|
Assert.assertEquals( TextComponent.toLegacyText( deserialised ), TextComponent.toLegacyText( component ) );
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testModernShowAdvancement()
|
||||||
|
{
|
||||||
|
String advancement = "achievement.openInventory";
|
||||||
|
// First do the text using the newer contents system
|
||||||
|
HoverEvent hoverEvent = new HoverEvent(
|
||||||
|
HoverEvent.Action.SHOW_TEXT,
|
||||||
|
new Text( advancement )
|
||||||
|
);
|
||||||
|
TextComponent component = new TextComponent( "test" );
|
||||||
|
component.setHoverEvent( hoverEvent );
|
||||||
|
Assert.assertEquals( component.getHoverEvent().getContents().size(), 1 );
|
||||||
|
Assert.assertTrue( component.getHoverEvent().getContents().get( 0 ) instanceof Text );
|
||||||
|
Assert.assertEquals( ( (Text) component.getHoverEvent().getContents().get( 0 ) ).getValue(), advancement );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHoverEventContents()
|
||||||
|
{
|
||||||
|
// First do the text using the newer contents system
|
||||||
|
HoverEvent hoverEvent = new HoverEvent(
|
||||||
|
HoverEvent.Action.SHOW_TEXT,
|
||||||
|
new Text( new ComponentBuilder( "First" ).create() ),
|
||||||
|
new Text( new ComponentBuilder( "Second" ).create() )
|
||||||
|
);
|
||||||
|
|
||||||
|
TextComponent component = new TextComponent( "Sample text" );
|
||||||
|
component.setHoverEvent( hoverEvent );
|
||||||
|
Assert.assertEquals( hoverEvent.getContents().size(), 2 );
|
||||||
|
Assert.assertFalse( hoverEvent.isLegacy() );
|
||||||
|
String serialized = ComponentSerializer.toString( component );
|
||||||
|
BaseComponent[] deserialized = ComponentSerializer.parse( serialized );
|
||||||
|
Assert.assertEquals( component.getHoverEvent(), deserialized[0].getHoverEvent() );
|
||||||
|
|
||||||
|
// check the test still works with the value method
|
||||||
|
hoverEvent = new HoverEvent( HoverEvent.Action.SHOW_TEXT, new ComponentBuilder( "Sample text" ).create() );
|
||||||
|
Assert.assertEquals( hoverEvent.getContents().size(), 1 );
|
||||||
|
Assert.assertTrue( hoverEvent.isLegacy() );
|
||||||
|
serialized = ComponentSerializer.toString( component );
|
||||||
|
deserialized = ComponentSerializer.parse( serialized );
|
||||||
|
Assert.assertEquals( component.getHoverEvent(), deserialized[0].getHoverEvent() );
|
||||||
|
|
||||||
|
// Test single content:
|
||||||
|
String json = "{\"italic\":true,\"color\":\"gray\",\"translate\":\"chat.type.admin\",\"with\":[{\"text\":\"@\"}"
|
||||||
|
+ ",{\"translate\":\"commands.give.success.single\",\"with\":[\"1\",{\"color\":\"white\""
|
||||||
|
+ ",\"hoverEvent\":{\"action\":\"show_item\",\"contents\":{\"id\":\"minecraft:diamond_sword\",\"tag\":\""
|
||||||
|
+ "{Damage:0,display:{Lore:['\\\"test lore'!\\\"'],Name:'\\\"test\\\"'}}\"}},"
|
||||||
|
+ "\"extra\":[{\"italic\":true,\"extra\":[{\"text\":\"test\"}],\"text\":\"\"},{\"text\":\"]\"}],"
|
||||||
|
+ "\"text\":\"[\"},{\"insertion\":\"Name\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":"
|
||||||
|
+ "\"/tell Name \"},\"hoverEvent\":{\"action\":\"show_entity\",\"contents\":"
|
||||||
|
+ "{\"type\":\"minecraft:player\",\"id\":\"00000000-0000-0000-0000-00000000000000\",\"name\":"
|
||||||
|
+ "{\"text\":\"Name\"}}},\"text\":\"Name\"}]}]}";
|
||||||
|
testDissembleReassemble( ComponentSerializer.parse( json ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFormatRetentionCopyFormatting()
|
||||||
|
{
|
||||||
|
TextComponent first = new TextComponent( "Hello" );
|
||||||
|
first.setBold( true );
|
||||||
|
first.setColor( ChatColor.RED );
|
||||||
|
first.setClickEvent( new ClickEvent( ClickEvent.Action.RUN_COMMAND, "test" ) );
|
||||||
|
first.setHoverEvent( new HoverEvent( HoverEvent.Action.SHOW_TEXT, new ComponentBuilder( "Test" ).create() ) );
|
||||||
|
|
||||||
|
TextComponent second = new TextComponent( " world" );
|
||||||
|
second.copyFormatting( first, ComponentBuilder.FormatRetention.ALL, true );
|
||||||
|
Assert.assertEquals( first.isBold(), second.isBold() );
|
||||||
|
Assert.assertEquals( first.getColor(), second.getColor() );
|
||||||
|
Assert.assertEquals( first.getClickEvent(), second.getClickEvent() );
|
||||||
|
Assert.assertEquals( first.getHoverEvent(), second.getHoverEvent() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBuilderClone()
|
||||||
|
{
|
||||||
|
ComponentBuilder builder = new ComponentBuilder( "Hello " ).color( ChatColor.RED ).append( "world" ).color( ChatColor.DARK_RED );
|
||||||
|
ComponentBuilder cloned = new ComponentBuilder( builder );
|
||||||
|
|
||||||
|
Assert.assertEquals( TextComponent.toLegacyText( builder.create() ), TextComponent.toLegacyText( cloned.create() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBuilderAppendMixedComponents()
|
||||||
|
{
|
||||||
|
ComponentBuilder builder = new ComponentBuilder( "Hello " );
|
||||||
|
TextComponent textComponent = new TextComponent( "world " );
|
||||||
|
TranslatableComponent translatableComponent = new TranslatableComponent( "item.swordGold.name" );
|
||||||
|
// array based BaseComponent append
|
||||||
|
builder.append( new BaseComponent[]
|
||||||
|
{
|
||||||
|
textComponent,
|
||||||
|
translatableComponent
|
||||||
|
} );
|
||||||
|
ScoreComponent scoreComponent = new ScoreComponent( "myscore", "myobjective" );
|
||||||
|
builder.append( scoreComponent ); // non array based BaseComponent append
|
||||||
|
BaseComponent[] components = builder.create();
|
||||||
|
Assert.assertEquals( "Hello ", components[0].toPlainText() );
|
||||||
|
Assert.assertEquals( textComponent.toPlainText(), components[1].toPlainText() );
|
||||||
|
Assert.assertEquals( translatableComponent.toPlainText(), components[2].toPlainText() );
|
||||||
|
Assert.assertEquals( scoreComponent.toPlainText(), components[3].toPlainText() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testScore()
|
||||||
|
{
|
||||||
|
BaseComponent[] component = ComponentSerializer.parse( "{\"score\":{\"name\":\"@p\",\"objective\":\"TEST\",\"value\":\"hello\"}}" );
|
||||||
|
String text = ComponentSerializer.toString( component );
|
||||||
|
BaseComponent[] reparsed = ComponentSerializer.parse( text );
|
||||||
|
|
||||||
|
Assert.assertArrayEquals( component, reparsed );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBuilderAppend()
|
||||||
|
{
|
||||||
|
ClickEvent clickEvent = new ClickEvent( ClickEvent.Action.RUN_COMMAND, "/help " );
|
||||||
|
HoverEvent hoverEvent = new HoverEvent( HoverEvent.Action.SHOW_TEXT, new ComponentBuilder( "Hello world" ).create() );
|
||||||
|
|
||||||
|
ComponentBuilder builder = new ComponentBuilder( "Hello " ).color( ChatColor.YELLOW );
|
||||||
|
builder.append( new ComponentBuilder( "world!" ).color( ChatColor.GREEN ).event( hoverEvent ).event( clickEvent ).create() );
|
||||||
|
|
||||||
|
BaseComponent[] components = builder.create();
|
||||||
|
|
||||||
|
Assert.assertEquals( components[1].getHoverEvent(), hoverEvent );
|
||||||
|
Assert.assertEquals( components[1].getClickEvent(), clickEvent );
|
||||||
|
Assert.assertEquals( "Hello world!", BaseComponent.toPlainText( components ) );
|
||||||
|
Assert.assertEquals( ChatColor.YELLOW + "Hello " + ChatColor.GREEN + "world!", BaseComponent.toLegacyText( components ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBuilderAppendLegacy()
|
||||||
|
{
|
||||||
|
ComponentBuilder builder = new ComponentBuilder( "Hello " ).color( ChatColor.YELLOW );
|
||||||
|
builder.appendLegacy( "§aworld!" );
|
||||||
|
|
||||||
|
BaseComponent[] components = builder.create();
|
||||||
|
|
||||||
|
Assert.assertEquals( "Hello world!", BaseComponent.toPlainText( components ) );
|
||||||
|
Assert.assertEquals( ChatColor.YELLOW + "Hello " + ChatColor.GREEN + "world!", BaseComponent.toLegacyText( components ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBasicComponent()
|
||||||
|
{
|
||||||
|
TextComponent textComponent = new TextComponent( "Hello world" );
|
||||||
|
textComponent.setColor( ChatColor.RED );
|
||||||
|
|
||||||
|
Assert.assertEquals( "Hello world", textComponent.toPlainText() );
|
||||||
|
Assert.assertEquals( ChatColor.RED + "Hello world", textComponent.toLegacyText() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLegacyConverter()
|
||||||
|
{
|
||||||
|
BaseComponent[] test1 = TextComponent.fromLegacyText( ChatColor.AQUA + "Aqua " + ChatColor.RED + ChatColor.BOLD + "RedBold" );
|
||||||
|
|
||||||
|
Assert.assertEquals( "Aqua RedBold", BaseComponent.toPlainText( test1 ) );
|
||||||
|
Assert.assertEquals( ChatColor.AQUA + "Aqua " + ChatColor.RED + ChatColor.BOLD + "RedBold", BaseComponent.toLegacyText( test1 ) );
|
||||||
|
|
||||||
|
BaseComponent[] test2 = TextComponent.fromLegacyText( "Text http://spigotmc.org " + ChatColor.GREEN + "google.com/test" );
|
||||||
|
|
||||||
|
Assert.assertEquals( "Text http://spigotmc.org google.com/test", BaseComponent.toPlainText( test2 ) );
|
||||||
|
//The extra ChatColor instances are sometimes inserted when not needed but it doesn't change the result
|
||||||
|
Assert.assertEquals( ChatColor.WHITE + "Text " + ChatColor.WHITE + "http://spigotmc.org" + ChatColor.WHITE
|
||||||
|
+ " " + ChatColor.GREEN + "google.com/test" + ChatColor.GREEN, BaseComponent.toLegacyText( test2 ) );
|
||||||
|
|
||||||
|
ClickEvent url1 = test2[1].getClickEvent();
|
||||||
|
Assert.assertNotNull( url1 );
|
||||||
|
Assert.assertTrue( url1.getAction() == ClickEvent.Action.OPEN_URL );
|
||||||
|
Assert.assertEquals( "http://spigotmc.org", url1.getValue() );
|
||||||
|
|
||||||
|
ClickEvent url2 = test2[3].getClickEvent();
|
||||||
|
Assert.assertNotNull( url2 );
|
||||||
|
Assert.assertTrue( url2.getAction() == ClickEvent.Action.OPEN_URL );
|
||||||
|
Assert.assertEquals( "http://google.com/test", url2.getValue() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTranslateComponent()
|
||||||
|
{
|
||||||
|
TranslatableComponent item = new TranslatableComponent( "item.swordGold.name" );
|
||||||
|
item.setColor( ChatColor.AQUA );
|
||||||
|
TranslatableComponent translatableComponent = new TranslatableComponent( "commands.give.success",
|
||||||
|
item, "5",
|
||||||
|
"thinkofdeath" );
|
||||||
|
|
||||||
|
Assert.assertEquals( "Given Golden Sword * 5 to thinkofdeath", translatableComponent.toPlainText() );
|
||||||
|
Assert.assertEquals( ChatColor.WHITE + "Given " + ChatColor.AQUA + "Golden Sword" + ChatColor.WHITE
|
||||||
|
+ " * " + ChatColor.WHITE + "5" + ChatColor.WHITE + " to " + ChatColor.WHITE + "thinkofdeath",
|
||||||
|
translatableComponent.toLegacyText() );
|
||||||
|
|
||||||
|
TranslatableComponent positional = new TranslatableComponent( "book.pageIndicator", "5", "50" );
|
||||||
|
|
||||||
|
Assert.assertEquals( "Page 5 of 50", positional.toPlainText() );
|
||||||
|
Assert.assertEquals( ChatColor.WHITE + "Page " + ChatColor.WHITE + "5" + ChatColor.WHITE + " of " + ChatColor.WHITE + "50", positional.toLegacyText() );
|
||||||
|
|
||||||
|
TranslatableComponent one_four_two = new TranslatableComponent( "filled_map.buried_treasure" );
|
||||||
|
Assert.assertEquals( "Buried Treasure Map", one_four_two.toPlainText() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBuilder()
|
||||||
|
{
|
||||||
|
BaseComponent[] components = new ComponentBuilder( "Hello " ).color( ChatColor.RED ).
|
||||||
|
append( "World" ).bold( true ).color( ChatColor.BLUE ).
|
||||||
|
append( "!" ).color( ChatColor.YELLOW ).create();
|
||||||
|
|
||||||
|
Assert.assertEquals( "Hello World!", BaseComponent.toPlainText( components ) );
|
||||||
|
Assert.assertEquals( ChatColor.RED + "Hello " + ChatColor.BLUE + ChatColor.BOLD
|
||||||
|
+ "World" + ChatColor.YELLOW + ChatColor.BOLD + "!", BaseComponent.toLegacyText( components ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBuilderReset()
|
||||||
|
{
|
||||||
|
BaseComponent[] components = new ComponentBuilder( "Hello " ).color( ChatColor.RED )
|
||||||
|
.append( "World" ).reset().create();
|
||||||
|
|
||||||
|
Assert.assertEquals( components[0].getColor(), ChatColor.RED );
|
||||||
|
Assert.assertEquals( components[1].getColor(), ChatColor.WHITE );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBuilderFormatRetention()
|
||||||
|
{
|
||||||
|
BaseComponent[] noneRetention = new ComponentBuilder( "Hello " ).color( ChatColor.RED )
|
||||||
|
.append( "World", ComponentBuilder.FormatRetention.NONE ).create();
|
||||||
|
|
||||||
|
Assert.assertEquals( noneRetention[0].getColor(), ChatColor.RED );
|
||||||
|
Assert.assertEquals( noneRetention[1].getColor(), ChatColor.WHITE );
|
||||||
|
|
||||||
|
HoverEvent testEvent = new HoverEvent( HoverEvent.Action.SHOW_TEXT, new ComponentBuilder( "test" ).create() );
|
||||||
|
|
||||||
|
BaseComponent[] formattingRetention = new ComponentBuilder( "Hello " ).color( ChatColor.RED )
|
||||||
|
.event( testEvent ).append( "World", ComponentBuilder.FormatRetention.FORMATTING ).create();
|
||||||
|
|
||||||
|
Assert.assertEquals( formattingRetention[0].getColor(), ChatColor.RED );
|
||||||
|
Assert.assertEquals( formattingRetention[0].getHoverEvent(), testEvent );
|
||||||
|
Assert.assertEquals( formattingRetention[1].getColor(), ChatColor.RED );
|
||||||
|
Assert.assertNull( formattingRetention[1].getHoverEvent() );
|
||||||
|
|
||||||
|
ClickEvent testClickEvent = new ClickEvent( ClickEvent.Action.OPEN_URL, "http://www.example.com" );
|
||||||
|
|
||||||
|
BaseComponent[] eventRetention = new ComponentBuilder( "Hello " ).color( ChatColor.RED )
|
||||||
|
.event( testEvent ).event( testClickEvent ).append( "World", ComponentBuilder.FormatRetention.EVENTS ).create();
|
||||||
|
|
||||||
|
Assert.assertEquals( eventRetention[0].getColor(), ChatColor.RED );
|
||||||
|
Assert.assertEquals( eventRetention[0].getHoverEvent(), testEvent );
|
||||||
|
Assert.assertEquals( eventRetention[0].getClickEvent(), testClickEvent );
|
||||||
|
Assert.assertEquals( eventRetention[1].getColor(), ChatColor.WHITE );
|
||||||
|
Assert.assertEquals( eventRetention[1].getHoverEvent(), testEvent );
|
||||||
|
Assert.assertEquals( eventRetention[1].getClickEvent(), testClickEvent );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void testLoopSimple()
|
||||||
|
{
|
||||||
|
TextComponent component = new TextComponent( "Testing" );
|
||||||
|
component.addExtra( component );
|
||||||
|
ComponentSerializer.toString( component );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void testLoopComplex()
|
||||||
|
{
|
||||||
|
TextComponent a = new TextComponent( "A" );
|
||||||
|
TextComponent b = new TextComponent( "B" );
|
||||||
|
b.setColor( ChatColor.AQUA );
|
||||||
|
TextComponent c = new TextComponent( "C" );
|
||||||
|
c.setColor( ChatColor.RED );
|
||||||
|
a.addExtra( b );
|
||||||
|
b.addExtra( c );
|
||||||
|
c.addExtra( a );
|
||||||
|
ComponentSerializer.toString( a );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRepeated()
|
||||||
|
{
|
||||||
|
TextComponent a = new TextComponent( "A" );
|
||||||
|
TextComponent b = new TextComponent( "B" );
|
||||||
|
b.setColor( ChatColor.AQUA );
|
||||||
|
a.addExtra( b );
|
||||||
|
a.addExtra( b );
|
||||||
|
ComponentSerializer.toString( a );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void testRepeatedError()
|
||||||
|
{
|
||||||
|
TextComponent a = new TextComponent( "A" );
|
||||||
|
TextComponent b = new TextComponent( "B" );
|
||||||
|
b.setColor( ChatColor.AQUA );
|
||||||
|
TextComponent c = new TextComponent( "C" );
|
||||||
|
c.setColor( ChatColor.RED );
|
||||||
|
a.addExtra( b );
|
||||||
|
a.addExtra( c );
|
||||||
|
c.addExtra( a );
|
||||||
|
a.addExtra( b );
|
||||||
|
ComponentSerializer.toString( a );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInvalidColorCodes()
|
||||||
|
{
|
||||||
|
StringBuilder allInvalidColorCodes = new StringBuilder();
|
||||||
|
|
||||||
|
// collect all invalid color codes (e.g. §z, §g, ...)
|
||||||
|
for ( char alphChar : "0123456789abcdefghijklmnopqrstuvwxyz".toCharArray() )
|
||||||
|
{
|
||||||
|
if ( ChatColor.ALL_CODES.indexOf( alphChar ) == -1 )
|
||||||
|
{
|
||||||
|
allInvalidColorCodes.append( ChatColor.COLOR_CHAR );
|
||||||
|
allInvalidColorCodes.append( alphChar );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// last char is a single '§'
|
||||||
|
allInvalidColorCodes.append( ChatColor.COLOR_CHAR );
|
||||||
|
|
||||||
|
String invalidColorCodesLegacyText = fromAndToLegacyText( allInvalidColorCodes.toString() );
|
||||||
|
String emptyLegacyText = fromAndToLegacyText( "" );
|
||||||
|
|
||||||
|
// all invalid color codes and the trailing '§' should be ignored
|
||||||
|
Assert.assertEquals( emptyLegacyText, invalidColorCodesLegacyText );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFormattingOnlyTextConversion()
|
||||||
|
{
|
||||||
|
String text = "§a";
|
||||||
|
|
||||||
|
BaseComponent[] converted = TextComponent.fromLegacyText( text );
|
||||||
|
Assert.assertEquals( ChatColor.GREEN, converted[0].getColor() );
|
||||||
|
|
||||||
|
String roundtripLegacyText = BaseComponent.toLegacyText( converted );
|
||||||
|
|
||||||
|
// color code should not be lost during conversion
|
||||||
|
Assert.assertEquals( text, roundtripLegacyText );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEquals()
|
||||||
|
{
|
||||||
|
TextComponent first = new TextComponent( "Hello, " );
|
||||||
|
first.addExtra( new TextComponent( "World!" ) );
|
||||||
|
|
||||||
|
TextComponent second = new TextComponent( "Hello, " );
|
||||||
|
second.addExtra( new TextComponent( "World!" ) );
|
||||||
|
|
||||||
|
Assert.assertEquals( first, second );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNotEquals()
|
||||||
|
{
|
||||||
|
TextComponent first = new TextComponent( "Hello, " );
|
||||||
|
first.addExtra( new TextComponent( "World." ) );
|
||||||
|
|
||||||
|
TextComponent second = new TextComponent( "Hello, " );
|
||||||
|
second.addExtra( new TextComponent( "World!" ) );
|
||||||
|
|
||||||
|
Assert.assertNotEquals( first, second );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLegacyHack()
|
||||||
|
{
|
||||||
|
BaseComponent[] hexColored = new ComponentBuilder().color( ChatColor.of( Color.GRAY ) ).append( "Test" ).create();
|
||||||
|
String legacy = TextComponent.toLegacyText( hexColored );
|
||||||
|
|
||||||
|
BaseComponent[] reColored = TextComponent.fromLegacyText( legacy );
|
||||||
|
|
||||||
|
Assert.assertArrayEquals( hexColored, reColored );
|
||||||
|
}
|
||||||
|
|
||||||
|
private String fromAndToLegacyText(String legacyText)
|
||||||
|
{
|
||||||
|
return BaseComponent.toLegacyText( TextComponent.fromLegacyText( legacyText ) );
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,28 @@
|
|||||||
|
package net.md_5.bungee.api.chat;
|
||||||
|
|
||||||
|
import net.md_5.bungee.chat.ComponentSerializer;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class TranslatableComponentTest
|
||||||
|
{
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMissingPlaceholdersAdded()
|
||||||
|
{
|
||||||
|
TranslatableComponent testComponent = new TranslatableComponent( "Test string with %s placeholders: %s", 2, "aoeu" );
|
||||||
|
Assert.assertEquals( "Test string with 2 placeholders: aoeu", testComponent.toPlainText() );
|
||||||
|
Assert.assertEquals( "§fTest string with §f2§f placeholders: §faoeu", testComponent.toLegacyText() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testJsonSerialisation()
|
||||||
|
{
|
||||||
|
TranslatableComponent testComponent = new TranslatableComponent( "Test string with %s placeholder", "a" );
|
||||||
|
String jsonString = ComponentSerializer.toString( testComponent );
|
||||||
|
BaseComponent[] baseComponents = ComponentSerializer.parse( jsonString );
|
||||||
|
|
||||||
|
Assert.assertEquals( "Test string with a placeholder", TextComponent.toPlainText( baseComponents ) );
|
||||||
|
Assert.assertEquals( "§fTest string with §fa§f placeholder", TextComponent.toLegacyText( baseComponents ) );
|
||||||
|
}
|
||||||
|
}
|
@@ -33,9 +33,9 @@
|
|||||||
|
|
||||||
<!-- See http://checkstyle.sourceforge.net/config_filters.html -->
|
<!-- See http://checkstyle.sourceforge.net/config_filters.html -->
|
||||||
<module name="SuppressionCommentFilter"/>
|
<module name="SuppressionCommentFilter"/>
|
||||||
<module name="SuppressWarningsHolder"/>
|
|
||||||
|
|
||||||
<!-- See http://checkstyle.sourceforge.net/config_imports.html -->
|
<!-- See http://checkstyle.sourceforge.net/config_imports.html -->
|
||||||
|
<module name="AvoidStarImport"/>
|
||||||
<module name="ImportOrder">
|
<module name="ImportOrder">
|
||||||
<property name="option" value="above"/>
|
<property name="option" value="above"/>
|
||||||
<property name="ordered" value="true"/>
|
<property name="ordered" value="true"/>
|
||||||
@@ -54,11 +54,11 @@
|
|||||||
<module name="OperatorWrap"/>
|
<module name="OperatorWrap"/>
|
||||||
<module name="ParenPad">
|
<module name="ParenPad">
|
||||||
<property name="option" value="nospace"/>
|
<property name="option" value="nospace"/>
|
||||||
<property name="tokens" value="ANNOTATION, CTOR_DEF, METHOD_DEF, LAMBDA"/>
|
<property name="tokens" value="ANNOTATION, CTOR_DEF, METHOD_DEF"/>
|
||||||
</module>
|
</module>
|
||||||
<module name="ParenPad">
|
<module name="ParenPad">
|
||||||
<property name="option" value="space"/>
|
<property name="option" value="space"/>
|
||||||
<property name="tokens" value="ANNOTATION_FIELD_DEF, CTOR_CALL, DOT, ENUM_CONSTANT_DEF, EXPR, LITERAL_CATCH, LITERAL_DO, LITERAL_FOR, LITERAL_IF, LITERAL_NEW, LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_WHILE, METHOD_CALL, QUESTION, RESOURCE_SPECIFICATION, SUPER_CTOR_CALL, RECORD_DEF"/>
|
<property name="tokens" value="ANNOTATION_FIELD_DEF, CTOR_CALL, DOT, ENUM_CONSTANT_DEF, EXPR, LITERAL_CATCH, LITERAL_DO, LITERAL_FOR, LITERAL_IF, LITERAL_NEW, LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_WHILE, METHOD_CALL, QUESTION, RESOURCE_SPECIFICATION, SUPER_CTOR_CALL, LAMBDA"/>
|
||||||
</module>
|
</module>
|
||||||
<module name="SingleSpaceSeparator"/>
|
<module name="SingleSpaceSeparator"/>
|
||||||
<module name="TypecastParenPad"/>
|
<module name="TypecastParenPad"/>
|
||||||
@@ -84,6 +84,4 @@
|
|||||||
<module name="Indentation"/>
|
<module name="Indentation"/>
|
||||||
<module name="UpperEll"/>
|
<module name="UpperEll"/>
|
||||||
</module>
|
</module>
|
||||||
|
|
||||||
<module name="SuppressWarningsFilter"/>
|
|
||||||
</module>
|
</module>
|
||||||
|
@@ -6,13 +6,13 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>net.md-5</groupId>
|
<groupId>net.md-5</groupId>
|
||||||
<artifactId>bungeecord-parent</artifactId>
|
<artifactId>bungeecord-parent</artifactId>
|
||||||
<version>1.21-R0.4-SNAPSHOT</version>
|
<version>1.16-R0.4-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<groupId>net.md-5</groupId>
|
<groupId>net.md-5</groupId>
|
||||||
<artifactId>bungeecord-config</artifactId>
|
<artifactId>bungeecord-config</artifactId>
|
||||||
<version>1.21-R0.4-SNAPSHOT</version>
|
<version>1.16-R0.4-SNAPSHOT</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>BungeeCord-Config</name>
|
<name>BungeeCord-Config</name>
|
||||||
@@ -22,14 +22,14 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.code.gson</groupId>
|
<groupId>com.google.code.gson</groupId>
|
||||||
<artifactId>gson</artifactId>
|
<artifactId>gson</artifactId>
|
||||||
<version>2.11.0</version>
|
<version>2.8.0</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.yaml</groupId>
|
<groupId>org.yaml</groupId>
|
||||||
<artifactId>snakeyaml</artifactId>
|
<artifactId>snakeyaml</artifactId>
|
||||||
<version>2.2</version>
|
<version>1.26</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
package net.md_5.bungee.config;
|
package net.md_5.bungee.config;
|
||||||
|
|
||||||
|
import com.google.common.base.Charsets;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
@@ -15,7 +16,6 @@ import java.io.OutputStreamWriter;
|
|||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
@@ -37,7 +37,7 @@ public class JsonConfiguration extends ConfigurationProvider
|
|||||||
@Override
|
@Override
|
||||||
public void save(Configuration config, File file) throws IOException
|
public void save(Configuration config, File file) throws IOException
|
||||||
{
|
{
|
||||||
try ( Writer writer = new OutputStreamWriter( new FileOutputStream( file ), StandardCharsets.UTF_8 ) )
|
try ( Writer writer = new OutputStreamWriter( new FileOutputStream( file ), Charsets.UTF_8 ) )
|
||||||
{
|
{
|
||||||
save( config, writer );
|
save( config, writer );
|
||||||
}
|
}
|
||||||
@@ -91,7 +91,7 @@ public class JsonConfiguration extends ConfigurationProvider
|
|||||||
@Override
|
@Override
|
||||||
public Configuration load(InputStream is, Configuration defaults)
|
public Configuration load(InputStream is, Configuration defaults)
|
||||||
{
|
{
|
||||||
return load( new InputStreamReader( is, StandardCharsets.UTF_8 ), defaults );
|
return load( new InputStreamReader( is, Charsets.UTF_8 ), defaults );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
package net.md_5.bungee.config;
|
package net.md_5.bungee.config;
|
||||||
|
|
||||||
|
import com.google.common.base.Charsets;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
@@ -8,13 +9,11 @@ import java.io.InputStream;
|
|||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import org.yaml.snakeyaml.DumperOptions;
|
import org.yaml.snakeyaml.DumperOptions;
|
||||||
import org.yaml.snakeyaml.LoaderOptions;
|
|
||||||
import org.yaml.snakeyaml.Yaml;
|
import org.yaml.snakeyaml.Yaml;
|
||||||
import org.yaml.snakeyaml.constructor.Constructor;
|
import org.yaml.snakeyaml.constructor.Constructor;
|
||||||
import org.yaml.snakeyaml.nodes.Node;
|
import org.yaml.snakeyaml.nodes.Node;
|
||||||
@@ -30,10 +29,7 @@ public class YamlConfiguration extends ConfigurationProvider
|
|||||||
@Override
|
@Override
|
||||||
protected Yaml initialValue()
|
protected Yaml initialValue()
|
||||||
{
|
{
|
||||||
DumperOptions options = new DumperOptions();
|
Representer representer = new Representer()
|
||||||
options.setDefaultFlowStyle( DumperOptions.FlowStyle.BLOCK );
|
|
||||||
|
|
||||||
Representer representer = new Representer( options )
|
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
representers.put( Configuration.class, new Represent()
|
representers.put( Configuration.class, new Represent()
|
||||||
@@ -47,14 +43,17 @@ public class YamlConfiguration extends ConfigurationProvider
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return new Yaml( new Constructor( new LoaderOptions() ), representer, options );
|
DumperOptions options = new DumperOptions();
|
||||||
|
options.setDefaultFlowStyle( DumperOptions.FlowStyle.BLOCK );
|
||||||
|
|
||||||
|
return new Yaml( new Constructor(), representer, options );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void save(Configuration config, File file) throws IOException
|
public void save(Configuration config, File file) throws IOException
|
||||||
{
|
{
|
||||||
try ( Writer writer = new OutputStreamWriter( new FileOutputStream( file ), StandardCharsets.UTF_8 ) )
|
try ( Writer writer = new OutputStreamWriter( new FileOutputStream( file ), Charsets.UTF_8 ) )
|
||||||
{
|
{
|
||||||
save( config, writer );
|
save( config, writer );
|
||||||
}
|
}
|
||||||
|
@@ -1,25 +1,30 @@
|
|||||||
package net.md_5.bungee.config;
|
package net.md_5.bungee.config;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Stream;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
import org.junit.Assert;
|
||||||
import org.junit.jupiter.params.provider.Arguments;
|
import org.junit.Test;
|
||||||
import org.junit.jupiter.params.provider.MethodSource;
|
import org.junit.runner.RunWith;
|
||||||
|
import org.junit.runners.Parameterized;
|
||||||
|
import org.junit.runners.Parameterized.Parameters;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
|
@RunWith(Parameterized.class)
|
||||||
public class CompoundConfigurationTest
|
public class CompoundConfigurationTest
|
||||||
{
|
{
|
||||||
|
|
||||||
public static Stream<Arguments> data()
|
@Parameters(name = "{0}")
|
||||||
|
public static Iterable<Object[]> data()
|
||||||
|
{
|
||||||
|
// CHECKSTYLE:OFF
|
||||||
|
return Arrays.asList( new Object[][]
|
||||||
|
{
|
||||||
{
|
{
|
||||||
return Stream.of(
|
|
||||||
Arguments.of(
|
|
||||||
// provider
|
// provider
|
||||||
YamlConfiguration.class,
|
YamlConfiguration.class,
|
||||||
// testDocument
|
// testDocument
|
||||||
@@ -68,8 +73,8 @@ public class CompoundConfigurationTest
|
|||||||
+ "null:\n"
|
+ "null:\n"
|
||||||
+ " null: object\n"
|
+ " null: object\n"
|
||||||
+ " object: null\n"
|
+ " object: null\n"
|
||||||
),
|
},
|
||||||
Arguments.of(
|
{
|
||||||
// provider
|
// provider
|
||||||
JsonConfiguration.class,
|
JsonConfiguration.class,
|
||||||
// testDocument
|
// testDocument
|
||||||
@@ -126,13 +131,18 @@ public class CompoundConfigurationTest
|
|||||||
+ " \"object\": null\n"
|
+ " \"object\": null\n"
|
||||||
+ " }\n"
|
+ " }\n"
|
||||||
+ "}"
|
+ "}"
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
} );
|
||||||
|
// CHECKSTYLE:ON
|
||||||
|
}
|
||||||
|
//
|
||||||
|
private final Class<? extends ConfigurationProvider> provider;
|
||||||
|
private final String testDocument;
|
||||||
|
private final String numberTest;
|
||||||
|
private final String nullTest;
|
||||||
|
|
||||||
@ParameterizedTest
|
@Test
|
||||||
@MethodSource("data")
|
public void testConfig() throws Exception
|
||||||
public void testConfig(Class<? extends ConfigurationProvider> provider, String testDocument, String numberTest, String nullTest) throws Exception
|
|
||||||
{
|
{
|
||||||
Configuration conf = ConfigurationProvider.getProvider( provider ).load( testDocument );
|
Configuration conf = ConfigurationProvider.getProvider( provider ).load( testDocument );
|
||||||
testSection( conf );
|
testSection( conf );
|
||||||
@@ -141,7 +151,7 @@ public class CompoundConfigurationTest
|
|||||||
ConfigurationProvider.getProvider( provider ).save( conf, sw );
|
ConfigurationProvider.getProvider( provider ).save( conf, sw );
|
||||||
|
|
||||||
// Check nulls were saved, see #1094
|
// Check nulls were saved, see #1094
|
||||||
assertFalse( sw.toString().contains( "null" ), "Config contains null" );
|
Assert.assertFalse( "Config contains null", sw.toString().contains( "null" ) );
|
||||||
|
|
||||||
conf = ConfigurationProvider.getProvider( provider ).load( new StringReader( sw.toString() ) );
|
conf = ConfigurationProvider.getProvider( provider ).load( new StringReader( sw.toString() ) );
|
||||||
conf.set( "receipt", "Oz-Ware Purchase Invoice" ); // Add it back
|
conf.set( "receipt", "Oz-Ware Purchase Invoice" ); // Add it back
|
||||||
@@ -150,38 +160,37 @@ public class CompoundConfigurationTest
|
|||||||
|
|
||||||
private void testSection(Configuration conf)
|
private void testSection(Configuration conf)
|
||||||
{
|
{
|
||||||
assertEquals( "Oz-Ware Purchase Invoice", conf.getString( "receipt" ), "receipt" );
|
Assert.assertEquals( "receipt", "Oz-Ware Purchase Invoice", conf.getString( "receipt" ) );
|
||||||
// assertEquals( "2012-08-06", conf.get( "date" ).toString(), "date" );
|
// Assert.assertEquals( "date", "2012-08-06", conf.get( "date" ).toString() );
|
||||||
|
|
||||||
Configuration customer = conf.getSection( "customer" );
|
Configuration customer = conf.getSection( "customer" );
|
||||||
assertEquals( "Dorothy", customer.getString( "given" ), "customer.given" );
|
Assert.assertEquals( "customer.given", "Dorothy", customer.getString( "given" ) );
|
||||||
assertEquals( "Dorothy", conf.getString( "customer.given" ), "customer.given" );
|
Assert.assertEquals( "customer.given", "Dorothy", conf.getString( "customer.given" ) );
|
||||||
|
|
||||||
List items = conf.getList( "items" );
|
List items = conf.getList( "items" );
|
||||||
Map item = (Map) items.get( 0 );
|
Map item = (Map) items.get( 0 );
|
||||||
assertEquals( "A4786", item.get( "part_no" ), "items[0].part_no" );
|
Assert.assertEquals( "items[0].part_no", "A4786", item.get( "part_no" ) );
|
||||||
|
|
||||||
conf.set( "receipt", null );
|
conf.set( "receipt", null );
|
||||||
assertEquals( null, conf.get( "receipt" ) );
|
Assert.assertEquals( null, conf.get( "receipt" ) );
|
||||||
assertEquals( "foo", conf.get( "receipt", "foo" ) );
|
Assert.assertEquals( "foo", conf.get( "receipt", "foo" ) );
|
||||||
|
|
||||||
Configuration newSection = conf.getSection( "new.section" );
|
Configuration newSection = conf.getSection( "new.section" );
|
||||||
newSection.set( "value", "foo" );
|
newSection.set( "value", "foo" );
|
||||||
assertEquals( "foo", conf.get( "new.section.value" ) );
|
Assert.assertEquals( "foo", conf.get( "new.section.value" ) );
|
||||||
|
|
||||||
conf.set( "other.new.section", "bar" );
|
conf.set( "other.new.section", "bar" );
|
||||||
assertEquals( "bar", conf.get( "other.new.section" ) );
|
Assert.assertEquals( "bar", conf.get( "other.new.section" ) );
|
||||||
|
|
||||||
assertTrue( conf.contains( "customer.given" ) );
|
Assert.assertTrue( conf.contains( "customer.given" ) );
|
||||||
assertTrue( customer.contains( "given" ) );
|
Assert.assertTrue( customer.contains( "given" ) );
|
||||||
|
|
||||||
assertFalse( conf.contains( "customer.foo" ) );
|
Assert.assertFalse( conf.contains( "customer.foo" ) );
|
||||||
assertFalse( customer.contains( "foo" ) );
|
Assert.assertFalse( customer.contains( "foo" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@Test
|
||||||
@MethodSource("data")
|
public void testNumberedKeys()
|
||||||
public void testNumberedKeys(Class<? extends ConfigurationProvider> provider, String testDocument, String numberTest, String nullTest)
|
|
||||||
{
|
{
|
||||||
Configuration conf = ConfigurationProvider.getProvider( provider ).load( numberTest );
|
Configuration conf = ConfigurationProvider.getProvider( provider ).load( numberTest );
|
||||||
|
|
||||||
@@ -192,31 +201,29 @@ public class CompoundConfigurationTest
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@Test
|
||||||
@MethodSource("data")
|
public void testNull()
|
||||||
public void testNull(Class<? extends ConfigurationProvider> provider, String testDocument, String numberTest, String nullTest)
|
|
||||||
{
|
{
|
||||||
Configuration conf = ConfigurationProvider.getProvider( provider ).load( nullTest );
|
Configuration conf = ConfigurationProvider.getProvider( provider ).load( nullTest );
|
||||||
|
|
||||||
assertEquals( "object", conf.get( "null.null" ) );
|
Assert.assertEquals( "object", conf.get( "null.null" ) );
|
||||||
assertEquals( "object", conf.getSection( "null" ).get( "null" ) );
|
Assert.assertEquals( "object", conf.getSection( "null" ).get( "null" ) );
|
||||||
|
|
||||||
assertEquals( null, conf.get( "null.object" ) );
|
Assert.assertEquals( null, conf.get( "null.object" ) );
|
||||||
assertEquals( "", conf.getString( "null.object" ) );
|
Assert.assertEquals( "", conf.getString( "null.object" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@Test
|
||||||
@MethodSource("data")
|
public void testMapAddition()
|
||||||
public void testMapAddition(Class<? extends ConfigurationProvider> provider, String testDocument, String numberTest, String nullTest)
|
|
||||||
{
|
{
|
||||||
Configuration conf = ConfigurationProvider.getProvider( provider ).load( testDocument );
|
Configuration conf = ConfigurationProvider.getProvider( provider ).load( testDocument );
|
||||||
|
|
||||||
conf.set( "addition", Collections.singletonMap( "foo", "bar" ) );
|
conf.set( "addition", Collections.singletonMap( "foo", "bar" ) );
|
||||||
|
|
||||||
// Order matters
|
// Order matters
|
||||||
assertEquals( "bar", conf.getSection( "addition" ).getString( "foo" ) );
|
Assert.assertEquals( "bar", conf.getSection( "addition" ).getString( "foo" ) );
|
||||||
assertEquals( "bar", conf.getString( "addition.foo" ) );
|
Assert.assertEquals( "bar", conf.getString( "addition.foo" ) );
|
||||||
|
|
||||||
assertTrue( conf.get( "addition" ) instanceof Configuration );
|
Assert.assertTrue( conf.get( "addition" ) instanceof Configuration );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
package net.md_5.bungee.config;
|
package net.md_5.bungee.config;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import org.junit.Assert;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class DefaultConfigurationTest
|
public class DefaultConfigurationTest
|
||||||
{
|
{
|
||||||
@@ -16,8 +16,8 @@ public class DefaultConfigurationTest
|
|||||||
|
|
||||||
Configuration actualConfig = new Configuration( defaultConfig );
|
Configuration actualConfig = new Configuration( defaultConfig );
|
||||||
|
|
||||||
assertEquals( 10, actualConfig.getInt( "setting" ) );
|
Assert.assertEquals( 10, actualConfig.getInt( "setting" ) );
|
||||||
assertEquals( 11, actualConfig.getInt( "nested.setting" ) );
|
Assert.assertEquals( 11, actualConfig.getInt( "nested.setting" ) );
|
||||||
assertEquals( 12, actualConfig.getInt( "double.nested.setting" ) );
|
Assert.assertEquals( 12, actualConfig.getInt( "double.nested.setting" ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,28 +0,0 @@
|
|||||||
BSD 3-Clause License
|
|
||||||
|
|
||||||
Copyright (c) 2025, SpigotMC Pty. Ltd.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
3. Neither the name of the copyright holder nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
||||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -1,38 +0,0 @@
|
|||||||
BungeeCord-Dialog
|
|
||||||
=================
|
|
||||||
|
|
||||||
Highly experimental API, subject to breakage. All contributions welcome, including major refactors/design changes.
|
|
||||||
|
|
||||||
Sample Plugin
|
|
||||||
-------------
|
|
||||||
|
|
||||||
```java
|
|
||||||
private class TestCommand extends Command
|
|
||||||
{
|
|
||||||
|
|
||||||
public TestCommand()
|
|
||||||
{
|
|
||||||
super( "btest" );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(CommandSender sender, String[] args)
|
|
||||||
{
|
|
||||||
ProxiedPlayer player = (ProxiedPlayer) sender;
|
|
||||||
|
|
||||||
Dialog notice = new NoticeDialog( new DialogBase( new ComponentBuilder( "Hello" ).color( ChatColor.RED ).build() ) );
|
|
||||||
player.showDialog( notice );
|
|
||||||
|
|
||||||
notice = new NoticeDialog(
|
|
||||||
new DialogBase( new ComponentBuilder( "Hello" ).color( ChatColor.RED ).build() )
|
|
||||||
.inputs(
|
|
||||||
Arrays.asList( new TextInput( "first", new ComponentBuilder( "First" ).build() ),
|
|
||||||
new TextInput( "second", new ComponentBuilder( "Second" ).build() )
|
|
||||||
)
|
|
||||||
) )
|
|
||||||
.action( new ActionButton( new ComponentBuilder( "Submit Button" ).build(), new CustomClickAction( "customform" ) ) );
|
|
||||||
|
|
||||||
player.sendMessage( new ComponentBuilder( "click me" ).event( new ShowDialogClickEvent( notice ) ).build() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
@@ -1,31 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project-shared-configuration>
|
|
||||||
<!--
|
|
||||||
This file contains additional configuration written by modules in the NetBeans IDE.
|
|
||||||
The configuration is intended to be shared among all the users of project and
|
|
||||||
therefore it is assumed to be part of version control checkout.
|
|
||||||
Without this configuration present, some functionality in the IDE may be limited or fail altogether.
|
|
||||||
-->
|
|
||||||
<properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
|
|
||||||
<!--
|
|
||||||
Properties that influence various parts of the IDE, especially code formatting and the like.
|
|
||||||
You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
|
|
||||||
That way multiple projects can share the same settings (useful for formatting rules for example).
|
|
||||||
Any value defined here will override the pom.xml file value but is only applicable to the current project.
|
|
||||||
-->
|
|
||||||
<org-netbeans-modules-editor-indent.CodeStyle.usedProfile>project</org-netbeans-modules-editor-indent.CodeStyle.usedProfile>
|
|
||||||
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement>
|
|
||||||
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement>
|
|
||||||
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement>
|
|
||||||
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinMethodCallParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinMethodCallParens>
|
|
||||||
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSwitchParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSwitchParens>
|
|
||||||
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinCatchParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinCatchParens>
|
|
||||||
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinTryParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinTryParens>
|
|
||||||
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSynchronizedParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSynchronizedParens>
|
|
||||||
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinArrayInitBrackets>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinArrayInitBrackets>
|
|
||||||
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinParens>
|
|
||||||
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinWhileParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinWhileParens>
|
|
||||||
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinIfParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinIfParens>
|
|
||||||
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinForParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinForParens>
|
|
||||||
</properties>
|
|
||||||
</project-shared-configuration>
|
|
@@ -1,36 +0,0 @@
|
|||||||
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>net.md-5</groupId>
|
|
||||||
<artifactId>bungeecord-parent</artifactId>
|
|
||||||
<version>1.21-R0.4-SNAPSHOT</version>
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<groupId>net.md-5</groupId>
|
|
||||||
<artifactId>bungeecord-dialog</artifactId>
|
|
||||||
<version>1.21-R0.4-SNAPSHOT</version>
|
|
||||||
<packaging>jar</packaging>
|
|
||||||
|
|
||||||
<name>BungeeCord-Dialog</name>
|
|
||||||
<description>Minecraft dialog API intended for use with BungeeCord</description>
|
|
||||||
<licenses>
|
|
||||||
<license>
|
|
||||||
<name>BSD-3-Clause</name>
|
|
||||||
<url>https://github.com/SpigotMC/BungeeCord/blob/master/dialog/LICENSE</url>
|
|
||||||
<distribution>repo</distribution>
|
|
||||||
</license>
|
|
||||||
</licenses>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>net.md-5</groupId>
|
|
||||||
<artifactId>bungeecord-chat</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
</project>
|
|
@@ -1,39 +0,0 @@
|
|||||||
package net.md_5.bungee.api.dialog;
|
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
import lombok.NonNull;
|
|
||||||
import lombok.ToString;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
import net.md_5.bungee.api.dialog.action.ActionButton;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a simple dialog with text and two actions at the bottom (default:
|
|
||||||
* "yes", "no").
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@ToString
|
|
||||||
@EqualsAndHashCode
|
|
||||||
@AllArgsConstructor
|
|
||||||
@Accessors(fluent = true)
|
|
||||||
public final class ConfirmationDialog implements Dialog
|
|
||||||
{
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Accessors(fluent = false)
|
|
||||||
private DialogBase base;
|
|
||||||
/**
|
|
||||||
* The "yes" click action / bottom (appears on the left).
|
|
||||||
*/
|
|
||||||
private ActionButton yes;
|
|
||||||
/**
|
|
||||||
* The "no" click action / bottom (appears on the right).
|
|
||||||
*/
|
|
||||||
private ActionButton no;
|
|
||||||
|
|
||||||
public ConfirmationDialog(@NonNull DialogBase base)
|
|
||||||
{
|
|
||||||
this( base, null, null );
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,29 +0,0 @@
|
|||||||
package net.md_5.bungee.api.dialog;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a dialog GUI.
|
|
||||||
*/
|
|
||||||
public interface Dialog
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the dialog base which contains the dialog title and other options
|
|
||||||
* common to all types of dialogs.
|
|
||||||
*
|
|
||||||
* @return mutable reference to the dialog base
|
|
||||||
*/
|
|
||||||
DialogBase getBase();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the dialog base.
|
|
||||||
* <br>
|
|
||||||
* For internal use only as this is mandatory and should be specified in the
|
|
||||||
* constructor.
|
|
||||||
*
|
|
||||||
* @param base the new dialog base
|
|
||||||
*/
|
|
||||||
@ApiStatus.Internal
|
|
||||||
void setBase(DialogBase base);
|
|
||||||
}
|
|
@@ -1,84 +0,0 @@
|
|||||||
package net.md_5.bungee.api.dialog;
|
|
||||||
|
|
||||||
import com.google.gson.annotations.SerializedName;
|
|
||||||
import java.util.List;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NonNull;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
import net.md_5.bungee.api.chat.BaseComponent;
|
|
||||||
import net.md_5.bungee.api.dialog.body.DialogBody;
|
|
||||||
import net.md_5.bungee.api.dialog.input.DialogInput;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the title and other options common to all dialogs.
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@AllArgsConstructor
|
|
||||||
@Accessors(fluent = true)
|
|
||||||
public final class DialogBase
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The mandatory dialog title.
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
private BaseComponent title;
|
|
||||||
/**
|
|
||||||
* The name which is used for any buttons leading to this dialog (eg from a
|
|
||||||
* {@link DialogListDialog}). Otherwise defaults to {@link #title}.
|
|
||||||
*/
|
|
||||||
@SerializedName("external_title")
|
|
||||||
private BaseComponent externalTitle;
|
|
||||||
/**
|
|
||||||
* The inputs to the dialog.
|
|
||||||
*/
|
|
||||||
private List<DialogInput> inputs;
|
|
||||||
/**
|
|
||||||
* The body elements which make up this dialog.
|
|
||||||
*/
|
|
||||||
private List<DialogBody> body;
|
|
||||||
/**
|
|
||||||
* Whether this dialog can be closed with the escape key (default: true).
|
|
||||||
*/
|
|
||||||
@SerializedName("can_close_with_escape")
|
|
||||||
private Boolean canCloseWithEscape;
|
|
||||||
/**
|
|
||||||
* Whether this dialog should pause the game in single-player mode (default:
|
|
||||||
* true).
|
|
||||||
*/
|
|
||||||
private Boolean pause;
|
|
||||||
/**
|
|
||||||
* Action to take after the a click or submit action is performed on the
|
|
||||||
* dialog (default: close).
|
|
||||||
*/
|
|
||||||
@SerializedName("after_action")
|
|
||||||
private AfterAction afterAction;
|
|
||||||
|
|
||||||
public DialogBase(@NonNull BaseComponent title)
|
|
||||||
{
|
|
||||||
this( title, null, null, null, null, null, null );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Types of action which may be taken after the dialog.
|
|
||||||
*/
|
|
||||||
public enum AfterAction
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Close the dialog.
|
|
||||||
*/
|
|
||||||
@SerializedName("close")
|
|
||||||
CLOSE,
|
|
||||||
/**
|
|
||||||
* Do nothing.
|
|
||||||
*/
|
|
||||||
@SerializedName("none")
|
|
||||||
NONE,
|
|
||||||
/**
|
|
||||||
* Show a waiting for response screen.
|
|
||||||
*/
|
|
||||||
@SerializedName("wait_for_response")
|
|
||||||
WAIT_FOR_RESPONSE;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,73 +0,0 @@
|
|||||||
package net.md_5.bungee.api.dialog;
|
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
import com.google.gson.annotations.SerializedName;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
import lombok.NonNull;
|
|
||||||
import lombok.ToString;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
import net.md_5.bungee.api.dialog.action.ActionButton;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a dialog which contains buttons that link to other dialogs.
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@ToString
|
|
||||||
@EqualsAndHashCode
|
|
||||||
@Accessors(fluent = true)
|
|
||||||
public final class DialogListDialog implements Dialog
|
|
||||||
{
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Accessors(fluent = false)
|
|
||||||
private DialogBase base;
|
|
||||||
/**
|
|
||||||
* The child dialogs behind each button.
|
|
||||||
*/
|
|
||||||
private List<Dialog> dialogs;
|
|
||||||
/**
|
|
||||||
* The {@link ActionButton} activated when the dialog is exited.
|
|
||||||
*/
|
|
||||||
@SerializedName("exit_action")
|
|
||||||
private ActionButton exitAction;
|
|
||||||
/**
|
|
||||||
* The number of columns for the dialog buttons (default: 2).
|
|
||||||
*/
|
|
||||||
private Integer columns;
|
|
||||||
/**
|
|
||||||
* The width of the dialog buttons (default: 150, minimum: 1, maximum: 1024).
|
|
||||||
*/
|
|
||||||
@SerializedName("button_width")
|
|
||||||
private Integer buttonWidth;
|
|
||||||
|
|
||||||
public DialogListDialog(@NonNull DialogBase base, Dialog... dialogs)
|
|
||||||
{
|
|
||||||
this( base, Arrays.asList( dialogs ), null, null, null );
|
|
||||||
}
|
|
||||||
|
|
||||||
public DialogListDialog(@NonNull DialogBase base, List<Dialog> dialogs, ActionButton exitAction, Integer columns, Integer buttonWidth)
|
|
||||||
{
|
|
||||||
this.base = base;
|
|
||||||
this.dialogs = dialogs;
|
|
||||||
this.exitAction = exitAction;
|
|
||||||
columns( columns );
|
|
||||||
buttonWidth( buttonWidth );
|
|
||||||
}
|
|
||||||
|
|
||||||
public DialogListDialog columns(Integer columns)
|
|
||||||
{
|
|
||||||
Preconditions.checkArgument( columns == null || columns > 0, "At least one column is required" );
|
|
||||||
this.columns = columns;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DialogListDialog buttonWidth(Integer buttonWidth)
|
|
||||||
{
|
|
||||||
Preconditions.checkArgument( buttonWidth == null || ( buttonWidth >= 1 && buttonWidth <= 1024 ), "buttonWidth must be between 1 and 1024" );
|
|
||||||
this.buttonWidth = buttonWidth;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,64 +0,0 @@
|
|||||||
package net.md_5.bungee.api.dialog;
|
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
import com.google.gson.annotations.SerializedName;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
import lombok.NonNull;
|
|
||||||
import lombok.ToString;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
import net.md_5.bungee.api.dialog.action.ActionButton;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a dialog with text a list of action buttons grouped into columns
|
|
||||||
* and scrollable if necessary.
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@ToString
|
|
||||||
@EqualsAndHashCode
|
|
||||||
@Accessors(fluent = true)
|
|
||||||
public final class MultiActionDialog implements Dialog
|
|
||||||
{
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Accessors(fluent = false)
|
|
||||||
private DialogBase base;
|
|
||||||
/**
|
|
||||||
* The action buttons in the dialog. At least one must be provided.
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
private List<ActionButton> actions;
|
|
||||||
/**
|
|
||||||
* The number of columns for the dialog buttons (default: 2).
|
|
||||||
*/
|
|
||||||
private Integer columns;
|
|
||||||
/**
|
|
||||||
* The {@link ActionButton} activated when the dialog is exited.
|
|
||||||
*/
|
|
||||||
@SerializedName("exit_action")
|
|
||||||
private ActionButton exitAction;
|
|
||||||
|
|
||||||
public MultiActionDialog(@NonNull DialogBase base, @NonNull ActionButton... actions)
|
|
||||||
{
|
|
||||||
this( base, Arrays.asList( actions ), null, null );
|
|
||||||
}
|
|
||||||
|
|
||||||
public MultiActionDialog(@NonNull DialogBase base, @NonNull List<ActionButton> actions, Integer columns, ActionButton exitAction)
|
|
||||||
{
|
|
||||||
Preconditions.checkArgument( !actions.isEmpty(), "At least one action must be provided" );
|
|
||||||
|
|
||||||
this.base = base;
|
|
||||||
this.actions = actions;
|
|
||||||
columns( columns );
|
|
||||||
this.exitAction = exitAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MultiActionDialog columns(Integer columns)
|
|
||||||
{
|
|
||||||
Preconditions.checkArgument( columns == null || columns > 0, "At least one column is required" );
|
|
||||||
this.columns = columns;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,35 +0,0 @@
|
|||||||
package net.md_5.bungee.api.dialog;
|
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
import lombok.NonNull;
|
|
||||||
import lombok.ToString;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
import net.md_5.bungee.api.dialog.action.ActionButton;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a simple dialog with text and one action at the bottom (default:
|
|
||||||
* "OK").
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@ToString
|
|
||||||
@EqualsAndHashCode
|
|
||||||
@AllArgsConstructor
|
|
||||||
@Accessors(fluent = true)
|
|
||||||
public final class NoticeDialog implements Dialog
|
|
||||||
{
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Accessors(fluent = false)
|
|
||||||
private DialogBase base;
|
|
||||||
/**
|
|
||||||
* The "OK" action button for the dialog.
|
|
||||||
*/
|
|
||||||
private ActionButton action;
|
|
||||||
|
|
||||||
public NoticeDialog(DialogBase base)
|
|
||||||
{
|
|
||||||
this( base, null );
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,71 +0,0 @@
|
|||||||
package net.md_5.bungee.api.dialog;
|
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
import com.google.gson.annotations.SerializedName;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
import lombok.NonNull;
|
|
||||||
import lombok.ToString;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
import net.md_5.bungee.api.dialog.action.ActionButton;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a dialog which shows the links configured/sent from the server.
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@ToString
|
|
||||||
@EqualsAndHashCode
|
|
||||||
@Accessors(fluent = true)
|
|
||||||
public final class ServerLinksDialog implements Dialog
|
|
||||||
{
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Accessors(fluent = false)
|
|
||||||
private DialogBase base;
|
|
||||||
/**
|
|
||||||
* The optional {@link ActionButton} for this dialog.
|
|
||||||
*/
|
|
||||||
@SerializedName("action")
|
|
||||||
private ActionButton action;
|
|
||||||
/**
|
|
||||||
* The {@link ActionButton} activated when the dialog is exited.
|
|
||||||
*/
|
|
||||||
@SerializedName("exit_action")
|
|
||||||
private ActionButton exitAction;
|
|
||||||
/**
|
|
||||||
* The number of columns for the dialog buttons (default: 2).
|
|
||||||
*/
|
|
||||||
private Integer columns;
|
|
||||||
/**
|
|
||||||
* The width of the dialog buttons (default: 150, minimum: 1, maximum: 1024).
|
|
||||||
*/
|
|
||||||
@SerializedName("button_width")
|
|
||||||
private Integer buttonWidth;
|
|
||||||
|
|
||||||
public ServerLinksDialog(@NonNull DialogBase base)
|
|
||||||
{
|
|
||||||
this( base, null, null, null );
|
|
||||||
}
|
|
||||||
|
|
||||||
public ServerLinksDialog(@NonNull DialogBase base, ActionButton action, Integer columns, Integer buttonWidth)
|
|
||||||
{
|
|
||||||
this.base = base;
|
|
||||||
this.action = action;
|
|
||||||
columns( columns );
|
|
||||||
buttonWidth( buttonWidth );
|
|
||||||
}
|
|
||||||
|
|
||||||
public ServerLinksDialog columns(Integer columns)
|
|
||||||
{
|
|
||||||
Preconditions.checkArgument( columns == null || columns > 0, "At least one column is required" );
|
|
||||||
this.columns = columns;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ServerLinksDialog buttonWidth(Integer buttonWidth)
|
|
||||||
{
|
|
||||||
Preconditions.checkArgument( buttonWidth == null || ( buttonWidth >= 1 && buttonWidth <= 1024 ), "buttonWidth must be between 1 and 1024" );
|
|
||||||
this.buttonWidth = buttonWidth;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,6 +0,0 @@
|
|||||||
package net.md_5.bungee.api.dialog.action;
|
|
||||||
|
|
||||||
public interface Action
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
@@ -1,54 +0,0 @@
|
|||||||
package net.md_5.bungee.api.dialog.action;
|
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NonNull;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
import net.md_5.bungee.api.chat.BaseComponent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a dialog action which will usually appear as a button.
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Accessors(fluent = true)
|
|
||||||
public class ActionButton
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The text label of the button, mandatory.
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
private BaseComponent label;
|
|
||||||
/**
|
|
||||||
* The hover tooltip of the button.
|
|
||||||
*/
|
|
||||||
private BaseComponent tooltip;
|
|
||||||
/**
|
|
||||||
* The width of the button (default: 150, minimum: 1, maximum: 1024).
|
|
||||||
*/
|
|
||||||
private Integer width;
|
|
||||||
/**
|
|
||||||
* The action to take.
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
private Action action;
|
|
||||||
|
|
||||||
public ActionButton(@NonNull BaseComponent label, BaseComponent tooltip, Integer width, @NonNull Action action)
|
|
||||||
{
|
|
||||||
this.label = label;
|
|
||||||
this.tooltip = tooltip;
|
|
||||||
setWidth( width );
|
|
||||||
this.action = action;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ActionButton(@NonNull BaseComponent label, @NonNull Action action)
|
|
||||||
{
|
|
||||||
this( label, null, null, action );
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setWidth(Integer width)
|
|
||||||
{
|
|
||||||
Preconditions.checkArgument( width == null || ( width >= 1 && width <= 1024 ), "width must be between 1 and 1024" );
|
|
||||||
this.width = width;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,27 +0,0 @@
|
|||||||
package net.md_5.bungee.api.dialog.action;
|
|
||||||
|
|
||||||
import com.google.gson.JsonElement;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NonNull;
|
|
||||||
import lombok.ToString;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Submits the dialog with the given ID and values as a payload.
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Accessors(fluent = true)
|
|
||||||
@ToString(callSuper = true)
|
|
||||||
public class CustomClickAction implements Action
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The namespaced key of the submission.
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
private String id;
|
|
||||||
/**
|
|
||||||
* Fields to be added to the submission payload.
|
|
||||||
*/
|
|
||||||
private JsonElement additions;
|
|
||||||
}
|
|
@@ -1,25 +0,0 @@
|
|||||||
package net.md_5.bungee.api.dialog.action;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NonNull;
|
|
||||||
import lombok.ToString;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executes a command. If the command requires a permission
|
|
||||||
* higher than 0, a confirmation dialog will be shown by the client.
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Accessors(fluent = true)
|
|
||||||
@ToString(callSuper = true)
|
|
||||||
public class RunCommandAction implements Action
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The template to be applied, where variables of the form
|
|
||||||
* <code>$(key)</code> will be replaced by their
|
|
||||||
* {@link net.md_5.bungee.api.dialog.input.DialogInput#key} value.
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
private String template;
|
|
||||||
}
|
|
@@ -1,20 +0,0 @@
|
|||||||
package net.md_5.bungee.api.dialog.action;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NonNull;
|
|
||||||
import lombok.ToString;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
import net.md_5.bungee.api.chat.ClickEvent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a static dialog action.
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Accessors(fluent = true)
|
|
||||||
@ToString(callSuper = true)
|
|
||||||
public class StaticAction implements Action
|
|
||||||
{
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
private ClickEvent clickEvent;
|
|
||||||
}
|
|
@@ -1,4 +0,0 @@
|
|||||||
/**
|
|
||||||
* Contains the different actions/buttons for a {@link net.md_5.bungee.api.dialog.Dialog}.
|
|
||||||
*/
|
|
||||||
package net.md_5.bungee.api.dialog.action;
|
|
@@ -1,20 +0,0 @@
|
|||||||
package net.md_5.bungee.api.dialog.body;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NonNull;
|
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the body content of a {@link net.md_5.bungee.api.dialog.Dialog}.
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
public abstract class DialogBody
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The internal body type.
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
@ApiStatus.Internal
|
|
||||||
private final String type;
|
|
||||||
}
|
|
@@ -1,49 +0,0 @@
|
|||||||
package net.md_5.bungee.api.dialog.body;
|
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
import lombok.NonNull;
|
|
||||||
import lombok.ToString;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
import net.md_5.bungee.api.chat.BaseComponent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a dialog body which consists of text constrained to a certain
|
|
||||||
* width.
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Accessors(fluent = true)
|
|
||||||
@ToString(callSuper = true)
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
public class PlainMessageBody extends DialogBody
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The text body.
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
private BaseComponent contents;
|
|
||||||
/**
|
|
||||||
* The maximum width (default: 200, minimum: 1, maximum: 1024).
|
|
||||||
*/
|
|
||||||
private Integer width;
|
|
||||||
|
|
||||||
public PlainMessageBody(@NonNull BaseComponent contents)
|
|
||||||
{
|
|
||||||
this( contents, null );
|
|
||||||
}
|
|
||||||
|
|
||||||
public PlainMessageBody(@NonNull BaseComponent contents, Integer width)
|
|
||||||
{
|
|
||||||
super( "minecraft:plain_message" );
|
|
||||||
this.contents = contents;
|
|
||||||
width( width );
|
|
||||||
}
|
|
||||||
|
|
||||||
public void width(Integer width)
|
|
||||||
{
|
|
||||||
Preconditions.checkArgument( width == null || ( width >= 1 && width <= 1024 ), "width must be between 1 and 1024" );
|
|
||||||
this.width = width;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,5 +0,0 @@
|
|||||||
/**
|
|
||||||
* Contains the different {@link net.md_5.bungee.api.dialog.Dialog} body content
|
|
||||||
* types.
|
|
||||||
*/
|
|
||||||
package net.md_5.bungee.api.dialog.body;
|
|
@@ -1,42 +0,0 @@
|
|||||||
package net.md_5.bungee.api.dialog.chat;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
import net.md_5.bungee.api.chat.ClickEvent;
|
|
||||||
import net.md_5.bungee.api.dialog.Dialog;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Click event which displays either a pre-existing dialog by key or a custom
|
|
||||||
* dialog.
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@EqualsAndHashCode(callSuper = false)
|
|
||||||
public class ShowDialogClickEvent extends ClickEvent
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Key for a pre-existing dialog to show.
|
|
||||||
*/
|
|
||||||
private String reference;
|
|
||||||
/**
|
|
||||||
* Dialog to show.
|
|
||||||
*/
|
|
||||||
private Dialog dialog;
|
|
||||||
|
|
||||||
public ShowDialogClickEvent(String reference)
|
|
||||||
{
|
|
||||||
this( reference, null );
|
|
||||||
}
|
|
||||||
|
|
||||||
public ShowDialogClickEvent(Dialog dialog)
|
|
||||||
{
|
|
||||||
this( null, dialog );
|
|
||||||
}
|
|
||||||
|
|
||||||
private ShowDialogClickEvent(String reference, Dialog dialog)
|
|
||||||
{
|
|
||||||
super( Action.SHOW_DIALOG, null );
|
|
||||||
this.reference = reference;
|
|
||||||
this.dialog = dialog;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,4 +0,0 @@
|
|||||||
/**
|
|
||||||
* Contains dialog extensions to the chat API.
|
|
||||||
*/
|
|
||||||
package net.md_5.bungee.api.dialog.chat;
|
|
@@ -1,54 +0,0 @@
|
|||||||
package net.md_5.bungee.api.dialog.input;
|
|
||||||
|
|
||||||
import com.google.gson.annotations.SerializedName;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
import lombok.NonNull;
|
|
||||||
import lombok.ToString;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
import net.md_5.bungee.api.chat.BaseComponent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a checkbox input control.
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Accessors(fluent = true)
|
|
||||||
@ToString(callSuper = true)
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
public class BooleanInput extends DialogInput
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The input label.
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
private BaseComponent label;
|
|
||||||
/**
|
|
||||||
* The initial value (default: false/unchecked).
|
|
||||||
*/
|
|
||||||
private Boolean initial;
|
|
||||||
/**
|
|
||||||
* The string value to be submitted when true/checked (default: "true").
|
|
||||||
*/
|
|
||||||
@SerializedName("on_true")
|
|
||||||
private String onTrue;
|
|
||||||
/**
|
|
||||||
* The string value to be submitted when false/unchecked (default: "false").
|
|
||||||
*/
|
|
||||||
@SerializedName("on_false")
|
|
||||||
private String onFalse;
|
|
||||||
|
|
||||||
public BooleanInput(@NonNull String key, @NonNull BaseComponent label)
|
|
||||||
{
|
|
||||||
this( key, label, null, "true", "false" );
|
|
||||||
}
|
|
||||||
|
|
||||||
public BooleanInput(@NonNull String key, @NonNull BaseComponent label, Boolean initial, String onTrue, String onFalse)
|
|
||||||
{
|
|
||||||
super( "minecraft:boolean", key );
|
|
||||||
this.label = label;
|
|
||||||
this.initial = initial;
|
|
||||||
this.onTrue = onTrue;
|
|
||||||
this.onFalse = onFalse;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,29 +0,0 @@
|
|||||||
package net.md_5.bungee.api.dialog.input;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NonNull;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a type of input which may be displayed/submitted with a form
|
|
||||||
* dialog.
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Accessors(fluent = true)
|
|
||||||
public class DialogInput
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The internal input type.
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
@ApiStatus.Internal
|
|
||||||
private final String type;
|
|
||||||
/**
|
|
||||||
* The key corresponding to this input and associated with the value
|
|
||||||
* submitted.
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
private final String key;
|
|
||||||
}
|
|
@@ -1,39 +0,0 @@
|
|||||||
package net.md_5.bungee.api.dialog.input;
|
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NonNull;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
import net.md_5.bungee.api.chat.BaseComponent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents an option choice which may form part of a
|
|
||||||
* {@link SingleOptionInput}.
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@AllArgsConstructor
|
|
||||||
@Accessors(fluent = true)
|
|
||||||
public class InputOption
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The string value associated with this option, to be submitted when
|
|
||||||
* selected.
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
private String id;
|
|
||||||
/**
|
|
||||||
* The text to display for this option.
|
|
||||||
*/
|
|
||||||
private BaseComponent display;
|
|
||||||
/**
|
|
||||||
* Whether this option is the one initially selected. Only one option may
|
|
||||||
* have this value as true (default: first option).
|
|
||||||
*/
|
|
||||||
private Boolean initial;
|
|
||||||
|
|
||||||
public InputOption(@NonNull String id)
|
|
||||||
{
|
|
||||||
this( id, null, null );
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,103 +0,0 @@
|
|||||||
package net.md_5.bungee.api.dialog.input;
|
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
import lombok.NonNull;
|
|
||||||
import lombok.ToString;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
import net.md_5.bungee.api.chat.BaseComponent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a number slider input.
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Accessors(fluent = true)
|
|
||||||
@ToString(callSuper = true)
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
public class NumberRangeInput extends DialogInput
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The width of the input (default: 200, minimum: 1, maximum: 1024).
|
|
||||||
*/
|
|
||||||
private Integer width;
|
|
||||||
/**
|
|
||||||
* The label of the slider.
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
private BaseComponent label;
|
|
||||||
/**
|
|
||||||
* A translate key used to display the label value (default:
|
|
||||||
* options.generic_value).
|
|
||||||
*/
|
|
||||||
private String labelFormat;
|
|
||||||
/**
|
|
||||||
* The start position of the slider (leftmost position).
|
|
||||||
*/
|
|
||||||
private float start;
|
|
||||||
/**
|
|
||||||
* The end position of the slider (rightmost position).
|
|
||||||
*/
|
|
||||||
private float end;
|
|
||||||
/**
|
|
||||||
* The steps in which the input will be increased or decreased, or null if
|
|
||||||
* no specific steps.
|
|
||||||
*/
|
|
||||||
private Float step;
|
|
||||||
/**
|
|
||||||
* The initial value of number input, or null to fall back to the middle.
|
|
||||||
*/
|
|
||||||
private Float initial;
|
|
||||||
|
|
||||||
public NumberRangeInput(@NonNull String key, @NonNull BaseComponent label, float start, float end)
|
|
||||||
{
|
|
||||||
this( key, null, label, "options.generic_value", start, end, null, null );
|
|
||||||
}
|
|
||||||
|
|
||||||
public NumberRangeInput(@NonNull String key, @NonNull BaseComponent label, float start, float end, Float step)
|
|
||||||
{
|
|
||||||
this( key, null, label, "options.generic_value", start, end, step, null );
|
|
||||||
}
|
|
||||||
|
|
||||||
public NumberRangeInput(@NonNull String key, @NonNull BaseComponent label, float start, float end, Float step, Float initial)
|
|
||||||
{
|
|
||||||
this( key, null, label, "options.generic_value", start, end, step, initial );
|
|
||||||
}
|
|
||||||
|
|
||||||
public NumberRangeInput(@NonNull String key, Integer width, @NonNull BaseComponent label, String labelFormat, float start, float end, Float step, Float initial)
|
|
||||||
{
|
|
||||||
super( "minecraft:number_range", key );
|
|
||||||
width( width );
|
|
||||||
this.label = label;
|
|
||||||
this.labelFormat = labelFormat;
|
|
||||||
this.start = start;
|
|
||||||
this.end = end;
|
|
||||||
step( step );
|
|
||||||
initial( initial );
|
|
||||||
}
|
|
||||||
|
|
||||||
public NumberRangeInput width(Integer width)
|
|
||||||
{
|
|
||||||
Preconditions.checkArgument( width == null || ( width >= 1 && width <= 1024 ), "with must be between 1 and 1024" );
|
|
||||||
this.width = width;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public NumberRangeInput step(Float step)
|
|
||||||
{
|
|
||||||
Preconditions.checkArgument( step == null || step > 0, "step must be null or greater than zero" );
|
|
||||||
this.step = step;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public NumberRangeInput initial(Float initial)
|
|
||||||
{
|
|
||||||
// we need to calculate if the initial value is between start and end, regardless of the order
|
|
||||||
float min = Math.min( start, end );
|
|
||||||
float max = Math.max( start, end );
|
|
||||||
Preconditions.checkArgument( initial == null || ( initial >= min && initial <= max ), "initial must be null or between start and end" );
|
|
||||||
this.initial = initial;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,66 +0,0 @@
|
|||||||
package net.md_5.bungee.api.dialog.input;
|
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
import com.google.gson.annotations.SerializedName;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
import lombok.NonNull;
|
|
||||||
import lombok.ToString;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
import net.md_5.bungee.api.chat.BaseComponent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a single option (dropdown) input.
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Accessors(fluent = true)
|
|
||||||
@ToString(callSuper = true)
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
public class SingleOptionInput extends DialogInput
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The width of the input (default: 200, minimum: 1, maximum: 1024).
|
|
||||||
*/
|
|
||||||
private Integer width;
|
|
||||||
/**
|
|
||||||
* The input label.
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
private BaseComponent label;
|
|
||||||
/**
|
|
||||||
* Whether the label is visible (default: true).
|
|
||||||
*/
|
|
||||||
@SerializedName("label_visible")
|
|
||||||
private Boolean labelVisible;
|
|
||||||
/**
|
|
||||||
* The non-empty list of options to be selected from.
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
private List<InputOption> options;
|
|
||||||
|
|
||||||
public SingleOptionInput(@NonNull String key, @NonNull BaseComponent label, @NonNull InputOption... options)
|
|
||||||
{
|
|
||||||
this( key, null, label, null, Arrays.asList( options ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
public SingleOptionInput(@NonNull String key, Integer width, @NonNull BaseComponent label, Boolean labelVisible, @NonNull List<InputOption> options)
|
|
||||||
{
|
|
||||||
super( "minecraft:single_option", key );
|
|
||||||
Preconditions.checkArgument( !options.isEmpty(), "At least one option must be provided" );
|
|
||||||
|
|
||||||
width( width );
|
|
||||||
this.label = label;
|
|
||||||
this.labelVisible = labelVisible;
|
|
||||||
this.options = options;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SingleOptionInput width(Integer width)
|
|
||||||
{
|
|
||||||
Preconditions.checkArgument( width == null || ( width >= 1 && width <= 1024 ), "width must be between 1 and 1024" );
|
|
||||||
this.width = width;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,110 +0,0 @@
|
|||||||
package net.md_5.bungee.api.dialog.input;
|
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
import com.google.gson.annotations.SerializedName;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import lombok.NonNull;
|
|
||||||
import lombok.ToString;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
import net.md_5.bungee.api.chat.BaseComponent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a textbox input.
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Accessors(fluent = true)
|
|
||||||
@ToString(callSuper = true)
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
public class TextInput extends DialogInput
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The width of this text input (default: 200, minimum: 1, maximum: 1024).
|
|
||||||
*/
|
|
||||||
private Integer width;
|
|
||||||
/**
|
|
||||||
* The label of this text input.
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
private BaseComponent label;
|
|
||||||
/**
|
|
||||||
* The visibility of this text input's label.
|
|
||||||
*/
|
|
||||||
@SerializedName("label_visible")
|
|
||||||
private Boolean labelVisible;
|
|
||||||
/**
|
|
||||||
* The initial value of this text input.
|
|
||||||
*/
|
|
||||||
private String initial;
|
|
||||||
/**
|
|
||||||
* The maximum length of the input (default: 32).
|
|
||||||
*/
|
|
||||||
@SerializedName("max_length")
|
|
||||||
private Integer maxLength;
|
|
||||||
/**
|
|
||||||
* If present, allows users to input multiple lines.
|
|
||||||
*/
|
|
||||||
private Multiline multiline;
|
|
||||||
|
|
||||||
public TextInput(@NonNull String key, @NonNull BaseComponent label)
|
|
||||||
{
|
|
||||||
this( key, null, label, null, null, null, null );
|
|
||||||
}
|
|
||||||
|
|
||||||
public TextInput(@NonNull String key, Integer width, @NonNull BaseComponent label, Boolean labelVisible, String initial, Integer maxLength)
|
|
||||||
{
|
|
||||||
this( key, width, label, labelVisible, initial, maxLength, null );
|
|
||||||
}
|
|
||||||
|
|
||||||
public TextInput(@NonNull String key, Integer width, @NonNull BaseComponent label, Boolean labelVisible, String initial, Integer maxLength, Multiline multiline)
|
|
||||||
{
|
|
||||||
super( "minecraft:text", key );
|
|
||||||
width( width );
|
|
||||||
this.label = label;
|
|
||||||
this.labelVisible = labelVisible;
|
|
||||||
this.initial = initial;
|
|
||||||
this.maxLength = maxLength;
|
|
||||||
this.multiline = multiline;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configuration data for a multiline input.
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Accessors(fluent = true)
|
|
||||||
public static class Multiline
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The maximum length of input, or null to disable any limits.
|
|
||||||
*/
|
|
||||||
@SerializedName("max_lines")
|
|
||||||
private Integer maxLines;
|
|
||||||
/**
|
|
||||||
* The height of this input (default: 32, minimum: 1, maximum: 512).
|
|
||||||
*/
|
|
||||||
private Integer height;
|
|
||||||
|
|
||||||
public Multiline(Integer maxLines, Integer height)
|
|
||||||
{
|
|
||||||
height( height ).maxLines( maxLines );
|
|
||||||
}
|
|
||||||
|
|
||||||
public Multiline height(Integer height)
|
|
||||||
{
|
|
||||||
Preconditions.checkArgument( height == null || height >= 1 && height <= 512, "height must null or be between 1 and 512" );
|
|
||||||
this.height = height;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public TextInput width(Integer width)
|
|
||||||
{
|
|
||||||
Preconditions.checkArgument( width == null || ( width >= 1 && width <= 1024 ), "width must be between 1 and 1024" );
|
|
||||||
this.width = width;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user