commit
0dcba749dc
@ -1,5 +1,7 @@
|
|||||||
package net.md_5.bungee.api;
|
package net.md_5.bungee.api;
|
||||||
|
|
||||||
|
import net.md_5.bungee.api.chat.BaseComponent;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
public interface CommandSender
|
public interface CommandSender
|
||||||
@ -17,6 +19,7 @@ public interface CommandSender
|
|||||||
*
|
*
|
||||||
* @param message the message to send
|
* @param message the message to send
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public void sendMessage(String message);
|
public void sendMessage(String message);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -25,8 +28,23 @@ public interface CommandSender
|
|||||||
*
|
*
|
||||||
* @param messages the messages to send
|
* @param messages the messages to send
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public void sendMessages(String... messages);
|
public void sendMessages(String... messages);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a message to this sender.
|
||||||
|
*
|
||||||
|
* @param message the message to send
|
||||||
|
*/
|
||||||
|
public void sendMessage(BaseComponent... message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a message to this sender.
|
||||||
|
*
|
||||||
|
* @param message the message to send
|
||||||
|
*/
|
||||||
|
public void sendMessage(BaseComponent message);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all groups this user is part of. This returns an unmodifiable
|
* Get all groups this user is part of. This returns an unmodifiable
|
||||||
* collection.
|
* collection.
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package net.md_5.bungee.api;
|
package net.md_5.bungee.api;
|
||||||
|
|
||||||
|
import net.md_5.bungee.api.chat.BaseComponent;
|
||||||
import net.md_5.bungee.api.plugin.PluginManager;
|
import net.md_5.bungee.api.plugin.PluginManager;
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -231,8 +232,23 @@ public abstract class ProxyServer
|
|||||||
*
|
*
|
||||||
* @param message the message to broadcast
|
* @param message the message to broadcast
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public abstract void broadcast(String message);
|
public abstract void broadcast(String message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send the specified message to the console and all connected players.
|
||||||
|
*
|
||||||
|
* @param message the message to broadcast
|
||||||
|
*/
|
||||||
|
public abstract void broadcast(BaseComponent... message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send the specified message to the console and all connected players.
|
||||||
|
*
|
||||||
|
* @param message the message to broadcast
|
||||||
|
*/
|
||||||
|
public abstract void broadcast(BaseComponent message);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a new instance of this proxies custom tab list.
|
* Gets a new instance of this proxies custom tab list.
|
||||||
*
|
*
|
||||||
|
392
api/src/main/java/net/md_5/bungee/api/chat/BaseComponent.java
Normal file
392
api/src/main/java/net/md_5/bungee/api/chat/BaseComponent.java
Normal file
@ -0,0 +1,392 @@
|
|||||||
|
package net.md_5.bungee.api.chat;
|
||||||
|
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import net.md_5.bungee.api.ChatColor;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
public abstract class BaseComponent
|
||||||
|
{
|
||||||
|
|
||||||
|
@Getter(AccessLevel.NONE)
|
||||||
|
@Setter(AccessLevel.NONE)
|
||||||
|
BaseComponent parent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The color of this component and any child
|
||||||
|
* components (unless overridden)
|
||||||
|
*/
|
||||||
|
@Getter(AccessLevel.NONE)
|
||||||
|
private ChatColor color;
|
||||||
|
/**
|
||||||
|
* Whether this component and any child
|
||||||
|
* components (unless overridden) is bold
|
||||||
|
*/
|
||||||
|
@Getter(AccessLevel.NONE)
|
||||||
|
private Boolean bold;
|
||||||
|
/**
|
||||||
|
* Whether this component and any child
|
||||||
|
* components (unless overridden) is italic
|
||||||
|
*/
|
||||||
|
@Getter(AccessLevel.NONE)
|
||||||
|
private Boolean italic;
|
||||||
|
/**
|
||||||
|
* Whether this component and any child
|
||||||
|
* components (unless overridden) is underlined
|
||||||
|
*/
|
||||||
|
@Getter(AccessLevel.NONE)
|
||||||
|
private Boolean underlined;
|
||||||
|
/**
|
||||||
|
* Whether this component and any child
|
||||||
|
* components (unless overridden) is strikethrough
|
||||||
|
*/
|
||||||
|
@Getter(AccessLevel.NONE)
|
||||||
|
private Boolean strikethrough;
|
||||||
|
/**
|
||||||
|
* Whether this component and any child
|
||||||
|
* components (unless overridden) is obfuscated
|
||||||
|
*/
|
||||||
|
@Getter(AccessLevel.NONE)
|
||||||
|
private Boolean obfuscated;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appended components that inherit this component's
|
||||||
|
* formatting and events
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
private List<BaseComponent> extra;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The action to preform when this component (and
|
||||||
|
* child components) are clicked
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
private ClickEvent clickEvent;
|
||||||
|
/**
|
||||||
|
* The action to preform when this component (and
|
||||||
|
* child components) are hovered over
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
private HoverEvent hoverEvent;
|
||||||
|
|
||||||
|
protected BaseComponent(BaseComponent old)
|
||||||
|
{
|
||||||
|
setColor( old.getColorRaw() );
|
||||||
|
setBold( old.isBoldRaw() );
|
||||||
|
setItalic( old.isItalicRaw() );
|
||||||
|
setUnderlined( old.isUnderlined() );
|
||||||
|
setStrikethrough( old.isStrikethroughRaw() );
|
||||||
|
setObfuscated( old.isObfuscatedRaw() );
|
||||||
|
setClickEvent( old.getClickEvent() );
|
||||||
|
setHoverEvent( old.getHoverEvent() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the components to a string that uses the
|
||||||
|
* old formatting codes ({@link net.md_5.bungee.api.ChatColor#COLOR_CHAR}
|
||||||
|
* @param components the components to convert
|
||||||
|
* @return the string in the old format
|
||||||
|
*/
|
||||||
|
public static String toLegacyText(BaseComponent... components)
|
||||||
|
{
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
for ( BaseComponent msg : components )
|
||||||
|
{
|
||||||
|
builder.append( msg.toLegacyText() );
|
||||||
|
}
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the components into a string without
|
||||||
|
* any formatting
|
||||||
|
* @param components the components to convert
|
||||||
|
* @return the string as plain text
|
||||||
|
*/
|
||||||
|
public static String toPlainText(BaseComponent... components)
|
||||||
|
{
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
for ( BaseComponent msg : components )
|
||||||
|
{
|
||||||
|
builder.append( msg.toPlainText() );
|
||||||
|
}
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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}
|
||||||
|
* is returned if no color is found.
|
||||||
|
*
|
||||||
|
* @return the color of this component
|
||||||
|
*/
|
||||||
|
public ChatColor getColor()
|
||||||
|
{
|
||||||
|
if ( color == null )
|
||||||
|
{
|
||||||
|
if ( parent == null )
|
||||||
|
{
|
||||||
|
return ChatColor.WHITE;
|
||||||
|
}
|
||||||
|
return parent.getColor();
|
||||||
|
}
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the color of this component without checking the parents
|
||||||
|
* color. May return null
|
||||||
|
*
|
||||||
|
* @return the color of this component
|
||||||
|
*/
|
||||||
|
public ChatColor getColorRaw()
|
||||||
|
{
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this component is bold. This uses the parent's
|
||||||
|
* setting if this component hasn't been set. false is returned
|
||||||
|
* if none of the parent chain has been set.
|
||||||
|
*
|
||||||
|
* @return whether the component is bold
|
||||||
|
*/
|
||||||
|
public boolean isBold()
|
||||||
|
{
|
||||||
|
if ( bold == null )
|
||||||
|
{
|
||||||
|
return parent != null && parent.isBold();
|
||||||
|
}
|
||||||
|
return bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this component is bold without checking
|
||||||
|
* the parents setting. May return null
|
||||||
|
*
|
||||||
|
* @return whether the component is bold
|
||||||
|
*/
|
||||||
|
public Boolean isBoldRaw()
|
||||||
|
{
|
||||||
|
return bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this component is italic. This uses the parent's
|
||||||
|
* setting if this component hasn't been set. false is returned
|
||||||
|
* if none of the parent chain has been set.
|
||||||
|
*
|
||||||
|
* @return whether the component is italic
|
||||||
|
*/
|
||||||
|
public boolean isItalic()
|
||||||
|
{
|
||||||
|
if ( italic == null )
|
||||||
|
{
|
||||||
|
return parent != null && parent.isItalic();
|
||||||
|
}
|
||||||
|
return italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this component is italic without checking
|
||||||
|
* the parents setting. May return null
|
||||||
|
*
|
||||||
|
* @return whether the component is italic
|
||||||
|
*/
|
||||||
|
public Boolean isItalicRaw()
|
||||||
|
{
|
||||||
|
return italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this component is underlined. This uses the parent's
|
||||||
|
* setting if this component hasn't been set. false is returned
|
||||||
|
* if none of the parent chain has been set.
|
||||||
|
*
|
||||||
|
* @return whether the component is underlined
|
||||||
|
*/
|
||||||
|
public boolean isUnderlined()
|
||||||
|
{
|
||||||
|
if ( underlined == null )
|
||||||
|
{
|
||||||
|
return parent != null && parent.isUnderlined();
|
||||||
|
}
|
||||||
|
return underlined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this component is underlined without checking
|
||||||
|
* the parents setting. May return null
|
||||||
|
*
|
||||||
|
* @return whether the component is underlined
|
||||||
|
*/
|
||||||
|
public Boolean isUnderlinedRaw()
|
||||||
|
{
|
||||||
|
return underlined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this component is strikethrough. This uses the parent's
|
||||||
|
* setting if this component hasn't been set. false is returned
|
||||||
|
* if none of the parent chain has been set.
|
||||||
|
*
|
||||||
|
* @return whether the component is strikethrough
|
||||||
|
*/
|
||||||
|
public boolean isStrikethrough()
|
||||||
|
{
|
||||||
|
if ( strikethrough == null )
|
||||||
|
{
|
||||||
|
return parent != null && parent.isStrikethrough();
|
||||||
|
}
|
||||||
|
return strikethrough;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this component is strikethrough without checking
|
||||||
|
* the parents setting. May return null
|
||||||
|
*
|
||||||
|
* @return whether the component is strikethrough
|
||||||
|
*/
|
||||||
|
public Boolean isStrikethroughRaw()
|
||||||
|
{
|
||||||
|
return strikethrough;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this component is obfuscated. This uses the parent's
|
||||||
|
* setting if this component hasn't been set. false is returned
|
||||||
|
* if none of the parent chain has been set.
|
||||||
|
*
|
||||||
|
* @return whether the component is obfuscated
|
||||||
|
*/
|
||||||
|
public boolean isObfuscated()
|
||||||
|
{
|
||||||
|
if ( obfuscated == null )
|
||||||
|
{
|
||||||
|
return parent != null && parent.isObfuscated();
|
||||||
|
}
|
||||||
|
return obfuscated;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this component is obfuscated without checking
|
||||||
|
* the parents setting. May return null
|
||||||
|
*
|
||||||
|
* @return whether the component is obfuscated
|
||||||
|
*/
|
||||||
|
public Boolean isObfuscatedRaw()
|
||||||
|
{
|
||||||
|
return obfuscated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExtra(List<BaseComponent> components)
|
||||||
|
{
|
||||||
|
for ( BaseComponent component : components )
|
||||||
|
{
|
||||||
|
component.parent = this;
|
||||||
|
}
|
||||||
|
extra = components;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends a text element to the component. The text will
|
||||||
|
* inherit this component's formatting
|
||||||
|
*
|
||||||
|
* @param text the text to append
|
||||||
|
*/
|
||||||
|
public void addExtra(String text)
|
||||||
|
{
|
||||||
|
addExtra( new TextComponent( text ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends a component to the component. The text will
|
||||||
|
* inherit this component's formatting
|
||||||
|
*
|
||||||
|
* @param component the component to append
|
||||||
|
*/
|
||||||
|
public void addExtra(BaseComponent component)
|
||||||
|
{
|
||||||
|
if ( extra == null )
|
||||||
|
{
|
||||||
|
extra = new ArrayList<>();
|
||||||
|
}
|
||||||
|
component.parent = this;
|
||||||
|
extra.add( component );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the component has any formatting
|
||||||
|
* or events applied to it
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean hasFormatting()
|
||||||
|
{
|
||||||
|
return color != null || bold != null ||
|
||||||
|
italic != null || underlined != null ||
|
||||||
|
strikethrough != null || obfuscated != null ||
|
||||||
|
hoverEvent != null || clickEvent != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the component into a string without
|
||||||
|
* any formatting
|
||||||
|
* @return the string as plain text
|
||||||
|
*/
|
||||||
|
public String toPlainText()
|
||||||
|
{
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
toPlainText( builder );
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void toPlainText(StringBuilder builder)
|
||||||
|
{
|
||||||
|
if ( extra != null )
|
||||||
|
{
|
||||||
|
for ( BaseComponent e : extra )
|
||||||
|
{
|
||||||
|
e.toPlainText( builder );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the component to a string that uses the
|
||||||
|
* old formatting codes ({@link net.md_5.bungee.api.ChatColor#COLOR_CHAR}
|
||||||
|
* @return the string in the old format
|
||||||
|
*/
|
||||||
|
public String toLegacyText()
|
||||||
|
{
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
toLegacyText( builder );
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void toLegacyText(StringBuilder builder)
|
||||||
|
{
|
||||||
|
if ( extra != null )
|
||||||
|
{
|
||||||
|
for ( BaseComponent e : extra )
|
||||||
|
{
|
||||||
|
e.toLegacyText( builder );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return String.format( "BaseComponent{color=%s, bold=%b, italic=%b, underlined=%b, strikethrough=%b, obfuscated=%b, clickEvent=%s, hoverEvent=%s}", getColor().getName(), isBold(), isItalic(), isUnderlined(), isStrikethrough(), isObfuscated(), getClickEvent(), getHoverEvent() );
|
||||||
|
}
|
||||||
|
}
|
53
api/src/main/java/net/md_5/bungee/api/chat/ClickEvent.java
Normal file
53
api/src/main/java/net/md_5/bungee/api/chat/ClickEvent.java
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
package net.md_5.bungee.api.chat;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
final public class ClickEvent
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The type of action to preform on click
|
||||||
|
*/
|
||||||
|
private final Action action;
|
||||||
|
/**
|
||||||
|
* Depends on action
|
||||||
|
* @see net.md_5.bungee.api.chat.ClickEvent.Action
|
||||||
|
*/
|
||||||
|
private final String value;
|
||||||
|
|
||||||
|
public enum Action
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Open a url at the path given by
|
||||||
|
* {@link net.md_5.bungee.api.chat.ClickEvent#getValue()}
|
||||||
|
*/
|
||||||
|
OPEN_URL,
|
||||||
|
/**
|
||||||
|
* Open a file at the path given by
|
||||||
|
* {@link net.md_5.bungee.api.chat.ClickEvent#getValue()}
|
||||||
|
*/
|
||||||
|
OPEN_FILE,
|
||||||
|
/**
|
||||||
|
* Run the command given by
|
||||||
|
* {@link net.md_5.bungee.api.chat.ClickEvent#getValue()}
|
||||||
|
*/
|
||||||
|
RUN_COMMAND,
|
||||||
|
/**
|
||||||
|
* Inserts the string given by
|
||||||
|
* {@link net.md_5.bungee.api.chat.ClickEvent#getValue()}
|
||||||
|
* into the players text box
|
||||||
|
*/
|
||||||
|
SUGGEST_COMMAND
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return String.format( "ClickEvent{action=%s, value=%s}", action, value );
|
||||||
|
}
|
||||||
|
}
|
157
api/src/main/java/net/md_5/bungee/api/chat/ComponentBuilder.java
Normal file
157
api/src/main/java/net/md_5/bungee/api/chat/ComponentBuilder.java
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
package net.md_5.bungee.api.chat;
|
||||||
|
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import net.md_5.bungee.api.ChatColor;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ComponentBuilder simplifies creating basic messages by allowing
|
||||||
|
* the use of a chainable builder.
|
||||||
|
* <p/>
|
||||||
|
* <pre>
|
||||||
|
* new ComponentBuilder("Hello ").color(ChatColor.RED).
|
||||||
|
* append("World").color(ChatColor.BLUE).
|
||||||
|
* append("!").bold(true).create();
|
||||||
|
* </pre>
|
||||||
|
* <p/>
|
||||||
|
* All methods (excluding {@link #append(String)} and {@link #create()}
|
||||||
|
* work on the last part appended to the builder, so in the example
|
||||||
|
* above "Hello " would be {@link net.md_5.bungee.api.ChatColor#RED}
|
||||||
|
* and "World" would be {@link net.md_5.bungee.api.ChatColor#BLUE} but
|
||||||
|
* "!" would be bold and {@link net.md_5.bungee.api.ChatColor#BLUE}
|
||||||
|
* because append copies the previous part's formatting
|
||||||
|
*/
|
||||||
|
public class ComponentBuilder
|
||||||
|
{
|
||||||
|
private TextComponent current;
|
||||||
|
private List<BaseComponent> parts = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a componentBuilder with the given text as the
|
||||||
|
* first part.
|
||||||
|
*
|
||||||
|
* @param text the first text element
|
||||||
|
*/
|
||||||
|
public ComponentBuilder(String text)
|
||||||
|
{
|
||||||
|
current = new TextComponent( text );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends the text to the builder and makes it the current
|
||||||
|
* target for formatting. The text will have all the
|
||||||
|
* formatting from the previous part.
|
||||||
|
*
|
||||||
|
* @param text the text to append
|
||||||
|
* @return this ComponentBuilder for chaining
|
||||||
|
*/
|
||||||
|
public ComponentBuilder append(String text)
|
||||||
|
{
|
||||||
|
parts.add( current );
|
||||||
|
current = new TextComponent( current );
|
||||||
|
current.setText( text );
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the color of the current part.
|
||||||
|
*
|
||||||
|
* @param color the new color
|
||||||
|
* @return this ComponentBuilder for chaining
|
||||||
|
*/
|
||||||
|
public ComponentBuilder color(ChatColor color)
|
||||||
|
{
|
||||||
|
current.setColor( color );
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the current part is bold.
|
||||||
|
*
|
||||||
|
* @param bold whether this part is bold
|
||||||
|
* @return this ComponentBuilder for chaining
|
||||||
|
*/
|
||||||
|
public ComponentBuilder bold(boolean bold)
|
||||||
|
{
|
||||||
|
current.setBold( bold );
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the current part is italic
|
||||||
|
*
|
||||||
|
* @param italic whether this part is italic
|
||||||
|
* @return this ComponentBuilder for chaining
|
||||||
|
*/
|
||||||
|
public ComponentBuilder italic(boolean italic)
|
||||||
|
{
|
||||||
|
current.setItalic( italic );
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the current part is underlined
|
||||||
|
*
|
||||||
|
* @param underlined whether this part is underlined
|
||||||
|
* @return this ComponentBuilder for chaining
|
||||||
|
*/
|
||||||
|
public ComponentBuilder underlined(boolean underlined)
|
||||||
|
{
|
||||||
|
current.setUnderlined( underlined );
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the current part is strikethrough
|
||||||
|
*
|
||||||
|
* @param strikethrough whether this part is strikethrough
|
||||||
|
* @return this ComponentBuilder for chaining
|
||||||
|
*/
|
||||||
|
public ComponentBuilder strikethrough(boolean strikethrough)
|
||||||
|
{
|
||||||
|
current.setStrikethrough( strikethrough );
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the current pat is obfuscated
|
||||||
|
*
|
||||||
|
* @param obfuscated whether this part is obfuscated
|
||||||
|
* @return this ComponentBuilder for chaining
|
||||||
|
*/
|
||||||
|
public ComponentBuilder obfuscated(boolean obfuscated)
|
||||||
|
{
|
||||||
|
current.setObfuscated( obfuscated );
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the click event for the current part.
|
||||||
|
* @param clickEvent
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public ComponentBuilder event(ClickEvent clickEvent)
|
||||||
|
{
|
||||||
|
current.setClickEvent( clickEvent );
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ComponentBuilder event(HoverEvent hoverEvent)
|
||||||
|
{
|
||||||
|
current.setHoverEvent( hoverEvent );
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the components needed to display the message
|
||||||
|
* created by this builder
|
||||||
|
* @return the created components
|
||||||
|
*/
|
||||||
|
public BaseComponent[] create()
|
||||||
|
{
|
||||||
|
parts.add( current );
|
||||||
|
return parts.toArray( new BaseComponent[parts.size()] );
|
||||||
|
}
|
||||||
|
}
|
27
api/src/main/java/net/md_5/bungee/api/chat/HoverEvent.java
Normal file
27
api/src/main/java/net/md_5/bungee/api/chat/HoverEvent.java
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package net.md_5.bungee.api.chat;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
final public class HoverEvent
|
||||||
|
{
|
||||||
|
private final Action action;
|
||||||
|
private final BaseComponent[] value;
|
||||||
|
|
||||||
|
public enum Action
|
||||||
|
{
|
||||||
|
SHOW_TEXT,
|
||||||
|
SHOW_ACHIEVEMENT,
|
||||||
|
SHOW_ITEM
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return String.format( "HoverEvent{action=%s, value=%s}", action, value );
|
||||||
|
}
|
||||||
|
}
|
158
api/src/main/java/net/md_5/bungee/api/chat/TextComponent.java
Normal file
158
api/src/main/java/net/md_5/bungee/api/chat/TextComponent.java
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
package net.md_5.bungee.api.chat;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import net.md_5.bungee.api.ChatColor;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class TextComponent extends BaseComponent
|
||||||
|
{
|
||||||
|
|
||||||
|
private static final Pattern url = Pattern.compile( "^(?:(https?)://)?([-\\w_\\.]{2,}\\.[a-z]{2,4})(/\\S*)?$" );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
public static BaseComponent[] fromLegacyText(String message)
|
||||||
|
{
|
||||||
|
ArrayList<BaseComponent> components = new ArrayList<>();
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
TextComponent component = new TextComponent();
|
||||||
|
Matcher matcher = url.matcher( message );
|
||||||
|
|
||||||
|
for ( int i = 0; i < message.length(); i++ )
|
||||||
|
{
|
||||||
|
char c = message.charAt( i );
|
||||||
|
if ( c == ChatColor.COLOR_CHAR )
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
c = message.charAt( i );
|
||||||
|
if ( c >= 'A' && c <= 'Z' )
|
||||||
|
{
|
||||||
|
c += 32;
|
||||||
|
}
|
||||||
|
if ( builder.length() > 0 )
|
||||||
|
{
|
||||||
|
TextComponent old = component;
|
||||||
|
component = new TextComponent( old );
|
||||||
|
old.setText( builder.toString() );
|
||||||
|
builder = new StringBuilder();
|
||||||
|
components.add( old );
|
||||||
|
}
|
||||||
|
ChatColor format = ChatColor.getByChar( c );
|
||||||
|
switch ( format )
|
||||||
|
{
|
||||||
|
case BOLD:
|
||||||
|
component.setBold( true );
|
||||||
|
break;
|
||||||
|
case ITALIC:
|
||||||
|
component.setItalic( true );
|
||||||
|
break;
|
||||||
|
case UNDERLINE:
|
||||||
|
component.setUnderlined( true );
|
||||||
|
break;
|
||||||
|
case STRIKETHROUGH:
|
||||||
|
component.setStrikethrough( true );
|
||||||
|
break;
|
||||||
|
case MAGIC:
|
||||||
|
component.setObfuscated( true );
|
||||||
|
break;
|
||||||
|
case RESET:
|
||||||
|
format = ChatColor.WHITE;
|
||||||
|
default:
|
||||||
|
component = new TextComponent();
|
||||||
|
component.setColor( format );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int pos = message.indexOf( ' ', i );
|
||||||
|
if ( pos == -1 ) pos = message.length();
|
||||||
|
if ( matcher.region( i, pos ).find() )
|
||||||
|
{ //Web link handling
|
||||||
|
|
||||||
|
if ( builder.length() > 0 )
|
||||||
|
{
|
||||||
|
TextComponent old = component;
|
||||||
|
component = new TextComponent( old );
|
||||||
|
old.setText( builder.toString() );
|
||||||
|
builder = new StringBuilder();
|
||||||
|
components.add( old );
|
||||||
|
}
|
||||||
|
|
||||||
|
TextComponent old = component;
|
||||||
|
component = new TextComponent( old );
|
||||||
|
String urlString = message.substring( i, pos );
|
||||||
|
component.setText( urlString );
|
||||||
|
component.setClickEvent( new ClickEvent( ClickEvent.Action.OPEN_URL,
|
||||||
|
urlString.startsWith( "http" ) ? urlString : "http://" + urlString ) );
|
||||||
|
components.add( component );
|
||||||
|
i += pos - i - 1;
|
||||||
|
component = old;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
builder.append( c );
|
||||||
|
}
|
||||||
|
if ( builder.length() > 0 )
|
||||||
|
{
|
||||||
|
component.setText( builder.toString() );
|
||||||
|
components.add( component );
|
||||||
|
}
|
||||||
|
return components.toArray( new BaseComponent[components.size()] );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The text of the component that will be
|
||||||
|
* displayed to the client
|
||||||
|
*/
|
||||||
|
private String text;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a TextComponent with formatting and text
|
||||||
|
* from the passed component
|
||||||
|
* @param textComponent the component to copy from
|
||||||
|
*/
|
||||||
|
public TextComponent(TextComponent textComponent)
|
||||||
|
{
|
||||||
|
super( textComponent );
|
||||||
|
setText( textComponent.getText() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void toPlainText(StringBuilder builder)
|
||||||
|
{
|
||||||
|
builder.append( text );
|
||||||
|
super.toPlainText( builder );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void toLegacyText(StringBuilder builder)
|
||||||
|
{
|
||||||
|
builder.append( getColor() );
|
||||||
|
if ( isBold() ) builder.append( ChatColor.BOLD );
|
||||||
|
if ( isItalic() ) builder.append( ChatColor.ITALIC );
|
||||||
|
if ( isUnderlined() ) builder.append( ChatColor.UNDERLINE );
|
||||||
|
if ( isStrikethrough() ) builder.append( ChatColor.STRIKETHROUGH );
|
||||||
|
if ( isObfuscated() ) builder.append( ChatColor.MAGIC );
|
||||||
|
builder.append( text );
|
||||||
|
super.toLegacyText( builder );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return String.format( "TextComponent{text=%s, %s}", text, super.toString() );
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,204 @@
|
|||||||
|
package net.md_5.bungee.api.chat;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import net.md_5.bungee.api.ChatColor;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class TranslatableComponent extends BaseComponent
|
||||||
|
{
|
||||||
|
private final ResourceBundle locales = ResourceBundle.getBundle( "mojang-translations/en_US" );
|
||||||
|
private final Pattern format = Pattern.compile( "%(?:(\\d+)\\$)?([A-Za-z%]|$)" );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The key into the Minecraft locale files to use for the
|
||||||
|
* translation. The text depends on the client's locale setting.
|
||||||
|
* The console is always en_US
|
||||||
|
*/
|
||||||
|
private String translate;
|
||||||
|
/**
|
||||||
|
* The components to substitute into the translation
|
||||||
|
*/
|
||||||
|
private List<BaseComponent> with;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a translatable component with the passed substitutions
|
||||||
|
* @see #setTranslate(String)
|
||||||
|
* @see #setWith(java.util.List)
|
||||||
|
* @param translate the translation key
|
||||||
|
* @param with the {@link java.lang.String}s and {@link net.md_5.bungee.api.chat.BaseComponent}s
|
||||||
|
* to use into the translation
|
||||||
|
*/
|
||||||
|
public TranslatableComponent(String translate, Object... with)
|
||||||
|
{
|
||||||
|
setTranslate( translate );
|
||||||
|
List<BaseComponent> temp = new ArrayList<>();
|
||||||
|
for ( Object w : with )
|
||||||
|
{
|
||||||
|
if ( w instanceof String )
|
||||||
|
{
|
||||||
|
temp.add( new TextComponent( (String) w ) );
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
temp.add( (BaseComponent) w );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setWith( temp );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the translation substitutions to be used in
|
||||||
|
* this component. Removes any previously set
|
||||||
|
* substitutions
|
||||||
|
* @param components the components to substitute
|
||||||
|
*/
|
||||||
|
public void setWith(List<BaseComponent> components)
|
||||||
|
{
|
||||||
|
for ( BaseComponent component : components )
|
||||||
|
{
|
||||||
|
component.parent = this;
|
||||||
|
}
|
||||||
|
with = components;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a text substitution to the component. The text will
|
||||||
|
* inherit this component's formatting
|
||||||
|
*
|
||||||
|
* @param text the text to substitute
|
||||||
|
*/
|
||||||
|
public void addWith(String text)
|
||||||
|
{
|
||||||
|
addWith( new TextComponent( text ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a component substitution to the component. The text will
|
||||||
|
* inherit this component's formatting
|
||||||
|
*
|
||||||
|
* @param component the component to substitute
|
||||||
|
*/
|
||||||
|
public void addWith(BaseComponent component)
|
||||||
|
{
|
||||||
|
if ( with == null )
|
||||||
|
{
|
||||||
|
with = new ArrayList<>();
|
||||||
|
}
|
||||||
|
component.parent = this;
|
||||||
|
with.add( component );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void toPlainText(StringBuilder builder)
|
||||||
|
{
|
||||||
|
String trans = locales.getString( translate );
|
||||||
|
if ( trans == null )
|
||||||
|
{
|
||||||
|
builder.append( translate );
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
Matcher matcher = format.matcher( trans );
|
||||||
|
int position = 0;
|
||||||
|
int i = 0;
|
||||||
|
while ( matcher.find( position ) )
|
||||||
|
{
|
||||||
|
int pos = matcher.start();
|
||||||
|
if ( pos != position )
|
||||||
|
{
|
||||||
|
builder.append( trans.substring( position, pos ) );
|
||||||
|
}
|
||||||
|
position = matcher.end();
|
||||||
|
|
||||||
|
String formatCode = matcher.group( 2 );
|
||||||
|
switch ( formatCode.charAt( 0 ) )
|
||||||
|
{
|
||||||
|
case 's':
|
||||||
|
case 'd':
|
||||||
|
String withIndex = matcher.group( 1 );
|
||||||
|
with.get( withIndex != null ? Integer.parseInt( withIndex ) - 1 : i++ ).toPlainText( builder );
|
||||||
|
break;
|
||||||
|
case '%':
|
||||||
|
builder.append( '%' );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( trans.length() != position )
|
||||||
|
{
|
||||||
|
builder.append( trans.substring( position, trans.length() ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.toPlainText( builder );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void toLegacyText(StringBuilder builder)
|
||||||
|
{
|
||||||
|
String trans = locales.getString( translate );
|
||||||
|
if ( trans == null )
|
||||||
|
{
|
||||||
|
addFormat( builder );
|
||||||
|
builder.append( translate );
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
Matcher matcher = format.matcher( trans );
|
||||||
|
int position = 0;
|
||||||
|
int i = 0;
|
||||||
|
while ( matcher.find( position ) )
|
||||||
|
{
|
||||||
|
int pos = matcher.start();
|
||||||
|
if ( pos != position )
|
||||||
|
{
|
||||||
|
addFormat( builder );
|
||||||
|
builder.append( trans.substring( position, pos ) );
|
||||||
|
}
|
||||||
|
position = matcher.end();
|
||||||
|
|
||||||
|
String formatCode = matcher.group( 2 );
|
||||||
|
switch ( formatCode.charAt( 0 ) )
|
||||||
|
{
|
||||||
|
case 's':
|
||||||
|
case 'd':
|
||||||
|
String withIndex = matcher.group( 1 );
|
||||||
|
with.get( withIndex != null ? Integer.parseInt( withIndex ) - 1 : i++ ).toLegacyText( builder );
|
||||||
|
break;
|
||||||
|
case '%':
|
||||||
|
addFormat( builder );
|
||||||
|
builder.append( '%' );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( trans.length() != position )
|
||||||
|
{
|
||||||
|
addFormat( builder );
|
||||||
|
builder.append( trans.substring( position, trans.length() ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.toLegacyText( builder );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addFormat(StringBuilder builder)
|
||||||
|
{
|
||||||
|
builder.append( getColor() );
|
||||||
|
if ( isBold() ) builder.append( ChatColor.BOLD );
|
||||||
|
if ( isItalic() ) builder.append( ChatColor.ITALIC );
|
||||||
|
if ( isUnderlined() ) builder.append( ChatColor.UNDERLINE );
|
||||||
|
if ( isStrikethrough() ) builder.append( ChatColor.STRIKETHROUGH );
|
||||||
|
if ( isObfuscated() ) builder.append( ChatColor.MAGIC );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return String.format( "TranslatableComponent{translate=%s, with=%s, %s}", translate, with, super.toString() );
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,8 @@
|
|||||||
package net.md_5.bungee.api.connection;
|
package net.md_5.bungee.api.connection;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
|
||||||
|
import net.md_5.bungee.api.chat.BaseComponent;
|
||||||
import net.md_5.bungee.protocol.DefinedPacket;
|
import net.md_5.bungee.protocol.DefinedPacket;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -26,8 +28,29 @@ public interface Connection
|
|||||||
* @param reason the reason shown to the player / sent to the server on
|
* @param reason the reason shown to the player / sent to the server on
|
||||||
* disconnect
|
* disconnect
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
void disconnect(String reason);
|
void disconnect(String reason);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disconnects this end of the connection for the specified reason. If this
|
||||||
|
* is an {@link ProxiedPlayer} the respective server connection will be
|
||||||
|
* closed too.
|
||||||
|
*
|
||||||
|
* @param reason the reason shown to the player / sent to the server on
|
||||||
|
* disconnect
|
||||||
|
*/
|
||||||
|
void disconnect(BaseComponent... reason);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disconnects this end of the connection for the specified reason. If this
|
||||||
|
* is an {@link ProxiedPlayer} the respective server connection will be
|
||||||
|
* closed too.
|
||||||
|
*
|
||||||
|
* @param reason the reason shown to the player / sent to the server on
|
||||||
|
* disconnect
|
||||||
|
*/
|
||||||
|
void disconnect(BaseComponent reason);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the unsafe methods of this class.
|
* Get the unsafe methods of this class.
|
||||||
*
|
*
|
||||||
|
@ -3,6 +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.chat.BaseComponent;
|
||||||
|
import net.md_5.bungee.api.chat.TextComponent;
|
||||||
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.plugin.Cancellable;
|
import net.md_5.bungee.api.plugin.Cancellable;
|
||||||
@ -28,7 +30,7 @@ public class ServerKickEvent extends Event implements Cancellable
|
|||||||
/**
|
/**
|
||||||
* Kick reason.
|
* Kick reason.
|
||||||
*/
|
*/
|
||||||
private String kickReason;
|
private BaseComponent[] kickReasonComponent;
|
||||||
/**
|
/**
|
||||||
* Server to send player to if this event is cancelled.
|
* Server to send player to if this event is cancelled.
|
||||||
*/
|
*/
|
||||||
@ -44,16 +46,26 @@ public class ServerKickEvent extends Event implements Cancellable
|
|||||||
CONNECTING, CONNECTED, UNKNOWN;
|
CONNECTING, CONNECTED, UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ServerKickEvent(ProxiedPlayer player, String kickReason, ServerInfo cancelServer)
|
public ServerKickEvent(ProxiedPlayer player, BaseComponent[] kickReasonComponent, ServerInfo cancelServer)
|
||||||
{
|
{
|
||||||
this( player, kickReason, cancelServer, State.UNKNOWN );
|
this( player, kickReasonComponent, cancelServer, State.UNKNOWN );
|
||||||
}
|
}
|
||||||
|
|
||||||
public ServerKickEvent(ProxiedPlayer player, String kickReason, ServerInfo cancelServer, State state)
|
public ServerKickEvent(ProxiedPlayer player, BaseComponent[] kickReasonComponent, ServerInfo cancelServer, State state)
|
||||||
{
|
{
|
||||||
this.player = player;
|
this.player = player;
|
||||||
this.kickReason = kickReason;
|
this.kickReasonComponent = kickReasonComponent;
|
||||||
this.cancelServer = cancelServer;
|
this.cancelServer = cancelServer;
|
||||||
this.state = state;
|
this.state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public String getKickReason() {
|
||||||
|
return BaseComponent.toLegacyText( kickReasonComponent );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public void setKickReason(String reason) {
|
||||||
|
kickReasonComponent = TextComponent.fromLegacyText( reason );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
package net.md_5.bungee;
|
package net.md_5.bungee;
|
||||||
|
|
||||||
import com.google.common.io.ByteStreams;
|
import com.google.common.io.ByteStreams;
|
||||||
|
import net.md_5.bungee.api.chat.BaseComponent;
|
||||||
|
import net.md_5.bungee.api.chat.TextComponent;
|
||||||
|
import net.md_5.bungee.chat.ComponentSerializer;
|
||||||
import net.md_5.bungee.log.BungeeLogger;
|
import net.md_5.bungee.log.BungeeLogger;
|
||||||
import net.md_5.bungee.reconnect.YamlReconnectHandler;
|
import net.md_5.bungee.reconnect.YamlReconnectHandler;
|
||||||
import net.md_5.bungee.scheduler.BungeeScheduler;
|
import net.md_5.bungee.scheduler.BungeeScheduler;
|
||||||
@ -134,6 +137,7 @@ public class BungeeCord extends ProxyServer
|
|||||||
getPluginManager().registerCommand( null, new CommandPerms() );
|
getPluginManager().registerCommand( null, new CommandPerms() );
|
||||||
getPluginManager().registerCommand( null, new CommandSend() );
|
getPluginManager().registerCommand( null, new CommandSend() );
|
||||||
getPluginManager().registerCommand( null, new CommandFind() );
|
getPluginManager().registerCommand( null, new CommandFind() );
|
||||||
|
getPluginManager().registerCommand( null, new CommandAlertRaw() );
|
||||||
|
|
||||||
registerChannel( "BungeeCord" );
|
registerChannel( "BungeeCord" );
|
||||||
}
|
}
|
||||||
@ -486,11 +490,21 @@ public class BungeeCord extends ProxyServer
|
|||||||
@Override
|
@Override
|
||||||
public void broadcast(String message)
|
public void broadcast(String message)
|
||||||
{
|
{
|
||||||
getConsole().sendMessage( message );
|
broadcast( TextComponent.fromLegacyText( message ) );
|
||||||
// TODO: Here too
|
|
||||||
for (String msg : ChatConverter.toJSONChat( message )) {
|
|
||||||
broadcast( new Chat( msg ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void broadcast(BaseComponent... message)
|
||||||
|
{
|
||||||
|
getConsole().sendMessage( BaseComponent.toLegacyText( message ) );
|
||||||
|
broadcast( new Chat( ComponentSerializer.toString( message ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void broadcast(BaseComponent message)
|
||||||
|
{
|
||||||
|
getConsole().sendMessage( message.toLegacyText() );
|
||||||
|
broadcast( new Chat( ComponentSerializer.toString( message ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addConnection(UserConnection con)
|
public void addConnection(UserConnection con)
|
||||||
|
@ -1,197 +0,0 @@
|
|||||||
package net.md_5.bungee;
|
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.google.gson.annotations.SerializedName;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
public class ChatConverter {
|
|
||||||
|
|
||||||
private static final Gson gson = new Gson();
|
|
||||||
private static final char COLOR_CHAR = '\u00A7';
|
|
||||||
private static final Pattern url = Pattern.compile("^(?:(https?)://)?([-\\w_\\.]{2,}\\.[a-z]{2,4})(/\\S*)?$");
|
|
||||||
|
|
||||||
public static String[] toJSONChat(String txt) {
|
|
||||||
Message msg = new Message();
|
|
||||||
ArrayList<String> parts = new ArrayList<String>();
|
|
||||||
StringBuilder outBuffer = new StringBuilder("[");
|
|
||||||
StringBuilder buf = new StringBuilder();
|
|
||||||
Matcher matcher = url.matcher(txt);
|
|
||||||
for (int i = 0; i < txt.length(); i++) {
|
|
||||||
char c = txt.charAt(i);
|
|
||||||
if (c != COLOR_CHAR) {
|
|
||||||
int pos = txt.indexOf(' ', i);
|
|
||||||
if (pos == -1) pos = txt.length();
|
|
||||||
if (matcher.region(i, pos).find()) { //Web link handling
|
|
||||||
msg.text = buf.toString();
|
|
||||||
buf = new StringBuilder();
|
|
||||||
outBuffer = append(parts, outBuffer, msg);
|
|
||||||
Message old = msg;
|
|
||||||
msg = new Message(old);
|
|
||||||
msg.clickEvent = new ClickEvent();
|
|
||||||
msg.clickEvent.action = "open_url";
|
|
||||||
String urlString = txt.substring(i, pos);
|
|
||||||
if (urlString.startsWith("http")) {
|
|
||||||
msg.text = msg.clickEvent.value = urlString;
|
|
||||||
} else {
|
|
||||||
msg.text = urlString;
|
|
||||||
msg.clickEvent.value = "http://" + urlString;
|
|
||||||
}
|
|
||||||
outBuffer = append(parts, outBuffer, msg);
|
|
||||||
i += pos - i - 1;
|
|
||||||
msg = new Message(old);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
buf.append(c);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
c = txt.charAt(i);
|
|
||||||
if (c >= 'A' && c <= 'Z') {
|
|
||||||
c += 32;
|
|
||||||
}
|
|
||||||
msg.text = buf.toString();
|
|
||||||
buf = new StringBuilder();
|
|
||||||
outBuffer = append(parts, outBuffer, msg);
|
|
||||||
msg = new Message(msg);
|
|
||||||
switch(c) {
|
|
||||||
case 'k':
|
|
||||||
msg.obfuscated = Boolean.TRUE;
|
|
||||||
break;
|
|
||||||
case 'l':
|
|
||||||
msg.bold = Boolean.TRUE;
|
|
||||||
break;
|
|
||||||
case 'm':
|
|
||||||
msg.strikethrough = Boolean.TRUE;
|
|
||||||
break;
|
|
||||||
case 'n':
|
|
||||||
msg.underlined = Boolean.TRUE;
|
|
||||||
break;
|
|
||||||
case 'o':
|
|
||||||
msg.italic = Boolean.TRUE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
msg.obfuscated = null;
|
|
||||||
msg.bold = null;
|
|
||||||
msg.strikethrough = null;
|
|
||||||
msg.underlined = null;
|
|
||||||
msg.italic = null;
|
|
||||||
if (c != 'r') {
|
|
||||||
msg.color = Color.fromCode(Character.toString(c));
|
|
||||||
} else {
|
|
||||||
msg.color = Color.WHITE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
msg.text = buf.toString();
|
|
||||||
append(parts, outBuffer, msg);
|
|
||||||
|
|
||||||
parts.add(outBuffer.append("]").toString());
|
|
||||||
String[] pArray = new String[parts.size()];
|
|
||||||
parts.toArray(pArray);
|
|
||||||
return pArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static StringBuilder append(ArrayList<String> parts, StringBuilder outBuffer, Message part) {
|
|
||||||
String p = gson.toJson(part);
|
|
||||||
if (p.length() + outBuffer.length() + 1 >= Short.MAX_VALUE - 20) {
|
|
||||||
outBuffer.append("]");
|
|
||||||
parts.add(outBuffer.toString());
|
|
||||||
outBuffer = new StringBuilder("[");
|
|
||||||
}
|
|
||||||
if (outBuffer.length() != 1) {
|
|
||||||
outBuffer.append(",");
|
|
||||||
}
|
|
||||||
outBuffer.append(p);
|
|
||||||
return outBuffer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Message {
|
|
||||||
public String text;
|
|
||||||
|
|
||||||
public Boolean bold;
|
|
||||||
public Boolean italic;
|
|
||||||
public Boolean underlined;
|
|
||||||
public Boolean strikethrough;
|
|
||||||
public Boolean obfuscated;
|
|
||||||
|
|
||||||
public Color color;
|
|
||||||
|
|
||||||
public ClickEvent clickEvent;
|
|
||||||
|
|
||||||
public Message() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public Message(Message old) {
|
|
||||||
this.bold = old.bold;
|
|
||||||
this.italic = old.italic;
|
|
||||||
this.underlined = old.underlined;
|
|
||||||
this.strikethrough = old.strikethrough;
|
|
||||||
this.color = old.color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ClickEvent {
|
|
||||||
public String action;
|
|
||||||
public String value;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Color {
|
|
||||||
@SerializedName("black")
|
|
||||||
BLACK("0"),
|
|
||||||
@SerializedName("dark_blue")
|
|
||||||
DARK_BLUE("1"),
|
|
||||||
@SerializedName("dark_green")
|
|
||||||
DARK_GREEN("2"),
|
|
||||||
@SerializedName("dark_aqua")
|
|
||||||
DARK_AQUA("3"),
|
|
||||||
@SerializedName("dark_red")
|
|
||||||
DARK_RED("4"),
|
|
||||||
@SerializedName("dark_purple")
|
|
||||||
DARK_PURPLE("5"),
|
|
||||||
@SerializedName("gold")
|
|
||||||
GOLD("6"),
|
|
||||||
@SerializedName("gray")
|
|
||||||
GRAY("7"),
|
|
||||||
@SerializedName("dark_gray")
|
|
||||||
DARK_GRAY("8"),
|
|
||||||
@SerializedName("blue")
|
|
||||||
BLUE("9"),
|
|
||||||
@SerializedName("green")
|
|
||||||
GREEN("a"),
|
|
||||||
@SerializedName("aqua")
|
|
||||||
AQUA("b"),
|
|
||||||
@SerializedName("red")
|
|
||||||
RED("c"),
|
|
||||||
@SerializedName("light_purple")
|
|
||||||
LIGHT_PURPLE("d"),
|
|
||||||
@SerializedName("yellow")
|
|
||||||
YELLOW("e"),
|
|
||||||
@SerializedName("white")
|
|
||||||
WHITE("f");
|
|
||||||
|
|
||||||
public String code;
|
|
||||||
|
|
||||||
Color(String code) {
|
|
||||||
this.code = code;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static HashMap<String, Color> codeMap = new HashMap<String, Color>();
|
|
||||||
|
|
||||||
public static Color fromCode(String code) {
|
|
||||||
return codeMap.get(code);
|
|
||||||
}
|
|
||||||
|
|
||||||
static {
|
|
||||||
for (Color color : values()) {
|
|
||||||
codeMap.put(color.code, color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,7 +5,10 @@ import java.util.concurrent.TimeUnit;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
import net.md_5.bungee.api.chat.BaseComponent;
|
||||||
|
import net.md_5.bungee.api.chat.TextComponent;
|
||||||
import net.md_5.bungee.api.connection.Server;
|
import net.md_5.bungee.api.connection.Server;
|
||||||
|
import net.md_5.bungee.chat.ComponentSerializer;
|
||||||
import net.md_5.bungee.netty.ChannelWrapper;
|
import net.md_5.bungee.netty.ChannelWrapper;
|
||||||
import net.md_5.bungee.protocol.DefinedPacket;
|
import net.md_5.bungee.protocol.DefinedPacket;
|
||||||
import net.md_5.bungee.protocol.packet.PluginMessage;
|
import net.md_5.bungee.protocol.packet.PluginMessage;
|
||||||
@ -39,11 +42,17 @@ public class ServerConnection implements Server
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void disconnect(String reason)
|
public synchronized void disconnect(String reason)
|
||||||
|
{
|
||||||
|
disconnect( TextComponent.fromLegacyText( reason ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disconnect(BaseComponent... reason)
|
||||||
{
|
{
|
||||||
if ( !ch.isClosed() )
|
if ( !ch.isClosed() )
|
||||||
{
|
{
|
||||||
// TODO: Can we just use a future here?
|
// TODO: Can we just use a future here?
|
||||||
unsafe().sendPacket( new Kick( reason ) );
|
unsafe().sendPacket( new Kick( ComponentSerializer.toString( reason ) ) );
|
||||||
ch.getHandle().eventLoop().schedule( new Runnable()
|
ch.getHandle().eventLoop().schedule( new Runnable()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
@ -53,6 +62,13 @@ public class ServerConnection implements Server
|
|||||||
}
|
}
|
||||||
}, 100, TimeUnit.MILLISECONDS );
|
}, 100, TimeUnit.MILLISECONDS );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disconnect(BaseComponent reason)
|
||||||
|
{
|
||||||
|
disconnect( new BaseComponent[]{reason} );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -15,6 +15,7 @@ import net.md_5.bungee.api.event.ServerSwitchEvent;
|
|||||||
import net.md_5.bungee.api.score.Objective;
|
import net.md_5.bungee.api.score.Objective;
|
||||||
import net.md_5.bungee.api.score.Scoreboard;
|
import net.md_5.bungee.api.score.Scoreboard;
|
||||||
import net.md_5.bungee.api.score.Team;
|
import net.md_5.bungee.api.score.Team;
|
||||||
|
import net.md_5.bungee.chat.ComponentSerializer;
|
||||||
import net.md_5.bungee.connection.CancelSendSignal;
|
import net.md_5.bungee.connection.CancelSendSignal;
|
||||||
import net.md_5.bungee.connection.DownstreamBridge;
|
import net.md_5.bungee.connection.DownstreamBridge;
|
||||||
import net.md_5.bungee.netty.HandlerBoss;
|
import net.md_5.bungee.netty.HandlerBoss;
|
||||||
@ -211,7 +212,7 @@ public class ServerConnector extends PacketHandler
|
|||||||
{
|
{
|
||||||
def = null;
|
def = null;
|
||||||
}
|
}
|
||||||
ServerKickEvent event = bungee.getPluginManager().callEvent( new ServerKickEvent( user, kick.getMessage(), def, ServerKickEvent.State.CONNECTING ) );
|
ServerKickEvent event = bungee.getPluginManager().callEvent( new ServerKickEvent( user, ComponentSerializer.parse(kick.getMessage()), def, ServerKickEvent.State.CONNECTING ) );
|
||||||
if ( event.isCancelled() && event.getCancelServer() != null )
|
if ( event.isCancelled() && event.getCancelServer() != null )
|
||||||
{
|
{
|
||||||
user.connect( event.getCancelServer() );
|
user.connect( event.getCancelServer() );
|
||||||
|
@ -20,12 +20,15 @@ import lombok.NonNull;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import net.md_5.bungee.api.ProxyServer;
|
import net.md_5.bungee.api.ProxyServer;
|
||||||
|
import net.md_5.bungee.api.chat.BaseComponent;
|
||||||
|
import net.md_5.bungee.api.chat.TextComponent;
|
||||||
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.PermissionCheckEvent;
|
import net.md_5.bungee.api.event.PermissionCheckEvent;
|
||||||
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 net.md_5.bungee.api.tab.TabListHandler;
|
import net.md_5.bungee.api.tab.TabListHandler;
|
||||||
|
import net.md_5.bungee.chat.ComponentSerializer;
|
||||||
import net.md_5.bungee.connection.InitialHandler;
|
import net.md_5.bungee.connection.InitialHandler;
|
||||||
import net.md_5.bungee.netty.ChannelWrapper;
|
import net.md_5.bungee.netty.ChannelWrapper;
|
||||||
import net.md_5.bungee.netty.HandlerBoss;
|
import net.md_5.bungee.netty.HandlerBoss;
|
||||||
@ -256,15 +259,27 @@ public final class UserConnection implements ProxiedPlayer
|
|||||||
@Override
|
@Override
|
||||||
public synchronized void disconnect(String reason)
|
public synchronized void disconnect(String reason)
|
||||||
{
|
{
|
||||||
disconnect0( ChatConverter.toJSONChat( reason )[0] );
|
disconnect0( TextComponent.fromLegacyText( reason ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void disconnect0(String reason)
|
@Override
|
||||||
|
public void disconnect(BaseComponent... reason)
|
||||||
|
{
|
||||||
|
disconnect0( reason );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disconnect(BaseComponent reason)
|
||||||
|
{
|
||||||
|
disconnect0( reason );
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void disconnect0(BaseComponent ...reason)
|
||||||
{
|
{
|
||||||
if ( ch.getHandle().isActive() )
|
if ( ch.getHandle().isActive() )
|
||||||
{
|
{
|
||||||
bungee.getLogger().log( Level.INFO, "[" + getName() + "] disconnected with: " + reason );
|
bungee.getLogger().log( Level.INFO, "[" + getName() + "] disconnected with: " + BaseComponent.toLegacyText( reason ) );
|
||||||
unsafe().sendPacket( new Kick( reason ) );
|
unsafe().sendPacket( new Kick( ComponentSerializer.toString( reason ) ) );
|
||||||
ch.close();
|
ch.close();
|
||||||
if ( server != null )
|
if ( server != null )
|
||||||
{
|
{
|
||||||
@ -283,9 +298,7 @@ public final class UserConnection implements ProxiedPlayer
|
|||||||
@Override
|
@Override
|
||||||
public void sendMessage(String message)
|
public void sendMessage(String message)
|
||||||
{
|
{
|
||||||
for(String msg : ChatConverter.toJSONChat( message )) {
|
sendMessage( TextComponent.fromLegacyText( message ) );
|
||||||
unsafe().sendPacket( new Chat( msg ) );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -297,6 +310,18 @@ public final class UserConnection implements ProxiedPlayer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendMessage(BaseComponent... message)
|
||||||
|
{
|
||||||
|
unsafe().sendPacket( new Chat( ComponentSerializer.toString( message ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendMessage(BaseComponent message)
|
||||||
|
{
|
||||||
|
unsafe().sendPacket( new Chat( ComponentSerializer.toString( message ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendData(String channel, byte[] data)
|
public void sendData(String channel, byte[] data)
|
||||||
{
|
{
|
||||||
|
@ -0,0 +1,116 @@
|
|||||||
|
package net.md_5.bungee.chat;
|
||||||
|
|
||||||
|
import com.google.gson.JsonDeserializationContext;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonSerializationContext;
|
||||||
|
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 java.util.Arrays;
|
||||||
|
|
||||||
|
public class BaseComponentSerializer
|
||||||
|
{
|
||||||
|
|
||||||
|
protected void deserialize(JsonObject object, BaseComponent component, JsonDeserializationContext context)
|
||||||
|
{
|
||||||
|
if ( object.has( "color" ) )
|
||||||
|
{
|
||||||
|
component.setColor( ChatColor.valueOf( object.get( "color" ).getAsString().toUpperCase() ) );
|
||||||
|
}
|
||||||
|
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.setUnderlined( object.get( "strikethrough" ).getAsBoolean() );
|
||||||
|
}
|
||||||
|
if ( object.has( "obfuscated" ) )
|
||||||
|
{
|
||||||
|
component.setUnderlined( object.get( "obfuscated" ).getAsBoolean() );
|
||||||
|
}
|
||||||
|
if ( object.has( "extra" ) )
|
||||||
|
{
|
||||||
|
component.setExtra( Arrays.<BaseComponent>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() ),
|
||||||
|
event.get( "value" ).getAsString() ) );
|
||||||
|
}
|
||||||
|
if ( object.has( "hoverEvent" ) )
|
||||||
|
{
|
||||||
|
JsonObject event = object.getAsJsonObject( "hoverEvent" );
|
||||||
|
BaseComponent[] res;
|
||||||
|
if (event.get("value").isJsonArray()) {
|
||||||
|
res = context.deserialize( event.get( "value" ), BaseComponent[].class );
|
||||||
|
} else {
|
||||||
|
res = new BaseComponent[]{context.<BaseComponent>deserialize( event.get( "value" ), BaseComponent.class )};
|
||||||
|
}
|
||||||
|
component.setHoverEvent( new HoverEvent( HoverEvent.Action.valueOf( event.get( "action" ).getAsString().toUpperCase() ), res ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void serialize(JsonObject object, BaseComponent component, JsonSerializationContext context)
|
||||||
|
{
|
||||||
|
if ( component.getColorRaw() != null )
|
||||||
|
{
|
||||||
|
object.addProperty( "color", component.getColorRaw().getName() );
|
||||||
|
}
|
||||||
|
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.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() );
|
||||||
|
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() );
|
||||||
|
hoverEvent.add( "value", context.serialize( component.getHoverEvent().getValue() ) );
|
||||||
|
object.add( "hoverEvent", hoverEvent );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
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.JsonSerializationContext;
|
||||||
|
import com.google.gson.JsonSerializer;
|
||||||
|
import net.md_5.bungee.api.chat.BaseComponent;
|
||||||
|
import net.md_5.bungee.api.chat.TextComponent;
|
||||||
|
import net.md_5.bungee.api.chat.TranslatableComponent;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
public class ComponentSerializer implements JsonSerializer<BaseComponent>, JsonDeserializer<BaseComponent>
|
||||||
|
{
|
||||||
|
|
||||||
|
private final static Gson gson = new GsonBuilder().
|
||||||
|
registerTypeAdapter( BaseComponent.class, new ComponentSerializer() ).
|
||||||
|
registerTypeAdapter( TextComponent.class, new TextComponentSerializer() ).
|
||||||
|
registerTypeAdapter( TranslatableComponent.class, new TranslatableComponentSerializer() ).
|
||||||
|
create();
|
||||||
|
|
||||||
|
public static BaseComponent[] parse(String json)
|
||||||
|
{
|
||||||
|
if ( json.startsWith( "[" ) )
|
||||||
|
{ //Array
|
||||||
|
return gson.fromJson( json, BaseComponent[].class );
|
||||||
|
}
|
||||||
|
return new BaseComponent[]{gson.fromJson( json, BaseComponent.class )};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String toString(BaseComponent component)
|
||||||
|
{
|
||||||
|
return gson.toJson( component );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String toString(BaseComponent... components)
|
||||||
|
{
|
||||||
|
return gson.toJson( 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 );
|
||||||
|
}
|
||||||
|
return context.deserialize( json, TextComponent.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsonElement serialize(BaseComponent src, Type typeOfSrc, JsonSerializationContext context)
|
||||||
|
{
|
||||||
|
return context.serialize( src, src.getClass() );
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
package net.md_5.bungee.chat;
|
||||||
|
|
||||||
|
import com.google.gson.JsonDeserializationContext;
|
||||||
|
import com.google.gson.JsonDeserializer;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParseException;
|
||||||
|
import com.google.gson.JsonPrimitive;
|
||||||
|
import com.google.gson.JsonSerializationContext;
|
||||||
|
import com.google.gson.JsonSerializer;
|
||||||
|
import net.md_5.bungee.api.chat.TextComponent;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
public class TextComponentSerializer extends BaseComponentSerializer implements JsonSerializer<TextComponent>, JsonDeserializer<TextComponent>
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public TextComponent deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
|
||||||
|
{
|
||||||
|
TextComponent component = new TextComponent();
|
||||||
|
JsonObject object = json.getAsJsonObject();
|
||||||
|
deserialize( object, component, context );
|
||||||
|
component.setText( object.get( "text" ).getAsString() );
|
||||||
|
return component;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsonElement serialize(TextComponent src, Type typeOfSrc, JsonSerializationContext context)
|
||||||
|
{
|
||||||
|
if ( !src.hasFormatting() )
|
||||||
|
{
|
||||||
|
return new JsonPrimitive( src.getText() );
|
||||||
|
}
|
||||||
|
JsonObject object = new JsonObject();
|
||||||
|
serialize( object, src, context );
|
||||||
|
object.addProperty( "text", src.getText() );
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
package net.md_5.bungee.chat;
|
||||||
|
|
||||||
|
import com.google.gson.JsonDeserializationContext;
|
||||||
|
import com.google.gson.JsonDeserializer;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParseException;
|
||||||
|
import com.google.gson.JsonSerializationContext;
|
||||||
|
import com.google.gson.JsonSerializer;
|
||||||
|
import net.md_5.bungee.api.chat.BaseComponent;
|
||||||
|
import net.md_5.bungee.api.chat.TranslatableComponent;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class TranslatableComponentSerializer extends BaseComponentSerializer implements JsonSerializer<TranslatableComponent>, JsonDeserializer<TranslatableComponent>
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public TranslatableComponent deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
|
||||||
|
{
|
||||||
|
TranslatableComponent component = new TranslatableComponent();
|
||||||
|
JsonObject object = json.getAsJsonObject();
|
||||||
|
deserialize( object, component, context );
|
||||||
|
component.setTranslate( object.get( "translate" ).getAsString() );
|
||||||
|
if ( object.has( "with" ) )
|
||||||
|
{
|
||||||
|
component.setWith( Arrays.asList( (BaseComponent[]) context.deserialize( object.get( "with" ), BaseComponent[].class ) ) );
|
||||||
|
}
|
||||||
|
return component;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsonElement serialize(TranslatableComponent src, Type typeOfSrc, JsonSerializationContext context)
|
||||||
|
{
|
||||||
|
JsonObject object = new JsonObject();
|
||||||
|
serialize( object, src, context );
|
||||||
|
object.addProperty( "translate", src.getTranslate() );
|
||||||
|
if ( src.getWith() != null )
|
||||||
|
{
|
||||||
|
object.add( "with", context.serialize( src.getWith() ) );
|
||||||
|
}
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
package net.md_5.bungee.command;
|
||||||
|
|
||||||
|
import com.google.common.base.Joiner;
|
||||||
|
import net.md_5.bungee.api.ChatColor;
|
||||||
|
import net.md_5.bungee.api.CommandSender;
|
||||||
|
import net.md_5.bungee.api.ProxyServer;
|
||||||
|
import net.md_5.bungee.api.chat.ComponentBuilder;
|
||||||
|
import net.md_5.bungee.api.chat.HoverEvent;
|
||||||
|
import net.md_5.bungee.api.chat.TextComponent;
|
||||||
|
import net.md_5.bungee.api.plugin.Command;
|
||||||
|
import net.md_5.bungee.chat.ComponentSerializer;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class CommandAlertRaw extends Command
|
||||||
|
{
|
||||||
|
|
||||||
|
public CommandAlertRaw()
|
||||||
|
{
|
||||||
|
super( "alertraw", "bungeecord.command.alert" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(CommandSender sender, String[] args)
|
||||||
|
{
|
||||||
|
if ( args.length == 0 )
|
||||||
|
{
|
||||||
|
sender.sendMessage( ChatColor.RED + "You must supply a message." );
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
String message = Joiner.on(' ').join( args );
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ProxyServer.getInstance().broadcast( ComponentSerializer.parse( message ) );
|
||||||
|
} catch ( Exception e )
|
||||||
|
{
|
||||||
|
sender.sendMessage(
|
||||||
|
new ComponentBuilder( "An error occured while parsing your message. (Hover for details)" ).
|
||||||
|
color( ChatColor.RED ).underlined( true ).
|
||||||
|
event( new HoverEvent( HoverEvent.Action.SHOW_TEXT,
|
||||||
|
new ComponentBuilder( e.getMessage() ).color( ChatColor.RED ).create() ) ).
|
||||||
|
create() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,7 @@ import java.util.Collections;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import net.md_5.bungee.api.CommandSender;
|
import net.md_5.bungee.api.CommandSender;
|
||||||
import net.md_5.bungee.api.ProxyServer;
|
import net.md_5.bungee.api.ProxyServer;
|
||||||
|
import net.md_5.bungee.api.chat.BaseComponent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Command sender representing the proxy console.
|
* Command sender representing the proxy console.
|
||||||
@ -34,6 +35,18 @@ public class ConsoleCommandSender implements CommandSender
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendMessage(BaseComponent... message)
|
||||||
|
{
|
||||||
|
sendMessage( BaseComponent.toLegacyText( message ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendMessage(BaseComponent message)
|
||||||
|
{
|
||||||
|
sendMessage( message.toLegacyText() );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName()
|
public String getName()
|
||||||
{
|
{
|
||||||
|
@ -20,6 +20,7 @@ import net.md_5.bungee.api.score.Position;
|
|||||||
import net.md_5.bungee.api.score.Score;
|
import net.md_5.bungee.api.score.Score;
|
||||||
import net.md_5.bungee.api.score.Scoreboard;
|
import net.md_5.bungee.api.score.Scoreboard;
|
||||||
import net.md_5.bungee.api.score.Team;
|
import net.md_5.bungee.api.score.Team;
|
||||||
|
import net.md_5.bungee.chat.ComponentSerializer;
|
||||||
import net.md_5.bungee.netty.ChannelWrapper;
|
import net.md_5.bungee.netty.ChannelWrapper;
|
||||||
import net.md_5.bungee.netty.PacketHandler;
|
import net.md_5.bungee.netty.PacketHandler;
|
||||||
import net.md_5.bungee.protocol.PacketWrapper;
|
import net.md_5.bungee.protocol.PacketWrapper;
|
||||||
@ -355,13 +356,13 @@ public class DownstreamBridge extends PacketHandler
|
|||||||
{
|
{
|
||||||
def = null;
|
def = null;
|
||||||
}
|
}
|
||||||
ServerKickEvent event = bungee.getPluginManager().callEvent( new ServerKickEvent( con, kick.getMessage(), def, ServerKickEvent.State.CONNECTED ) );
|
ServerKickEvent event = bungee.getPluginManager().callEvent( new ServerKickEvent( con, ComponentSerializer.parse(kick.getMessage()), def, ServerKickEvent.State.CONNECTED ) );
|
||||||
if ( event.isCancelled() && event.getCancelServer() != null )
|
if ( event.isCancelled() && event.getCancelServer() != null )
|
||||||
{
|
{
|
||||||
con.connectNow( event.getCancelServer() );
|
con.connectNow( event.getCancelServer() );
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
con.disconnect0( event.getKickReason() ); // TODO: Json concat util method // TODO: Prefix our own stuff.
|
con.disconnect0( event.getKickReasonComponent() ); // TODO: Prefix our own stuff.
|
||||||
}
|
}
|
||||||
server.setObsolete( true );
|
server.setObsolete( true );
|
||||||
throw new CancelSendSignal();
|
throw new CancelSendSignal();
|
||||||
|
@ -16,6 +16,8 @@ import net.md_5.bungee.api.Callback;
|
|||||||
import net.md_5.bungee.api.ChatColor;
|
import net.md_5.bungee.api.ChatColor;
|
||||||
import net.md_5.bungee.api.ProxyServer;
|
import net.md_5.bungee.api.ProxyServer;
|
||||||
import net.md_5.bungee.api.ServerPing;
|
import net.md_5.bungee.api.ServerPing;
|
||||||
|
import net.md_5.bungee.api.chat.BaseComponent;
|
||||||
|
import net.md_5.bungee.api.chat.TextComponent;
|
||||||
import net.md_5.bungee.api.config.ListenerInfo;
|
import net.md_5.bungee.api.config.ListenerInfo;
|
||||||
import net.md_5.bungee.api.config.ServerInfo;
|
import net.md_5.bungee.api.config.ServerInfo;
|
||||||
import net.md_5.bungee.api.connection.PendingConnection;
|
import net.md_5.bungee.api.connection.PendingConnection;
|
||||||
@ -23,6 +25,7 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
|
|||||||
import net.md_5.bungee.api.event.LoginEvent;
|
import net.md_5.bungee.api.event.LoginEvent;
|
||||||
import net.md_5.bungee.api.event.PostLoginEvent;
|
import net.md_5.bungee.api.event.PostLoginEvent;
|
||||||
import net.md_5.bungee.api.event.ProxyPingEvent;
|
import net.md_5.bungee.api.event.ProxyPingEvent;
|
||||||
|
import net.md_5.bungee.chat.ComponentSerializer;
|
||||||
import net.md_5.bungee.http.HttpClient;
|
import net.md_5.bungee.http.HttpClient;
|
||||||
import net.md_5.bungee.netty.HandlerBoss;
|
import net.md_5.bungee.netty.HandlerBoss;
|
||||||
import net.md_5.bungee.netty.ChannelWrapper;
|
import net.md_5.bungee.netty.ChannelWrapper;
|
||||||
@ -397,11 +400,27 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
|||||||
{
|
{
|
||||||
if (!ch.isClosed())
|
if (!ch.isClosed())
|
||||||
{
|
{
|
||||||
unsafe().sendPacket( new Kick( ChatConverter.toJSONChat( reason )[0] ) );
|
unsafe().sendPacket( new Kick( ComponentSerializer.toString( TextComponent.fromLegacyText( reason ) ) ) );
|
||||||
ch.close();
|
ch.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disconnect(BaseComponent... reason)
|
||||||
|
{
|
||||||
|
if ( !ch.isClosed() )
|
||||||
|
{
|
||||||
|
unsafe().sendPacket( new Kick( ComponentSerializer.toString( reason ) ) );
|
||||||
|
ch.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disconnect(BaseComponent reason)
|
||||||
|
{
|
||||||
|
disconnect( new BaseComponent[]{reason} );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName()
|
public String getName()
|
||||||
{
|
{
|
||||||
|
1685
proxy/src/main/resources/mojang-translations/en_US.properties
Normal file
1685
proxy/src/main/resources/mojang-translations/en_US.properties
Normal file
File diff suppressed because it is too large
Load Diff
82
proxy/src/test/java/net/md_5/bungee/chat/ComponentsTest.java
Normal file
82
proxy/src/test/java/net/md_5/bungee/chat/ComponentsTest.java
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
package net.md_5.bungee.chat;
|
||||||
|
|
||||||
|
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.ComponentBuilder;
|
||||||
|
import net.md_5.bungee.api.chat.TextComponent;
|
||||||
|
import net.md_5.bungee.api.chat.TranslatableComponent;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class ComponentsTest
|
||||||
|
{
|
||||||
|
@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.WHITEs 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", 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() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user