Improve chat API + removed old Player API
This commit is contained in:
parent
6b7098eacd
commit
2e334af7a1
@ -2,15 +2,24 @@ package fr.pandacube.lib.core.chat;
|
|||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import java.util.function.UnaryOperator;
|
import java.util.function.UnaryOperator;
|
||||||
|
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
|
||||||
import net.kyori.adventure.key.Key;
|
import net.kyori.adventure.key.Key;
|
||||||
|
import net.kyori.adventure.text.BlockNBTComponent;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.ComponentBuilder;
|
||||||
import net.kyori.adventure.text.ComponentLike;
|
import net.kyori.adventure.text.ComponentLike;
|
||||||
|
import net.kyori.adventure.text.EntityNBTComponent;
|
||||||
|
import net.kyori.adventure.text.KeybindComponent;
|
||||||
|
import net.kyori.adventure.text.ScoreComponent;
|
||||||
|
import net.kyori.adventure.text.SelectorComponent;
|
||||||
|
import net.kyori.adventure.text.StorageNBTComponent;
|
||||||
import net.kyori.adventure.text.TextComponent;
|
import net.kyori.adventure.text.TextComponent;
|
||||||
|
import net.kyori.adventure.text.TranslatableComponent;
|
||||||
import net.kyori.adventure.text.event.ClickEvent;
|
import net.kyori.adventure.text.event.ClickEvent;
|
||||||
import net.kyori.adventure.text.event.HoverEvent;
|
import net.kyori.adventure.text.event.HoverEvent;
|
||||||
import net.kyori.adventure.text.event.HoverEventSource;
|
import net.kyori.adventure.text.event.HoverEventSource;
|
||||||
@ -26,33 +35,33 @@ import net.md_5.bungee.api.chat.BaseComponent;
|
|||||||
|
|
||||||
public abstract class Chat extends ChatStatic implements HoverEventSource<Component>, ComponentLike {
|
public abstract class Chat extends ChatStatic implements HoverEventSource<Component>, ComponentLike {
|
||||||
|
|
||||||
protected Component component;
|
protected ComponentBuilder<?, ?> builder;
|
||||||
protected boolean console = false;
|
protected boolean console = false;
|
||||||
|
|
||||||
protected Chat(Component c) {
|
protected Chat(ComponentBuilder<?, ?> b) {
|
||||||
Objects.requireNonNull(c, "Provided component must not be null");
|
Objects.requireNonNull(b, "Provided component builder must not be null");
|
||||||
component = c;
|
builder = b;
|
||||||
}
|
|
||||||
|
|
||||||
public BaseComponent get() {
|
|
||||||
return toBungee(component);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Component getAdv() {
|
public Component getAdv() {
|
||||||
return component;
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseComponent get() {
|
||||||
|
return toBungee(getAdv());
|
||||||
}
|
}
|
||||||
|
|
||||||
public BaseComponent[] getAsArray() {
|
public BaseComponent[] getAsArray() {
|
||||||
return toBungeeArray(component);
|
return toBungeeArray(getAdv());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getLegacyText() {
|
public String getLegacyText() {
|
||||||
return LegacyComponentSerializer.legacySection().serializeOr(component, "");
|
return LegacyComponentSerializer.legacySection().serializeOr(getAdv(), "");
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPlainText() {
|
public String getPlainText() {
|
||||||
return PlainComponentSerializer.plain().serializeOr(component, "");
|
return PlainComponentSerializer.plain().serializeOr(getAdv(), "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -61,15 +70,6 @@ public abstract class Chat extends ChatStatic implements HoverEventSource<Compon
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public Chat then(BaseComponent subComponent) {
|
|
||||||
return then(toAdventure(subComponent));
|
|
||||||
}
|
|
||||||
public Chat then(Chat comp) {
|
|
||||||
return then(comp.getAdv());
|
|
||||||
}
|
|
||||||
public Chat then(BaseComponent[] components) {
|
|
||||||
return then(toAdventure(components));
|
|
||||||
}
|
|
||||||
public Chat then(Component comp) {
|
public Chat then(Component comp) {
|
||||||
if (comp instanceof TextComponent) {
|
if (comp instanceof TextComponent) {
|
||||||
TextComponent txtComp = (TextComponent) comp;
|
TextComponent txtComp = (TextComponent) comp;
|
||||||
@ -83,39 +83,33 @@ public abstract class Chat extends ChatStatic implements HoverEventSource<Compon
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
component.append(comp);
|
builder.append(comp);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
public Chat then(BaseComponent subComponent) {
|
||||||
|
return then(toAdventure(subComponent));
|
||||||
|
}
|
||||||
|
public Chat then(Chat comp) {
|
||||||
|
return then(comp.getAdv());
|
||||||
|
}
|
||||||
|
public Chat then(BaseComponent[] components) {
|
||||||
|
return then(toAdventure(components));
|
||||||
|
}
|
||||||
|
|
||||||
public Chat thenText(Object plainText) { return then(text(plainText)); }
|
public Chat thenText(Object plainText) { return then(text(plainText)); }
|
||||||
|
|
||||||
public Chat thenInfo(Object plainText) { return then(infoText(plainText)); }
|
public Chat thenInfo(Object plainText) { return then(infoText(plainText)); }
|
||||||
|
|
||||||
public Chat thenSuccess(Object plainText) { return then(successText(plainText)); }
|
public Chat thenSuccess(Object plainText) { return then(successText(plainText)); }
|
||||||
|
|
||||||
public Chat thenFailure(Object plainText) { return then(failureText(plainText)); }
|
public Chat thenFailure(Object plainText) { return then(failureText(plainText)); }
|
||||||
|
|
||||||
public Chat thenData(Object plainText) { return then(dataText(plainText)); }
|
public Chat thenData(Object plainText) { return then(dataText(plainText)); }
|
||||||
|
|
||||||
public Chat thenDecoration(Object plainText) { return then(decorationText(plainText)); }
|
public Chat thenDecoration(Object plainText) { return then(decorationText(plainText)); }
|
||||||
|
|
||||||
public Chat thenPlayerName(String legacyText) { return then(playerNameText(legacyText)); }
|
public Chat thenPlayerName(String legacyText) { return then(playerNameText(legacyText)); }
|
||||||
|
|
||||||
public Chat thenPlayerName(Component comp) { return then(playerNameComponent(comp)); }
|
public Chat thenPlayerName(Component comp) { return then(playerNameComponent(comp)); }
|
||||||
|
|
||||||
public Chat thenNewLine() { return then(Component.newline()); }
|
public Chat thenNewLine() { return then(Component.newline()); }
|
||||||
|
|
||||||
public Chat thenLegacyText(Object legacyText) { return then(legacyText(legacyText)); }
|
public Chat thenLegacyText(Object legacyText) { return then(legacyText(legacyText)); }
|
||||||
|
|
||||||
public Chat thenTranslation(String key, Object... with) { return then(translation(key, with)); }
|
public Chat thenTranslation(String key, Object... with) { return then(translation(key, with)); }
|
||||||
|
|
||||||
public Chat thenKeyBind(String key) { return then(keybind(key)); }
|
public Chat thenKeyBind(String key) { return then(keybind(key)); }
|
||||||
|
|
||||||
public Chat thenScore(String name, String objective) { return then(score(name, objective)); }
|
public Chat thenScore(String name, String objective) { return then(score(name, objective)); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public Chat thenURLLink(Chat inner, String url, Chat hover) { return then(ChatUtil.createURLLink(inner, url, hover)); }
|
public Chat thenURLLink(Chat inner, String url, Chat hover) { return then(ChatUtil.createURLLink(inner, url, hover)); }
|
||||||
public Chat thenURLLink(Chat inner, String url) { return thenURLLink(inner, url, null); }
|
public Chat thenURLLink(Chat inner, String url) { return thenURLLink(inner, url, null); }
|
||||||
public Chat thenURLLink(String url, Chat hover) { return thenURLLink(text(url), url, hover); }
|
public Chat thenURLLink(String url, Chat hover) { return thenURLLink(text(url), url, hover); }
|
||||||
@ -212,13 +206,13 @@ public abstract class Chat extends ChatStatic implements HoverEventSource<Compon
|
|||||||
|
|
||||||
|
|
||||||
public static class FormatableChat extends Chat {
|
public static class FormatableChat extends Chat {
|
||||||
/* package */ FormatableChat(Component c) {
|
/* package */ FormatableChat(ComponentBuilder<?, ?> c) {
|
||||||
super(c);
|
super(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FormatableChat console(boolean c) { console = c; return this; }
|
public FormatableChat console(boolean c) { console = c; return this; }
|
||||||
|
|
||||||
public FormatableChat color(TextColor c) { component.color(c); return this; }
|
public FormatableChat color(TextColor c) { builder.color(c); return this; }
|
||||||
public FormatableChat color(ChatColor c) { return color(TextColor.color(c.getColor().getRGB())); }
|
public FormatableChat color(ChatColor c) { return color(TextColor.color(c.getColor().getRGB())); }
|
||||||
public FormatableChat color(Color c) { return color(TextColor.color(c.getRGB())); }
|
public FormatableChat color(Color c) { return color(TextColor.color(c.getRGB())); }
|
||||||
public FormatableChat color(String c) { return color(ChatColor.of(c)); }
|
public FormatableChat color(String c) { return color(ChatColor.of(c)); }
|
||||||
@ -246,15 +240,11 @@ public abstract class Chat extends ChatStatic implements HoverEventSource<Compon
|
|||||||
public FormatableChat dataColor() { return color(config.dataColor); }
|
public FormatableChat dataColor() { return color(config.dataColor); }
|
||||||
public FormatableChat decorationColor() { return color(config.decorationColor); }
|
public FormatableChat decorationColor() { return color(config.decorationColor); }
|
||||||
|
|
||||||
private FormatableChat setStyle(UnaryOperator<Style> styleOp) {
|
private FormatableChat setStyle(Consumer<Style.Builder> styleOp) { builder.style(styleOp); return this; }
|
||||||
component.style(styleOp.apply(component.style()));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
private FormatableChat setDecoration(TextDecoration deco, Boolean state) {
|
|
||||||
return setStyle(s -> s.decoration(deco, State.byBoolean(state)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public FormatableChat font(Key f) { return setStyle(s -> s.font(f)); }
|
private FormatableChat setDecoration(TextDecoration deco, Boolean state) {
|
||||||
|
return setStyle(b -> b.decoration(deco, State.byBoolean(state)));
|
||||||
|
}
|
||||||
|
|
||||||
public FormatableChat bold(Boolean b) { return setDecoration(TextDecoration.BOLD, b); }
|
public FormatableChat bold(Boolean b) { return setDecoration(TextDecoration.BOLD, b); }
|
||||||
public FormatableChat bold() { return bold(true); }
|
public FormatableChat bold() { return bold(true); }
|
||||||
@ -271,16 +261,18 @@ public abstract class Chat extends ChatStatic implements HoverEventSource<Compon
|
|||||||
public FormatableChat obfuscated(Boolean o) { return setDecoration(TextDecoration.OBFUSCATED, o); }
|
public FormatableChat obfuscated(Boolean o) { return setDecoration(TextDecoration.OBFUSCATED, o); }
|
||||||
public FormatableChat obfuscated() { return obfuscated(true); }
|
public FormatableChat obfuscated() { return obfuscated(true); }
|
||||||
|
|
||||||
public FormatableChat shiftClickInsertion(String i) { component.insertion(i); return this; }
|
public FormatableChat font(Key f) { return setStyle(s -> s.font(f)); }
|
||||||
|
|
||||||
private FormatableChat click(ClickEvent e) { component.clickEvent(e); return this; }
|
public FormatableChat shiftClickInsertion(String i) { builder.insertion(i); return this; }
|
||||||
|
|
||||||
|
private FormatableChat click(ClickEvent e) { builder.clickEvent(e); return this; }
|
||||||
public FormatableChat clickCommand(String cmdWithSlash) { return click(ClickEvent.runCommand(cmdWithSlash)); }
|
public FormatableChat clickCommand(String cmdWithSlash) { return click(ClickEvent.runCommand(cmdWithSlash)); }
|
||||||
public FormatableChat clickSuggest(String cmdWithSlash) { return click(ClickEvent.suggestCommand(cmdWithSlash)); }
|
public FormatableChat clickSuggest(String cmdWithSlash) { return click(ClickEvent.suggestCommand(cmdWithSlash)); }
|
||||||
public FormatableChat clickClipboard(String value) { return click(ClickEvent.copyToClipboard(value)); }
|
public FormatableChat clickClipboard(String value) { return click(ClickEvent.copyToClipboard(value)); }
|
||||||
public FormatableChat clickURL(String url) { return click(ClickEvent.openUrl(url)); }
|
public FormatableChat clickURL(String url) { return click(ClickEvent.openUrl(url)); }
|
||||||
public FormatableChat clickBookPage(int page) { return click(ClickEvent.changePage(page)); }
|
public FormatableChat clickBookPage(int page) { return click(ClickEvent.changePage(page)); }
|
||||||
|
|
||||||
public FormatableChat hover(HoverEventSource<?> e) { component.hoverEvent(e); return this; }
|
public FormatableChat hover(HoverEventSource<?> e) { builder.hoverEvent(e); return this; }
|
||||||
public FormatableChat hover(Chat v) { return hover(v.getAdv()); }
|
public FormatableChat hover(Chat v) { return hover(v.getAdv()); }
|
||||||
public FormatableChat hover(BaseComponent v) { return hover(toAdventure(v)); }
|
public FormatableChat hover(BaseComponent v) { return hover(toAdventure(v)); }
|
||||||
public FormatableChat hover(BaseComponent[] v) { return hover(toAdventure(v)); }
|
public FormatableChat hover(BaseComponent[] v) { return hover(toAdventure(v)); }
|
||||||
@ -334,6 +326,8 @@ public abstract class Chat extends ChatStatic implements HoverEventSource<Compon
|
|||||||
ret[i] = toAdventure((BaseComponent[]) v);
|
ret[i] = toAdventure((BaseComponent[]) v);
|
||||||
else if (v instanceof BaseComponent)
|
else if (v instanceof BaseComponent)
|
||||||
ret[i] = toAdventure((BaseComponent) v);
|
ret[i] = toAdventure((BaseComponent) v);
|
||||||
|
else if (v instanceof ComponentLike)
|
||||||
|
ret[i] = (ComponentLike) v;
|
||||||
else
|
else
|
||||||
ret[i] = Component.text(Objects.toString(v));
|
ret[i] = Component.text(Objects.toString(v));
|
||||||
}
|
}
|
||||||
@ -357,12 +351,61 @@ public abstract class Chat extends ChatStatic implements HoverEventSource<Compon
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static ComponentBuilder<?, ?> componentToBuilder(Component c) {
|
||||||
|
ComponentBuilder<?, ?> builder;
|
||||||
|
if (c instanceof TextComponent) {
|
||||||
|
builder = Component.text()
|
||||||
|
.content(((TextComponent) c).content());
|
||||||
|
}
|
||||||
|
else if (c instanceof TranslatableComponent) {
|
||||||
|
builder = Component.translatable()
|
||||||
|
.key(((TranslatableComponent) c).key())
|
||||||
|
.args(((TranslatableComponent) c).args());
|
||||||
|
}
|
||||||
|
else if (c instanceof SelectorComponent) {
|
||||||
|
builder = Component.selector()
|
||||||
|
.pattern(((SelectorComponent) c).pattern());
|
||||||
|
}
|
||||||
|
else if (c instanceof ScoreComponent) {
|
||||||
|
builder = Component.score()
|
||||||
|
.name(((ScoreComponent) c).name())
|
||||||
|
.objective(((ScoreComponent) c).objective());
|
||||||
|
}
|
||||||
|
else if (c instanceof KeybindComponent) {
|
||||||
|
builder = Component.keybind()
|
||||||
|
.keybind(((KeybindComponent) c).keybind());
|
||||||
|
}
|
||||||
|
else if (c instanceof BlockNBTComponent) {
|
||||||
|
builder = Component.blockNBT()
|
||||||
|
.interpret(((BlockNBTComponent) c).interpret())
|
||||||
|
.nbtPath(((BlockNBTComponent) c).nbtPath())
|
||||||
|
.pos(((BlockNBTComponent) c).pos());
|
||||||
|
}
|
||||||
|
else if (c instanceof EntityNBTComponent) {
|
||||||
|
builder = Component.entityNBT()
|
||||||
|
.interpret(((EntityNBTComponent) c).interpret())
|
||||||
|
.nbtPath(((EntityNBTComponent) c).nbtPath())
|
||||||
|
.selector(((EntityNBTComponent) c).selector());
|
||||||
|
}
|
||||||
|
else if (c instanceof StorageNBTComponent) {
|
||||||
|
builder = Component.storageNBT()
|
||||||
|
.interpret(((StorageNBTComponent) c).interpret())
|
||||||
|
.nbtPath(((StorageNBTComponent) c).nbtPath())
|
||||||
|
.storage(((StorageNBTComponent) c).storage());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new IllegalArgumentException("Unknows component type " + c.getClass());
|
||||||
|
}
|
||||||
|
return builder.style(c.style());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static Chat italicFalseIfNotSet(Chat c) {
|
public static Chat italicFalseIfNotSet(Chat c) {
|
||||||
if (c instanceof FormatableChat) {
|
c.builder.style(b -> {
|
||||||
if (c.component.style().decoration(TextDecoration.ITALIC) == State.NOT_SET)
|
if (b.build().decoration(TextDecoration.ITALIC) == State.NOT_SET) {
|
||||||
((FormatableChat) c).italic(false);
|
((FormatableChat) c).italic(false);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,11 +12,11 @@ public abstract class ChatStatic {
|
|||||||
|
|
||||||
|
|
||||||
public static FormatableChat chatComponent(Component c) {
|
public static FormatableChat chatComponent(Component c) {
|
||||||
return new FormatableChat(c);
|
return new FormatableChat(Chat.componentToBuilder(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FormatableChat chatComponent(BaseComponent c) {
|
public static FormatableChat chatComponent(BaseComponent c) {
|
||||||
return new FormatableChat(Chat.toAdventure(c));
|
return new FormatableChat(Chat.componentToBuilder(Chat.toAdventure(c)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FormatableChat chat() {
|
public static FormatableChat chat() {
|
||||||
|
@ -9,7 +9,6 @@ import net.kyori.adventure.identity.Identified;
|
|||||||
import net.kyori.adventure.identity.Identity;
|
import net.kyori.adventure.identity.Identity;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.ComponentLike;
|
import net.kyori.adventure.text.ComponentLike;
|
||||||
import net.md_5.bungee.api.chat.BaseComponent;
|
|
||||||
|
|
||||||
public interface IOnlinePlayer extends IOffPlayer {
|
public interface IOnlinePlayer extends IOffPlayer {
|
||||||
|
|
||||||
@ -112,14 +111,6 @@ public interface IOnlinePlayer extends IOffPlayer {
|
|||||||
* Sending packet and stuff to player
|
* Sending packet and stuff to player
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* Display the provided message in the player’s chat, if
|
|
||||||
* the chat is activated.
|
|
||||||
* @param message the message to display.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public abstract void sendMessage(BaseComponent message);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display the provided message in the player’s chat, if
|
* Display the provided message in the player’s chat, if
|
||||||
* the chat is activated.
|
* the chat is activated.
|
||||||
@ -145,19 +136,6 @@ public interface IOnlinePlayer extends IOffPlayer {
|
|||||||
sendMessage(message.getAdv());
|
sendMessage(message.getAdv());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Display the provided message in the player’s chat, if
|
|
||||||
* they allows to display CHAT messages
|
|
||||||
* @param message the message to display.
|
|
||||||
* @param sender the player causing the send of this message. Client side filtering may occur.
|
|
||||||
* May be null if we don’t want client filtering, but still consider the message as CHAT message.
|
|
||||||
* @implNote implementation of this method should not filter the send of the message, based on
|
|
||||||
* the sender. This parameter is only there to be transmitted to the client, so client side filtering can
|
|
||||||
* be processed.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public abstract void sendMessage(BaseComponent message, UUID sender);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display the provided message in the player’s chat, if
|
* Display the provided message in the player’s chat, if
|
||||||
* they allows to display CHAT messages
|
* they allows to display CHAT messages
|
||||||
@ -215,16 +193,6 @@ public interface IOnlinePlayer extends IOffPlayer {
|
|||||||
sendMessage(IPlayerManager.prefixedAndColored(message));
|
sendMessage(IPlayerManager.prefixedAndColored(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Display the provided message in the player’s chat, if the chat is
|
|
||||||
* activated, prepended with the server prefix.
|
|
||||||
* @param message the message to display
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public default void sendPrefixedMessage(BaseComponent message) {
|
|
||||||
sendMessage(IPlayerManager.prefixedAndColored(message));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display the provided message in the player’s chat, if the chat is
|
* Display the provided message in the player’s chat, if the chat is
|
||||||
* activated, prepended with the server prefix.
|
* activated, prepended with the server prefix.
|
||||||
@ -234,17 +202,6 @@ public interface IOnlinePlayer extends IOffPlayer {
|
|||||||
sendPrefixedMessage(message.getAdv());
|
sendPrefixedMessage(message.getAdv());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Display a title in the middle of the screen.
|
|
||||||
* @param title The big text
|
|
||||||
* @param subtitle The less big text
|
|
||||||
* @param fadeIn Fade in time in tick
|
|
||||||
* @param stay Stay time in tick
|
|
||||||
* @param fadeOut Fade out time in tick
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public abstract void sendTitle(BaseComponent title, BaseComponent subtitle, int fadeIn, int stay, int fadeOut);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display a title in the middle of the screen.
|
* Display a title in the middle of the screen.
|
||||||
* @param title The big text
|
* @param title The big text
|
||||||
|
Loading…
Reference in New Issue
Block a user