mirror of
https://github.com/DiscordSRV/Ascension.git
synced 2024-11-22 11:55:54 +01:00
Make MinecraftComponent immutable
This commit is contained in:
parent
295bc1c6bf
commit
6f8b5bd023
@ -5,6 +5,9 @@ dependencies {
|
|||||||
// Annotations
|
// Annotations
|
||||||
compileOnlyApi(libs.jetbrains.annotations)
|
compileOnlyApi(libs.jetbrains.annotations)
|
||||||
|
|
||||||
|
// Unrelocate
|
||||||
|
compileOnly(project(':common:common-unrelocate'))
|
||||||
|
|
||||||
// JDA
|
// JDA
|
||||||
api(libs.jda) {
|
api(libs.jda) {
|
||||||
// We don't use audio
|
// We don't use audio
|
||||||
|
@ -43,7 +43,7 @@ import java.util.function.Predicate;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The DiscordSRV API.
|
* The DiscordSRV API.
|
||||||
*
|
* <p>
|
||||||
* Use your platform's service provider or {@link #get()} / {@link #optional()} to get the instance.
|
* Use your platform's service provider or {@link #get()} / {@link #optional()} to get the instance.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused") // API
|
@SuppressWarnings("unused") // API
|
||||||
@ -51,12 +51,17 @@ public interface DiscordSRVApi {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the instance of {@link DiscordSRVApi}.
|
* Gets the instance of {@link DiscordSRVApi}.
|
||||||
* @return the DiscordSRV api, or {@code null} if not available
|
* @return the DiscordSRV api
|
||||||
* @see #isAvailable()
|
* @see #isAvailable()
|
||||||
|
* @throws IllegalStateException if DiscordSRV has not been initialized yet
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@NotNull
|
||||||
static DiscordSRVApi get() {
|
static DiscordSRVApi get() {
|
||||||
return InstanceHolder.API;
|
DiscordSRVApi api = InstanceHolder.API;
|
||||||
|
if (api == null) {
|
||||||
|
throw new IllegalStateException("DiscordSRV has not been initialized yet");
|
||||||
|
}
|
||||||
|
return api;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
package com.discordsrv.api.component;
|
package com.discordsrv.api.component;
|
||||||
|
|
||||||
import com.discordsrv.api.DiscordSRVApi;
|
import com.discordsrv.api.DiscordSRVApi;
|
||||||
|
import com.discordsrv.unrelocate.net.kyori.adventure.text.Component;
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@ -31,7 +32,7 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
/**
|
/**
|
||||||
* A Minecraft json text component. Use {@link DiscordSRVApi#componentFactory()} to get an instance.<br/>
|
* A Minecraft json text component. Use {@link DiscordSRVApi#componentFactory()} to get an instance.<br/>
|
||||||
* <br/>
|
* <br/>
|
||||||
* This is designed to work with Adventure, see {@link #adventureAdapter(Class, Class)} and {@link #adventureAdapter(MinecraftComponentAdapter)}
|
* This is designed to work with Adventure, see {@link #asAdventure(Class, Class)} and {@link #asAdventure(MinecraftComponentAdapter)}
|
||||||
* but is compatible with anything able to handle Minecraft's json format.
|
* but is compatible with anything able to handle Minecraft's json format.
|
||||||
* Legacy is <b>not supported</b>.
|
* Legacy is <b>not supported</b>.
|
||||||
*/
|
*/
|
||||||
@ -39,6 +40,34 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
@ApiStatus.NonExtendable
|
@ApiStatus.NonExtendable
|
||||||
public interface MinecraftComponent {
|
public interface MinecraftComponent {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link MinecraftComponent} from the provided JSON.
|
||||||
|
*
|
||||||
|
* @param json the json
|
||||||
|
* @return a new {@link MinecraftComponent}
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
static MinecraftComponent fromJson(@NotNull String json) {
|
||||||
|
return DiscordSRVApi.get()
|
||||||
|
.componentFactory()
|
||||||
|
.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link MinecraftComponent} from the given unrelocated Adventure Component.
|
||||||
|
*
|
||||||
|
* @param unrelocatedAdventureComponent the <b>unrelocated</b> adventure Component
|
||||||
|
* @return a new {@link MinecraftComponent}
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
static MinecraftComponent fromAdventure(@NotNull Component unrelocatedAdventureComponent) {
|
||||||
|
MinecraftComponentAdapter<Component> adapter = MinecraftComponentAdapter.unrelocated();
|
||||||
|
if (adapter == null) {
|
||||||
|
throw new IllegalStateException("Unrelocated Adventure GSON serializer not available");
|
||||||
|
}
|
||||||
|
return adapter.toDiscordSRV(unrelocatedAdventureComponent);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets this component as json.
|
* Gets this component as json.
|
||||||
* @return json of this component
|
* @return json of this component
|
||||||
@ -46,13 +75,6 @@ public interface MinecraftComponent {
|
|||||||
@NotNull
|
@NotNull
|
||||||
String asJson();
|
String asJson();
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets this component from json.
|
|
||||||
* @param json valid Minecraft message component json
|
|
||||||
* @throws IllegalArgumentException if the provided json is not valid
|
|
||||||
*/
|
|
||||||
void setJson(@NotNull String json);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets this message as a plain {@link String} losing any coloring, click and hover components it may have had.
|
* Gets this message as a plain {@link String} losing any coloring, click and hover components it may have had.
|
||||||
* Use for reference only, <b>this is not a substitute for legacy</b>.
|
* Use for reference only, <b>this is not a substitute for legacy</b>.
|
||||||
@ -62,72 +84,59 @@ public interface MinecraftComponent {
|
|||||||
String asPlainString();
|
String asPlainString();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an Adventure adapter for convenience.
|
* Converts this {@link MinecraftComponent} to an Adventure Component of the provided GSON serializer.
|
||||||
|
* Prefer using {@link #asAdventure(MinecraftComponentAdapter)}.
|
||||||
*
|
*
|
||||||
* @param gsonSerializerClass the gson serializer class
|
* @param gsonSerializerClass the gson serializer class
|
||||||
* @return an adapter that will convert to/from relocated or unrelocated adventure classes to/from json
|
* @return an adapter that will convert to/from relocated or unrelocated adventure classes to/from json
|
||||||
* @throws IllegalArgumentException if the provided class is not an Adventure GsonComponentSerializer
|
* @throws IllegalArgumentException if the provided class is not an Adventure GsonComponentSerializer
|
||||||
* @see #adventureAdapter(Class, Class)
|
* @see #asAdventure(Class, Class)
|
||||||
*/
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
default Adapter<Object> adventureAdapter(@NotNull Class<?> gsonSerializerClass) {
|
default Object asAdventure(@NotNull Class<?> gsonSerializerClass) {
|
||||||
return adventureAdapter(gsonSerializerClass, null);
|
return asAdventure(gsonSerializerClass, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an Adventure adapter for convenience.
|
* Converts this {@link MinecraftComponent} to an Adventure Component of the provided GSON serializer.
|
||||||
|
* Prefer using {@link #asAdventure(MinecraftComponentAdapter)}.
|
||||||
*
|
*
|
||||||
* @param gsonSerializerClass the {@code GsonComponentSerializer} class
|
* @param gsonSerializerClass the {@code GsonComponentSerializer} class
|
||||||
* @param componentClass the {@code Component} class that's returned by the given gson component serializer
|
* @param componentClass the {@code Component} class that's returned by the given gson component serializer
|
||||||
* @return an adapter that will convert to/from relocated or unrelocated adventure classes to/from json
|
* @return the component from the GSON serializers output
|
||||||
* @throws IllegalArgumentException if the provided class is not an Adventure {@code GsonComponentSerializer}
|
* @throws IllegalArgumentException if the provided class is not an Adventure {@code GsonComponentSerializer}
|
||||||
* or if the provided {@code Component} class isn't the one returned by the serializer
|
* or if the provided {@code Component} class isn't the one returned by the serializer
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
@NotNull
|
@NotNull
|
||||||
<T> Adapter<T> adventureAdapter(@NotNull Class<?> gsonSerializerClass, Class<T> componentClass);
|
default <T> T asAdventure(@NotNull Class<?> gsonSerializerClass, Class<T> componentClass) {
|
||||||
|
return (T) MinecraftComponentAdapter.create(gsonSerializerClass).toAdventure(this);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an Adventure adapter from a {@link MinecraftComponentAdapter} for convenience.
|
* Creates an Adventure adapter from a {@link MinecraftComponentAdapter} for convenience.
|
||||||
*
|
*
|
||||||
* @param adapter the pre-made {@link MinecraftComponentAdapter}
|
* @param adapter the pre-made {@link MinecraftComponentAdapter}
|
||||||
* @return a {@link Adapter} for this component using the given {@link MinecraftComponentAdapter}
|
* @return a new Adventure Component
|
||||||
*/
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
<T> Adapter<T> adventureAdapter(@NotNull MinecraftComponentAdapter<T> adapter);
|
default <T> T asAdventure(@NotNull MinecraftComponentAdapter<T> adapter) {
|
||||||
|
return adapter.toAdventure(this);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an Adventure adapter for the unrelocated adventure.
|
* Creates an Adventure adapter for the unrelocated adventure.
|
||||||
*
|
*
|
||||||
* @return a {@link Adapter} for this component using the unrelocated adventure, {@code null} if not available
|
* @return the <b>unrelocated</b> Adventure Component, {@code null} if not available
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
@ApiStatus.NonExtendable
|
@ApiStatus.NonExtendable
|
||||||
default Adapter<Object> unrelocatedAdapter() {
|
default Component asAdventure() {
|
||||||
MinecraftComponentAdapter<Object> adapter = MinecraftComponentAdapter.UNRELOCATED;
|
MinecraftComponentAdapter<Component> adapter = MinecraftComponentAdapter.unrelocated();
|
||||||
if (adapter == null) {
|
if (adapter == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return adventureAdapter(adapter);
|
return asAdventure(adapter);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An Adventure adapter, converts from/to given adventure components from/to json.
|
|
||||||
*/
|
|
||||||
interface Adapter<Component> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the Adventure Component returned by the gson serializer of this adapter.
|
|
||||||
* @return the {@code net.kyori.adventure.text.Component} (or relocated), cast this to your end class
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
Component getComponent();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the component to the component that can be serialized by the gson serializer for this class.
|
|
||||||
* @param adventureComponent the component
|
|
||||||
* @throws IllegalArgumentException if the provided component cannot be processed by the gson serializer of this adapter
|
|
||||||
*/
|
|
||||||
void setComponent(@NotNull Component adventureComponent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -23,97 +23,66 @@
|
|||||||
|
|
||||||
package com.discordsrv.api.component;
|
package com.discordsrv.api.component;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import com.discordsrv.api.DiscordSRVApi;
|
||||||
import java.lang.reflect.Method;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A persistent Adventure adapter for {@link MinecraftComponent}s, this is more efficient than using {@link MinecraftComponent#adventureAdapter(Class)}.
|
* A helper class to make {@link MinecraftComponent}s using Adventure.
|
||||||
* @see MinecraftComponent#adventureAdapter(MinecraftComponentAdapter)
|
* @param <Component> the Adventure Component type, relocated or unrelocated
|
||||||
*/
|
*/
|
||||||
public class MinecraftComponentAdapter<Component> {
|
public interface MinecraftComponentAdapter<Component> {
|
||||||
|
|
||||||
public static final MinecraftComponentAdapter<Object> UNRELOCATED;
|
|
||||||
|
|
||||||
static {
|
|
||||||
MinecraftComponentAdapter<Object> unrelocated = null;
|
|
||||||
try {
|
|
||||||
unrelocated = MinecraftComponentAdapter.create(
|
|
||||||
Class.forName("net.ky".concat("ori.adventure.text.serializer.gson.GsonComponentSerializer"))
|
|
||||||
);
|
|
||||||
} catch (ClassNotFoundException ignored) {}
|
|
||||||
UNRELOCATED = unrelocated;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link MinecraftComponentAdapter} that can be used with {@link MinecraftComponent}s.
|
* Create a new {@link MinecraftComponentAdapter} for the given GSONComponentSerializer class.
|
||||||
*
|
*
|
||||||
* @param gsonSerializerClass a GsonComponentSerializer class
|
* @param gsonSerializerClass the serializer class
|
||||||
* @return a new {@link MinecraftComponentAdapter} with the provided GsonComponentSerializer
|
* @return a new {@link MinecraftComponentAdapter}
|
||||||
* @throws IllegalArgumentException if the provided argument is not a GsonComponentSerialize class
|
* @param <Component> the type of Adventure Component the serializer handles
|
||||||
*/
|
*/
|
||||||
public static MinecraftComponentAdapter<Object> create(Class<?> gsonSerializerClass) {
|
@NotNull
|
||||||
return new MinecraftComponentAdapter<>(gsonSerializerClass, null);
|
static <Component> MinecraftComponentAdapter<Component> create(Class<?> gsonSerializerClass) {
|
||||||
|
return create(gsonSerializerClass, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link MinecraftComponentAdapter} that can be used with {@link MinecraftComponent}s.
|
* Create a new {@link MinecraftComponentAdapter} for the given GSONComponentSerializer class.
|
||||||
*
|
*
|
||||||
* @param gsonSerializerClass a GsonComponentSerializer class
|
* @param gsonSerializerClass the serializer class
|
||||||
* @param componentClass the Component class returned by the GsonComponentSerializer
|
* @param componentClass the {@code Component} class that's returned by the given gson component serializer
|
||||||
* @return a new {@link MinecraftComponentAdapter} with the provided GsonComponentSerializer
|
* @return a new {@link MinecraftComponentAdapter}
|
||||||
* @throws IllegalArgumentException if the provided argument is not a GsonComponentSerialize class
|
* @param <T> the type of Adventure Component the serializer returns
|
||||||
|
* @throws IllegalArgumentException if the provided componentClass does not match the gsonSerializerClasses Component
|
||||||
*/
|
*/
|
||||||
public static <Component> MinecraftComponentAdapter<Component> create(Class<?> gsonSerializerClass, Class<Component> componentClass) {
|
@NotNull
|
||||||
return new MinecraftComponentAdapter<>(gsonSerializerClass, componentClass);
|
static <T> MinecraftComponentAdapter<T> create(Class<?> gsonSerializerClass, Class<T> componentClass) {
|
||||||
|
return DiscordSRVApi.get()
|
||||||
|
.componentFactory()
|
||||||
|
.makeAdapter(gsonSerializerClass, componentClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Class<?> gsonSerializerClass;
|
/**
|
||||||
private final Object instance;
|
* Create a new {@link MinecraftComponentAdapter} for unrelocated Adventure.
|
||||||
private final Method deserialize;
|
*
|
||||||
private final Method serialize;
|
* @return the shared instance of {@link MinecraftComponentAdapter} unrelocated Adventure, or {@code null}
|
||||||
|
*/
|
||||||
private MinecraftComponentAdapter(Class<?> gsonSerializerClass, Class<Component> providedComponentClass) {
|
@SuppressWarnings("unchecked")
|
||||||
try {
|
@Nullable
|
||||||
this.gsonSerializerClass = gsonSerializerClass;
|
static MinecraftComponentAdapter<com.discordsrv.unrelocate.net.kyori.adventure.text.Component> unrelocated() {
|
||||||
this.instance = gsonSerializerClass.getDeclaredMethod("gson").invoke(null);
|
return (MinecraftComponentAdapter<com.discordsrv.unrelocate.net.kyori.adventure.text.Component>) (Object) MinecraftComponentAdapterUnrelocated.INSTANCE;
|
||||||
this.deserialize = gsonSerializerClass.getMethod("deserialize", Object.class);
|
|
||||||
Class<?> componentClass = deserialize.getReturnType();
|
|
||||||
checkComponentClass(providedComponentClass, componentClass);
|
|
||||||
this.serialize = gsonSerializerClass.getMethod("serialize", componentClass);
|
|
||||||
} catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
|
|
||||||
throw new IllegalArgumentException("The provided class is not a GsonComponentSerializer", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void checkComponentClass(Class<?> provided, Class<?> actual) {
|
/**
|
||||||
if (provided == null) {
|
* Converts a {@link MinecraftComponent} to an Adventure Component.
|
||||||
// Ignore null
|
* @param component the {@link MinecraftComponent}
|
||||||
return;
|
* @return a new Adventure Component
|
||||||
}
|
*/
|
||||||
|
Component toAdventure(MinecraftComponent component);
|
||||||
|
|
||||||
String providedName = provided.getName();
|
/**
|
||||||
String actualName = actual.getName();
|
* Converts an Adventure Component into a {@link MinecraftComponent}.
|
||||||
if (!providedName.equals(actualName)) {
|
* @param component the Adventure Component
|
||||||
throw new IllegalArgumentException(
|
* @return a new {@link MinecraftComponent}
|
||||||
"The provided Component class (" + providedName
|
*/
|
||||||
+ ") does not match the one returned by the serializer: " + actualName
|
MinecraftComponent toDiscordSRV(Component component);
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Class<?> serializerClass() {
|
|
||||||
return gsonSerializerClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object serializerInstance() {
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Method deserializeMethod() {
|
|
||||||
return deserialize;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Method serializeMethod() {
|
|
||||||
return serialize;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ package com.discordsrv.api.component;
|
|||||||
|
|
||||||
import com.discordsrv.api.DiscordSRVApi;
|
import com.discordsrv.api.DiscordSRVApi;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A factory for creating {@link MinecraftComponent}s.
|
* A factory for creating {@link MinecraftComponent}s.
|
||||||
@ -33,12 +34,21 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
public interface MinecraftComponentFactory {
|
public interface MinecraftComponentFactory {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an empty {@link MinecraftComponent}.
|
* Creates an {@link MinecraftComponent} from JSON.
|
||||||
*
|
*
|
||||||
|
* @param json the Minecraft component json
|
||||||
* @return a new {@link MinecraftComponent}
|
* @return a new {@link MinecraftComponent}
|
||||||
*/
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
MinecraftComponent empty();
|
MinecraftComponent fromJson(@NotNull String json);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an {@link MinecraftComponentAdapter} for the given GSONComponentSerializer class.
|
||||||
|
* @param gsonSerializerClass the serializer class
|
||||||
|
* @return a new {@link MinecraftComponentAdapter}
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
<T> MinecraftComponentAdapter<T> makeAdapter(Class<?> gsonSerializerClass, @Nullable Class<T> componentClass);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a EnhancedLegacyText {@link GameTextBuilder} based on the given input.
|
* Creates a EnhancedLegacyText {@link GameTextBuilder} based on the given input.
|
||||||
|
@ -355,9 +355,6 @@ public class SendableDiscordMessageImpl implements SendableDiscordMessage {
|
|||||||
@Override
|
@Override
|
||||||
public @NotNull Formatter applyPlaceholderService() {
|
public @NotNull Formatter applyPlaceholderService() {
|
||||||
DiscordSRVApi api = DiscordSRVApi.get();
|
DiscordSRVApi api = DiscordSRVApi.get();
|
||||||
if (api == null) {
|
|
||||||
throw new IllegalStateException("DiscordSRVApi not available");
|
|
||||||
}
|
|
||||||
this.replacements.put(
|
this.replacements.put(
|
||||||
PlaceholderService.PATTERN,
|
PlaceholderService.PATTERN,
|
||||||
wrapFunction(matcher -> api.placeholderService().getResultAsCharSequence(matcher, context))
|
wrapFunction(matcher -> api.placeholderService().getResultAsCharSequence(matcher, context))
|
||||||
@ -384,9 +381,6 @@ public class SendableDiscordMessageImpl implements SendableDiscordMessage {
|
|||||||
@Override
|
@Override
|
||||||
public @NotNull SendableDiscordMessage build() {
|
public @NotNull SendableDiscordMessage build() {
|
||||||
DiscordSRVApi api = DiscordSRVApi.get();
|
DiscordSRVApi api = DiscordSRVApi.get();
|
||||||
if (api == null) {
|
|
||||||
throw new IllegalStateException("DiscordSRVApi not available");
|
|
||||||
}
|
|
||||||
|
|
||||||
Function<String, String> placeholders = input -> {
|
Function<String, String> placeholders = input -> {
|
||||||
if (input == null) {
|
if (input == null) {
|
||||||
|
@ -67,9 +67,6 @@ public interface Module {
|
|||||||
@NotNull
|
@NotNull
|
||||||
default Collection<DiscordGatewayIntent> requiredIntents() {
|
default Collection<DiscordGatewayIntent> requiredIntents() {
|
||||||
DiscordSRVApi api = DiscordSRVApi.get();
|
DiscordSRVApi api = DiscordSRVApi.get();
|
||||||
if (api == null) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
Collection<? extends EventListener> listeners = api.eventBus().getListeners(this);
|
Collection<? extends EventListener> listeners = api.eventBus().getListeners(this);
|
||||||
EnumSet<DiscordGatewayIntent> intents = EnumSet.noneOf(DiscordGatewayIntent.class);
|
EnumSet<DiscordGatewayIntent> intents = EnumSet.noneOf(DiscordGatewayIntent.class);
|
||||||
|
@ -66,7 +66,7 @@ public class PaperComponentHandle<T> {
|
|||||||
unrelocated = handle.invoke(target);
|
unrelocated = handle.invoke(target);
|
||||||
} catch (Throwable ignored) {}
|
} catch (Throwable ignored) {}
|
||||||
if (unrelocated != null) {
|
if (unrelocated != null) {
|
||||||
return ComponentUtil.fromUnrelocated((com.discordsrv.unrelocate.net.kyori.adventure.text.Component) unrelocated);
|
return MinecraftComponent.fromAdventure((com.discordsrv.unrelocate.net.kyori.adventure.text.Component) unrelocated);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
package com.discordsrv.bukkit.console.executor;
|
package com.discordsrv.bukkit.console.executor;
|
||||||
|
|
||||||
import com.discordsrv.api.component.MinecraftComponent;
|
import com.discordsrv.api.component.MinecraftComponent;
|
||||||
import com.discordsrv.common.component.util.ComponentUtil;
|
|
||||||
import com.discordsrv.unrelocate.net.kyori.adventure.text.Component;
|
import com.discordsrv.unrelocate.net.kyori.adventure.text.Component;
|
||||||
import org.bukkit.Server;
|
import org.bukkit.Server;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
@ -43,7 +42,6 @@ public class PaperCommandFeedbackExecutor implements Consumer<Component> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accept(Component component) {
|
public void accept(Component component) {
|
||||||
MinecraftComponent minecraftComponent = ComponentUtil.fromUnrelocated(component);
|
componentConsumer.accept(MinecraftComponent.fromAdventure(component));
|
||||||
componentConsumer.accept(minecraftComponent);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@ public final class PaperPlayer {
|
|||||||
|
|
||||||
public static void kick(Player player, Component reason) {
|
public static void kick(Player player, Component reason) {
|
||||||
try {
|
try {
|
||||||
KICK_COMPONENT_HANDLE.invokeExact(player, ComponentUtil.toUnrelocated(ComponentUtil.toAPI(reason)));
|
KICK_COMPONENT_HANDLE.invokeExact(player, ComponentUtil.toAPI(reason).asAdventure());
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
throw new RuntimeException("Failed to kick player", e);
|
throw new RuntimeException("Failed to kick player", e);
|
||||||
}
|
}
|
||||||
|
@ -124,7 +124,7 @@ public class BukkitPlayer extends BukkitCommandSender implements IPlayer {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
PAPER_SEND_MESSAGE_HANDLE.invoke(player, ComponentUtil.toUnrelocated(component));
|
PAPER_SEND_MESSAGE_HANDLE.invoke(player, component.asAdventure());
|
||||||
} catch (Throwable ignored) {
|
} catch (Throwable ignored) {
|
||||||
super.sendMessage(ComponentUtil.fromAPI(component));
|
super.sendMessage(ComponentUtil.fromAPI(component));
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ package com.discordsrv.common.component;
|
|||||||
|
|
||||||
import com.discordsrv.api.component.GameTextBuilder;
|
import com.discordsrv.api.component.GameTextBuilder;
|
||||||
import com.discordsrv.api.component.MinecraftComponent;
|
import com.discordsrv.api.component.MinecraftComponent;
|
||||||
|
import com.discordsrv.api.component.MinecraftComponentAdapter;
|
||||||
import com.discordsrv.api.component.MinecraftComponentFactory;
|
import com.discordsrv.api.component.MinecraftComponentFactory;
|
||||||
import com.discordsrv.common.DiscordSRV;
|
import com.discordsrv.common.DiscordSRV;
|
||||||
import com.discordsrv.common.component.renderer.DiscordSRVMinecraftRenderer;
|
import com.discordsrv.common.component.renderer.DiscordSRVMinecraftRenderer;
|
||||||
@ -40,6 +41,7 @@ import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
|||||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||||
import net.kyori.ansi.ColorLevel;
|
import net.kyori.ansi.ColorLevel;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -129,8 +131,13 @@ public class ComponentFactory implements MinecraftComponentFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull MinecraftComponent empty() {
|
public @NotNull MinecraftComponent fromJson(@NotNull String json) {
|
||||||
return MinecraftComponentImpl.empty();
|
return new MinecraftComponentImpl(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> @NotNull MinecraftComponentAdapter<T> makeAdapter(Class<?> gsonSerializerClass, @Nullable Class<T> componentClass) {
|
||||||
|
return new MinecraftComponentAdapterImpl<>(gsonSerializerClass, componentClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||||
|
* Copyright (c) 2016-2024 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.discordsrv.common.component;
|
||||||
|
|
||||||
|
import com.discordsrv.api.component.MinecraftComponent;
|
||||||
|
import com.discordsrv.api.component.MinecraftComponentAdapter;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
public class MinecraftComponentAdapterImpl<T> implements MinecraftComponentAdapter<T> {
|
||||||
|
|
||||||
|
private final Class<?> gsonSerializerClass;
|
||||||
|
private final Object instance;
|
||||||
|
private final Method deserialize;
|
||||||
|
private final Method serialize;
|
||||||
|
|
||||||
|
public MinecraftComponentAdapterImpl(Class<?> gsonSerializerClass, Class<T> providedComponentClass) {
|
||||||
|
try {
|
||||||
|
this.gsonSerializerClass = gsonSerializerClass;
|
||||||
|
this.instance = gsonSerializerClass.getDeclaredMethod("gson").invoke(null);
|
||||||
|
this.deserialize = gsonSerializerClass.getMethod("deserialize", Object.class);
|
||||||
|
Class<?> componentClass = deserialize.getReturnType();
|
||||||
|
checkComponentClass(providedComponentClass, componentClass);
|
||||||
|
this.serialize = gsonSerializerClass.getMethod("serialize", componentClass);
|
||||||
|
} catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
|
||||||
|
throw new IllegalArgumentException("The provided class is not a GsonComponentSerializer", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void checkComponentClass(Class<?> provided, Class<?> actual) {
|
||||||
|
if (provided == null) {
|
||||||
|
// Ignore null
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String providedName = provided.getName();
|
||||||
|
String actualName = actual.getName();
|
||||||
|
if (!providedName.equals(actualName)) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"The provided Component class (" + providedName
|
||||||
|
+ ") does not match the one returned by the serializer: " + actualName
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private <R> R execute(Method method, Object input) {
|
||||||
|
try {
|
||||||
|
return (R) method.invoke(instance, input);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
throw new RuntimeException("Failed to invoke " + gsonSerializerClass.getName() + "." + method.getName(), e.getCause());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T toAdventure(MinecraftComponent component) {
|
||||||
|
String json = component.asJson();
|
||||||
|
return execute(deserialize, json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MinecraftComponent toDiscordSRV(T o) {
|
||||||
|
String json = execute(serialize, o);
|
||||||
|
return MinecraftComponent.fromJson(json);
|
||||||
|
}
|
||||||
|
}
|
@ -19,116 +19,38 @@
|
|||||||
package com.discordsrv.common.component;
|
package com.discordsrv.common.component;
|
||||||
|
|
||||||
import com.discordsrv.api.component.MinecraftComponent;
|
import com.discordsrv.api.component.MinecraftComponent;
|
||||||
import com.discordsrv.api.component.MinecraftComponentAdapter;
|
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
|
|
||||||
public class MinecraftComponentImpl implements MinecraftComponent {
|
public class MinecraftComponentImpl implements MinecraftComponent {
|
||||||
|
|
||||||
private String json;
|
private final String json;
|
||||||
private Component component;
|
private final Component component;
|
||||||
|
|
||||||
public static MinecraftComponentImpl empty() {
|
|
||||||
return new MinecraftComponentImpl("{text:\"\"}");
|
|
||||||
}
|
|
||||||
|
|
||||||
public MinecraftComponentImpl(String json) {
|
public MinecraftComponentImpl(String json) {
|
||||||
setJson(json);
|
this(GsonComponentSerializer.gson().deserialize(json));
|
||||||
}
|
}
|
||||||
|
|
||||||
public MinecraftComponentImpl(@NotNull Component component) {
|
public MinecraftComponentImpl(@NotNull Component component) {
|
||||||
setComponent(component);
|
this.component = component;
|
||||||
|
this.json = GsonComponentSerializer.gson().serialize(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Component getComponent() {
|
public Component getComponent() {
|
||||||
return component;
|
return component;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setComponent(@NotNull Component component) {
|
|
||||||
this.component = component;
|
|
||||||
this.json = GsonComponentSerializer.gson().serialize(component);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull String asJson() {
|
public @NotNull String asJson() {
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setJson(@NotNull String json) throws IllegalArgumentException {
|
|
||||||
Component component;
|
|
||||||
try {
|
|
||||||
component = GsonComponentSerializer.gson().deserialize(json);
|
|
||||||
} catch (Throwable t) {
|
|
||||||
throw new IllegalArgumentException("Provided json is not valid: " + json, t);
|
|
||||||
}
|
|
||||||
this.component = component;
|
|
||||||
this.json = json;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull String asPlainString() {
|
public @NotNull String asPlainString() {
|
||||||
return PlainTextComponentSerializer.plainText().serialize(component);
|
return PlainTextComponentSerializer.plainText().serialize(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> MinecraftComponent.@NotNull Adapter<T> adventureAdapter(
|
|
||||||
@NotNull Class<?> gsonSerializerClass, @NotNull Class<T> componentClass
|
|
||||||
) {
|
|
||||||
return new Adapter<>(gsonSerializerClass, componentClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> MinecraftComponent.@NotNull Adapter<T> adventureAdapter(@NotNull MinecraftComponentAdapter<T> adapter) {
|
|
||||||
return new Adapter<>(adapter);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public class Adapter<T> implements MinecraftComponent.Adapter<T> {
|
|
||||||
|
|
||||||
private final MinecraftComponentAdapter<T> adapter;
|
|
||||||
|
|
||||||
private Adapter(Class<?> gsonSerializerClass, Class<T> componentClass) {
|
|
||||||
this(MinecraftComponentAdapter.create(gsonSerializerClass, componentClass));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Adapter(MinecraftComponentAdapter<T> adapter) {
|
|
||||||
this.adapter = adapter;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull T getComponent() {
|
|
||||||
try {
|
|
||||||
return (T) adapter.deserializeMethod()
|
|
||||||
.invoke(
|
|
||||||
adapter.serializerInstance(),
|
|
||||||
json
|
|
||||||
);
|
|
||||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
|
||||||
throw new RuntimeException("Failed to convert to adventure component", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setComponent(@NotNull Object adventureComponent) {
|
|
||||||
try {
|
|
||||||
setJson(
|
|
||||||
(String) adapter.serializeMethod()
|
|
||||||
.invoke(
|
|
||||||
adapter.serializerInstance(),
|
|
||||||
adventureComponent
|
|
||||||
)
|
|
||||||
);
|
|
||||||
} catch (InvocationTargetException e) {
|
|
||||||
throw new IllegalArgumentException("The provided class is not a Component for the GsonComponentSerializer " + adapter.serializerClass().getName(), e);
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
throw new RuntimeException("Failed to convert from adventure component", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,30 +22,26 @@ import com.discordsrv.api.component.MinecraftComponent;
|
|||||||
import com.discordsrv.api.component.MinecraftComponentAdapter;
|
import com.discordsrv.api.component.MinecraftComponentAdapter;
|
||||||
import com.discordsrv.common.component.MinecraftComponentImpl;
|
import com.discordsrv.common.component.MinecraftComponentImpl;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.ComponentLike;
|
|
||||||
import net.kyori.adventure.text.TextComponent;
|
|
||||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||||
import org.jetbrains.annotations.Contract;
|
import org.jetbrains.annotations.Contract;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An util class for {@link Component}s and {@link MinecraftComponent}s.
|
* A util class for {@link Component}s and {@link MinecraftComponent}s.
|
||||||
*/
|
*/
|
||||||
public final class ComponentUtil {
|
public final class ComponentUtil {
|
||||||
|
|
||||||
|
private ComponentUtil() {}
|
||||||
|
|
||||||
private static MinecraftComponentAdapter<Component> ADAPTER;
|
private static MinecraftComponentAdapter<Component> ADAPTER;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static MinecraftComponentAdapter<Component> getAdapter() {
|
private static MinecraftComponentAdapter<Component> adapter() {
|
||||||
return ADAPTER != null ? ADAPTER : (ADAPTER = MinecraftComponentAdapter.create(GsonComponentSerializer.class, Component.class));
|
return ADAPTER != null ? ADAPTER : (ADAPTER = MinecraftComponentAdapter.create(GsonComponentSerializer.class, Component.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
private ComponentUtil() {}
|
|
||||||
|
|
||||||
public static boolean isEmpty(@NotNull Component component) {
|
public static boolean isEmpty(@NotNull Component component) {
|
||||||
return PlainTextComponentSerializer.plainText().serialize(component).isEmpty();
|
return PlainTextComponentSerializer.plainText().serialize(component).isEmpty();
|
||||||
}
|
}
|
||||||
@ -78,48 +74,7 @@ public final class ComponentUtil {
|
|||||||
if (component instanceof MinecraftComponentImpl) {
|
if (component instanceof MinecraftComponentImpl) {
|
||||||
return ((MinecraftComponentImpl) component).getComponent();
|
return ((MinecraftComponentImpl) component).getComponent();
|
||||||
} else {
|
} else {
|
||||||
return component.adventureAdapter(getAdapter()).getComponent();
|
return component.asAdventure(adapter());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void set(MinecraftComponent minecraftComponent, Component component) {
|
|
||||||
if (component instanceof MinecraftComponentImpl) {
|
|
||||||
((MinecraftComponentImpl) component).setComponent(component);
|
|
||||||
} else {
|
|
||||||
minecraftComponent.adventureAdapter(getAdapter()).setComponent(component);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static MinecraftComponent fromUnrelocated(@NotNull com.discordsrv.unrelocate.net.kyori.adventure.text.Component unrelocatedAdventure) {
|
|
||||||
MinecraftComponentImpl component = MinecraftComponentImpl.empty();
|
|
||||||
MinecraftComponent.Adapter<Object> adapter = component.unrelocatedAdapter();
|
|
||||||
if (adapter == null) {
|
|
||||||
throw new IllegalStateException("Could not get unrelocated adventure gson serializer");
|
|
||||||
}
|
|
||||||
adapter.setComponent(unrelocatedAdventure);
|
|
||||||
return component;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static com.discordsrv.unrelocate.net.kyori.adventure.text.Component toUnrelocated(MinecraftComponent component) {
|
|
||||||
MinecraftComponent.Adapter<Object> adapter = component.unrelocatedAdapter();
|
|
||||||
if (adapter == null) {
|
|
||||||
throw new IllegalStateException("Could not get unrelocated adventure gson serializer");
|
|
||||||
}
|
|
||||||
return (com.discordsrv.unrelocate.net.kyori.adventure.text.Component) adapter.getComponent();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Component join(@NotNull Component delimiter, @NotNull Collection<? extends ComponentLike> components) {
|
|
||||||
return join(delimiter, components.toArray(new ComponentLike[0]));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Component join(@NotNull Component delimiter, @NotNull ComponentLike[] components) {
|
|
||||||
TextComponent.Builder builder = Component.text();
|
|
||||||
for (int i = 0; i < components.length; i++) {
|
|
||||||
builder.append(components[i]);
|
|
||||||
if (i < components.length - 1) {
|
|
||||||
builder.append(delimiter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -37,11 +37,7 @@ public class MinecraftMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public GameTextBuilder textBuilder() {
|
public GameTextBuilder textBuilder() {
|
||||||
DiscordSRVApi discordSRV = DiscordSRVApi.get();
|
return DiscordSRVApi.get().componentFactory().textBuilder(rawFormat);
|
||||||
if (discordSRV == null) {
|
|
||||||
throw new IllegalStateException("DiscordSRVApi == null");
|
|
||||||
}
|
|
||||||
return discordSRV.componentFactory().textBuilder(rawFormat);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public MinecraftComponent make() {
|
public MinecraftComponent make() {
|
||||||
|
@ -27,10 +27,10 @@ import com.discordsrv.api.placeholder.annotation.Placeholder;
|
|||||||
import com.discordsrv.api.placeholder.annotation.PlaceholderPrefix;
|
import com.discordsrv.api.placeholder.annotation.PlaceholderPrefix;
|
||||||
import com.discordsrv.api.placeholder.annotation.PlaceholderRemainder;
|
import com.discordsrv.api.placeholder.annotation.PlaceholderRemainder;
|
||||||
import com.discordsrv.common.DiscordSRV;
|
import com.discordsrv.common.DiscordSRV;
|
||||||
import com.discordsrv.common.component.util.ComponentUtil;
|
|
||||||
import net.dv8tion.jda.api.entities.Member;
|
import net.dv8tion.jda.api.entities.Member;
|
||||||
import net.dv8tion.jda.api.entities.Role;
|
import net.dv8tion.jda.api.entities.Role;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.JoinConfiguration;
|
||||||
import net.kyori.adventure.text.format.TextColor;
|
import net.kyori.adventure.text.format.TextColor;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@ -159,7 +159,7 @@ public class DiscordGuildMemberImpl implements DiscordGuildMember {
|
|||||||
components.add(Component.text(role.getName()).color(TextColor.color(role.getColor().rgb())));
|
components.add(Component.text(role.getName()).color(TextColor.color(role.getColor().rgb())));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ComponentUtil.join(Component.text(suffix), components);
|
return Component.join(JoinConfiguration.separator(Component.text(suffix)), components);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -42,6 +42,7 @@ import net.dv8tion.jda.api.entities.MessageEmbed;
|
|||||||
import net.dv8tion.jda.api.entities.WebhookClient;
|
import net.dv8tion.jda.api.entities.WebhookClient;
|
||||||
import net.dv8tion.jda.api.requests.ErrorResponse;
|
import net.dv8tion.jda.api.requests.ErrorResponse;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.JoinConfiguration;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.annotations.Unmodifiable;
|
import org.jetbrains.annotations.Unmodifiable;
|
||||||
@ -307,7 +308,7 @@ public class ReceivedDiscordMessageImpl implements ReceivedDiscordMessage {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ComponentUtil.join(Component.text(suffix), components);
|
return Component.join(JoinConfiguration.separator(Component.text(suffix)), components);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
Reference in New Issue
Block a user