Chat Component API
This commit is contained in:
parent
85c27f30ee
commit
c20d8f9cd6
@ -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
|
||||||
@ -27,6 +29,20 @@ public interface CommandSender
|
|||||||
*/
|
*/
|
||||||
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;
|
||||||
@ -233,6 +234,20 @@ public abstract class ProxyServer
|
|||||||
*/
|
*/
|
||||||
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.
|
||||||
*
|
*
|
||||||
|
256
api/src/main/java/net/md_5/bungee/api/chat/BaseComponent.java
Normal file
256
api/src/main/java/net/md_5/bungee/api/chat/BaseComponent.java
Normal file
@ -0,0 +1,256 @@
|
|||||||
|
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.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
public abstract class BaseComponent {
|
||||||
|
|
||||||
|
@Getter(AccessLevel.NONE)
|
||||||
|
@Setter(AccessLevel.NONE)
|
||||||
|
BaseComponent parent;
|
||||||
|
|
||||||
|
//Formatting
|
||||||
|
@Getter(AccessLevel.NONE)
|
||||||
|
private ChatColor color;
|
||||||
|
@Getter(AccessLevel.NONE)
|
||||||
|
private Boolean bold;
|
||||||
|
@Getter(AccessLevel.NONE)
|
||||||
|
private Boolean italic;
|
||||||
|
@Getter(AccessLevel.NONE)
|
||||||
|
private Boolean underlined;
|
||||||
|
@Getter(AccessLevel.NONE)
|
||||||
|
private Boolean strikethrough;
|
||||||
|
@Getter(AccessLevel.NONE)
|
||||||
|
private Boolean obfuscated;
|
||||||
|
|
||||||
|
//Appended components
|
||||||
|
private List<BaseComponent> extra;
|
||||||
|
|
||||||
|
//Events
|
||||||
|
private ClickEvent clickEvent;
|
||||||
|
private HoverEvent hoverEvent;
|
||||||
|
|
||||||
|
public BaseComponent(BaseComponent old) {
|
||||||
|
setColor(old.getColorRaw());
|
||||||
|
setBold(old.isBoldRaw());
|
||||||
|
setItalic(old.isItalicRaw());
|
||||||
|
setUnderlined(old.isUnderlined());
|
||||||
|
setStrikethrough(old.isStrikethroughRaw());
|
||||||
|
setObfuscated(old.isObfuscatedRaw());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasFormatting() {
|
||||||
|
return color != null || bold != null ||
|
||||||
|
italic != null || underlined != null ||
|
||||||
|
strikethrough != null || obfuscated != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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}", getColor().getName(), isBold(), isItalic(), isUnderlined(), isStrikethrough(), isObfuscated());
|
||||||
|
}
|
||||||
|
}
|
23
api/src/main/java/net/md_5/bungee/api/chat/ClickEvent.java
Normal file
23
api/src/main/java/net/md_5/bungee/api/chat/ClickEvent.java
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package net.md_5.bungee.api.chat;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class ClickEvent {
|
||||||
|
private Action action;
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
public enum Action {
|
||||||
|
OPEN_URL,
|
||||||
|
OPEN_FILE,
|
||||||
|
RUN_COMMAND,
|
||||||
|
SUGGEST_COMMAND
|
||||||
|
}
|
||||||
|
}
|
39
api/src/main/java/net/md_5/bungee/api/chat/HoverEvent.java
Normal file
39
api/src/main/java/net/md_5/bungee/api/chat/HoverEvent.java
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
package net.md_5.bungee.api.chat;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class HoverEvent {
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private Action action;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private Object value;
|
||||||
|
|
||||||
|
public HoverEvent(Action action, String value) {
|
||||||
|
setAction(action);
|
||||||
|
setValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public HoverEvent(Action action, BaseComponent value) {
|
||||||
|
setAction(action);
|
||||||
|
setValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(BaseComponent value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Action {
|
||||||
|
SHOW_TEXT,
|
||||||
|
SHOW_ACHIEVEMENT,
|
||||||
|
SHOW_ITEM
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
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;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class TextComponent extends BaseComponent {
|
||||||
|
private String text;
|
||||||
|
|
||||||
|
public TextComponent(TextComponent old) {
|
||||||
|
super(old);
|
||||||
|
setText(old.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,53 @@
|
|||||||
|
package net.md_5.bungee.api.chat;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class TranslatableComponent extends BaseComponent {
|
||||||
|
|
||||||
|
private String translate;
|
||||||
|
private List<BaseComponent> with;
|
||||||
|
|
||||||
|
public TranslatableComponent(String translate, Object ...with) {
|
||||||
|
setTranslate(translate);
|
||||||
|
this.with = new ArrayList<>();
|
||||||
|
for (Object w : with) {
|
||||||
|
if (w instanceof String) {
|
||||||
|
this.with.add(new TextComponent((String) w));
|
||||||
|
} else {
|
||||||
|
this.with.add((BaseComponent) w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWith(List<BaseComponent> components) {
|
||||||
|
for (BaseComponent component : components) {
|
||||||
|
component.parent = this;
|
||||||
|
}
|
||||||
|
with = components;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void toPlainText(StringBuilder builder) {
|
||||||
|
//TODO
|
||||||
|
super.toPlainText(builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void toLegacyText(StringBuilder builder) {
|
||||||
|
//TODO
|
||||||
|
super.toLegacyText(builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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;
|
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.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;
|
||||||
@ -487,10 +489,23 @@ public class BungeeCord extends ProxyServer
|
|||||||
public void broadcast(String message)
|
public void broadcast(String message)
|
||||||
{
|
{
|
||||||
getConsole().sendMessage( message );
|
getConsole().sendMessage( message );
|
||||||
// TODO: Here too
|
broadcast(ComponentSerializer.fromLegacyChat(message));
|
||||||
for (String msg : ChatConverter.toJSONChat( message )) {
|
|
||||||
broadcast( new Chat( msg ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void broadcast(BaseComponent[] message) {
|
||||||
|
StringBuilder constr = new StringBuilder();
|
||||||
|
for (BaseComponent msg : message) {
|
||||||
|
constr.append( msg.toLegacyText() );
|
||||||
|
}
|
||||||
|
getConsole().sendMessage( constr.toString() );
|
||||||
|
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -20,12 +20,14 @@ 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.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,7 +258,7 @@ 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( ComponentSerializer.toString( ComponentSerializer.fromLegacyChat( reason ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void disconnect0(String reason)
|
public synchronized void disconnect0(String reason)
|
||||||
@ -283,9 +285,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(ComponentSerializer.fromLegacyChat(message));
|
||||||
unsafe().sendPacket( new Chat( msg ) );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -297,6 +297,16 @@ 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,95 @@
|
|||||||
|
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.asList((BaseComponent[])context.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");
|
||||||
|
HoverEvent hoverEvent = new HoverEvent();
|
||||||
|
hoverEvent.setAction(HoverEvent.Action.valueOf(event.get("action").getAsString().toUpperCase()));
|
||||||
|
Object res = context.deserialize(event.get("value"), BaseComponent.class);
|
||||||
|
if (res instanceof String) {
|
||||||
|
hoverEvent.setValue((String) res);
|
||||||
|
} else {
|
||||||
|
hoverEvent.setValue((BaseComponent) res);
|
||||||
|
}
|
||||||
|
component.setHoverEvent(hoverEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
if (component.getHoverEvent() != null) {
|
||||||
|
JsonObject clickEvent = new JsonObject();
|
||||||
|
clickEvent.addProperty("action", component.getHoverEvent().getAction().toString().toLowerCase());
|
||||||
|
clickEvent.add("value", context.serialize(component.getHoverEvent().getValue()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,147 @@
|
|||||||
|
package net.md_5.bungee.chat;
|
||||||
|
|
||||||
|
import com.google.gson.*;
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
import com.google.gson.stream.JsonReader;
|
||||||
|
import com.google.gson.stream.JsonWriter;
|
||||||
|
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.TextComponent;
|
||||||
|
import net.md_5.bungee.api.chat.TranslatableComponent;
|
||||||
|
|
||||||
|
import javax.xml.soap.Text;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
private static final Pattern url = Pattern.compile("^(?:(https?)://)?([-\\w_\\.]{2,}\\.[a-z]{2,4})(/\\S*)?$");
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BaseComponent[] fromLegacyChat(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);
|
||||||
|
ClickEvent clickEvent = new ClickEvent();
|
||||||
|
clickEvent.setAction(ClickEvent.Action.OPEN_URL);
|
||||||
|
String urlString = message.substring(i, pos);
|
||||||
|
if (urlString.startsWith("http")) {
|
||||||
|
component.setText(urlString);
|
||||||
|
clickEvent.setValue(urlString);
|
||||||
|
} else {
|
||||||
|
component.setText(urlString);
|
||||||
|
clickEvent.setValue("http://" + urlString);
|
||||||
|
}
|
||||||
|
component.setClickEvent(clickEvent);
|
||||||
|
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()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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,28 @@
|
|||||||
|
package net.md_5.bungee.chat;
|
||||||
|
|
||||||
|
import com.google.gson.*;
|
||||||
|
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,35 @@
|
|||||||
|
package net.md_5.bungee.chat;
|
||||||
|
|
||||||
|
import com.google.gson.*;
|
||||||
|
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;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
@ -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,20 @@ public class ConsoleCommandSender implements CommandSender
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendMessage(BaseComponent[] message) {
|
||||||
|
StringBuilder constr = new StringBuilder();
|
||||||
|
for (BaseComponent msg : message) {
|
||||||
|
constr.append( msg.toLegacyText() );
|
||||||
|
}
|
||||||
|
sendMessage( constr.toString() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendMessage(BaseComponent message) {
|
||||||
|
sendMessage( message.toLegacyText() );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName()
|
public String getName()
|
||||||
{
|
{
|
||||||
|
@ -23,6 +23,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,7 +398,7 @@ 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(ComponentSerializer.fromLegacyChat(reason)) ) );
|
||||||
ch.close();
|
ch.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user