mirror of
https://github.com/DiscordSRV/Ascension.git
synced 2025-02-06 00:01:46 +01:00
Make use of MethodHandles for paper component getting
This commit is contained in:
parent
2b5c8b9d2f
commit
888f376846
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||
* Copyright (c) 2016-2022 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.bukkit.component;
|
||||
|
||||
import com.discordsrv.api.component.MinecraftComponent;
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import com.discordsrv.common.component.ComponentFactory;
|
||||
import com.discordsrv.common.component.util.ComponentUtil;
|
||||
import net.kyori.adventure.platform.bukkit.BukkitComponentSerializer;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class PaperComponentHandle<T> {
|
||||
|
||||
public static final boolean IS_PAPER_ADVENTURE;
|
||||
private static final MethodHandles.Lookup LOOKUP;
|
||||
|
||||
static {
|
||||
boolean isPaperAdventure = false;
|
||||
try {
|
||||
Class.forName("io.papermc.paper.event.player.AsyncChatEvent");
|
||||
isPaperAdventure = true;
|
||||
} catch (ClassNotFoundException ignored) {}
|
||||
IS_PAPER_ADVENTURE = isPaperAdventure;
|
||||
LOOKUP = IS_PAPER_ADVENTURE ? MethodHandles.lookup() : null;
|
||||
}
|
||||
|
||||
private final MethodHandle handle;
|
||||
private final Function<T, String> legacy;
|
||||
|
||||
public PaperComponentHandle(Class<T> targetClass, String methodName, Function<T, String> legacy) {
|
||||
this.legacy = legacy;
|
||||
|
||||
MethodHandle handle = null;
|
||||
if (IS_PAPER_ADVENTURE) {
|
||||
try {
|
||||
MethodType methodType = MethodType.methodType(ComponentFactory.UNRELOCATED_ADVENTURE_COMPONENT);
|
||||
handle = LOOKUP.findVirtual(targetClass, methodName, methodType);
|
||||
} catch (Throwable ignored) {}
|
||||
}
|
||||
this.handle = handle;
|
||||
}
|
||||
|
||||
public MinecraftComponent getComponent(DiscordSRV discordSRV, T target) {
|
||||
if (handle != null) {
|
||||
Object unrelocated = null;
|
||||
try {
|
||||
unrelocated = handle.invoke(target);
|
||||
} catch (Throwable ignored) {}
|
||||
if (unrelocated != null) {
|
||||
MinecraftComponent component = discordSRV.componentFactory().empty();
|
||||
component.unrelocatedAdapter()
|
||||
.orElseThrow(() -> new IllegalStateException("Unrelocated adventure unavailable"))
|
||||
.setComponent(unrelocated);
|
||||
return component;
|
||||
}
|
||||
}
|
||||
|
||||
String legacyOutput = legacy.apply(target);
|
||||
return legacyOutput != null
|
||||
? ComponentUtil.toAPI(BukkitComponentSerializer.legacy().deserialize(legacyOutput))
|
||||
: null;
|
||||
}
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
/*
|
||||
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||
* Copyright (c) 2016-2022 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.bukkit.component.util;
|
||||
|
||||
import com.discordsrv.api.component.MinecraftComponent;
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import com.discordsrv.common.component.util.ComponentUtil;
|
||||
import net.kyori.adventure.platform.bukkit.BukkitComponentSerializer;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.function.Function;
|
||||
|
||||
public final class PaperComponentUtil {
|
||||
|
||||
public static final boolean IS_PAPER_ADVENTURE;
|
||||
|
||||
static {
|
||||
boolean isPaperAdventure = false;
|
||||
try {
|
||||
Class.forName("io.papermc.paper.event.player.AsyncChatEvent");
|
||||
isPaperAdventure = true;
|
||||
} catch (ClassNotFoundException ignored) {}
|
||||
IS_PAPER_ADVENTURE = isPaperAdventure;
|
||||
}
|
||||
|
||||
private PaperComponentUtil() {}
|
||||
|
||||
public static <T> MinecraftComponent getComponent(
|
||||
DiscordSRV discordSRV, T source, String methodName, Function<T, String> legacy) {
|
||||
if (!IS_PAPER_ADVENTURE) {
|
||||
return getLegacy(legacy.apply(source));
|
||||
}
|
||||
|
||||
return getComponent(discordSRV, source, methodName);
|
||||
}
|
||||
|
||||
private static MinecraftComponent getLegacy(String legacy) {
|
||||
return ComponentUtil.toAPI(BukkitComponentSerializer.legacy().deserialize(legacy));
|
||||
}
|
||||
|
||||
public static MinecraftComponent getComponent(DiscordSRV discordSRV, Object source, String methodName) {
|
||||
if (!IS_PAPER_ADVENTURE) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Class<?> eventClass = source.getClass();
|
||||
Object unrelocated;
|
||||
try {
|
||||
Method method = eventClass.getMethod(methodName);
|
||||
unrelocated = method.invoke(source);
|
||||
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||
throw new IllegalStateException("Failed to invoke method reflectively", e);
|
||||
}
|
||||
|
||||
MinecraftComponent component = discordSRV.componentFactory().empty();
|
||||
component.unrelocatedAdapter()
|
||||
.orElseThrow(() -> new IllegalStateException("Unrelocated adventure unavailable"))
|
||||
.setComponent(unrelocated);
|
||||
|
||||
return component;
|
||||
}
|
||||
}
|
@ -21,7 +21,7 @@ package com.discordsrv.bukkit.listener;
|
||||
import com.discordsrv.api.component.MinecraftComponent;
|
||||
import com.discordsrv.api.event.events.message.receive.game.GameChatMessageReceiveEvent;
|
||||
import com.discordsrv.bukkit.BukkitDiscordSRV;
|
||||
import com.discordsrv.bukkit.component.util.PaperComponentUtil;
|
||||
import com.discordsrv.bukkit.component.PaperComponentHandle;
|
||||
import com.discordsrv.common.channel.DefaultGlobalChannel;
|
||||
import com.discordsrv.common.component.util.ComponentUtil;
|
||||
import io.papermc.paper.event.player.AsyncChatEvent;
|
||||
@ -36,7 +36,7 @@ public abstract class BukkitChatListener implements Listener {
|
||||
public static BukkitChatListener get(BukkitDiscordSRV discordSRV) {
|
||||
// TODO: config option
|
||||
//noinspection ConstantConditions,PointlessBooleanExpression
|
||||
if (1 == 2 && PaperComponentUtil.IS_PAPER_ADVENTURE) {
|
||||
if (1 == 2 && PaperComponentHandle.IS_PAPER_ADVENTURE) {
|
||||
return new Paper(discordSRV);
|
||||
}
|
||||
|
||||
@ -78,13 +78,20 @@ public abstract class BukkitChatListener implements Listener {
|
||||
|
||||
static class Paper extends BukkitChatListener {
|
||||
|
||||
private final PaperComponentHandle<AsyncChatEvent> componentHandle;
|
||||
|
||||
public Paper(BukkitDiscordSRV discordSRV) {
|
||||
super(discordSRV);
|
||||
this.componentHandle = new PaperComponentHandle<>(
|
||||
AsyncChatEvent.class,
|
||||
"message",
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onAsyncChat(AsyncChatEvent event) {
|
||||
MinecraftComponent component = PaperComponentUtil.getComponent(discordSRV, event, "message");
|
||||
MinecraftComponent component = componentHandle.getComponent(discordSRV, event);
|
||||
publishEvent(event.getPlayer(), component, event.isCancelled());
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ import com.discordsrv.api.component.MinecraftComponent;
|
||||
import com.discordsrv.api.event.events.message.receive.game.DeathMessageReceiveEvent;
|
||||
import com.discordsrv.api.player.DiscordSRVPlayer;
|
||||
import com.discordsrv.bukkit.BukkitDiscordSRV;
|
||||
import com.discordsrv.bukkit.component.util.PaperComponentUtil;
|
||||
import com.discordsrv.bukkit.component.PaperComponentHandle;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
@ -31,16 +31,22 @@ import org.bukkit.event.entity.PlayerDeathEvent;
|
||||
public class BukkitDeathListener implements Listener {
|
||||
|
||||
private final BukkitDiscordSRV discordSRV;
|
||||
|
||||
public BukkitDeathListener(BukkitDiscordSRV discordSRV) {
|
||||
this.discordSRV = discordSRV;
|
||||
}
|
||||
private final PaperComponentHandle<PlayerDeathEvent> componentHandle;
|
||||
|
||||
@SuppressWarnings("deprecation") // Paper
|
||||
public BukkitDeathListener(BukkitDiscordSRV discordSRV) {
|
||||
this.discordSRV = discordSRV;
|
||||
this.componentHandle = new PaperComponentHandle<>(
|
||||
PlayerDeathEvent.class,
|
||||
"deathMessage",
|
||||
PlayerDeathEvent::getDeathMessage
|
||||
);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPlayerDeath(PlayerDeathEvent event) {
|
||||
DiscordSRVPlayer player = discordSRV.playerProvider().player(event.getEntity());
|
||||
MinecraftComponent component = PaperComponentUtil.getComponent(discordSRV, event, "deathMessage", PlayerDeathEvent::getDeathMessage);
|
||||
MinecraftComponent component = componentHandle.getComponent(discordSRV, event);
|
||||
|
||||
discordSRV.scheduler().run(() -> discordSRV.eventBus().publish(
|
||||
new DeathMessageReceiveEvent(player, null, component, event.isCancelled())));
|
||||
|
@ -23,7 +23,7 @@ import com.discordsrv.api.event.events.message.receive.game.JoinMessageReceiveEv
|
||||
import com.discordsrv.api.event.events.message.receive.game.LeaveMessageReceiveEvent;
|
||||
import com.discordsrv.api.player.DiscordSRVPlayer;
|
||||
import com.discordsrv.bukkit.BukkitDiscordSRV;
|
||||
import com.discordsrv.bukkit.component.util.PaperComponentUtil;
|
||||
import com.discordsrv.bukkit.component.PaperComponentHandle;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
@ -33,17 +33,28 @@ import org.bukkit.event.player.PlayerQuitEvent;
|
||||
public class BukkitStatusMessageListener implements Listener {
|
||||
|
||||
private final BukkitDiscordSRV discordSRV;
|
||||
|
||||
public BukkitStatusMessageListener(BukkitDiscordSRV discordSRV) {
|
||||
this.discordSRV = discordSRV;
|
||||
}
|
||||
private final PaperComponentHandle<PlayerJoinEvent> joinHandle;
|
||||
private final PaperComponentHandle<PlayerQuitEvent> quitHandle;
|
||||
|
||||
@SuppressWarnings("deprecation") // Paper
|
||||
public BukkitStatusMessageListener(BukkitDiscordSRV discordSRV) {
|
||||
this.discordSRV = discordSRV;
|
||||
this.joinHandle = new PaperComponentHandle<>(
|
||||
PlayerJoinEvent.class,
|
||||
"joinMessage",
|
||||
PlayerJoinEvent::getJoinMessage
|
||||
);
|
||||
this.quitHandle = new PaperComponentHandle<>(
|
||||
PlayerQuitEvent.class,
|
||||
"quitMessage",
|
||||
PlayerQuitEvent::getQuitMessage
|
||||
);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
DiscordSRVPlayer player = discordSRV.playerProvider().player(event.getPlayer());
|
||||
MinecraftComponent component = PaperComponentUtil.getComponent(
|
||||
discordSRV, event, "joinMessage", PlayerJoinEvent::getJoinMessage);
|
||||
MinecraftComponent component = joinHandle.getComponent(discordSRV, event);
|
||||
boolean firstJoin = !event.getPlayer().hasPlayedBefore();
|
||||
|
||||
discordSRV.scheduler().run(() -> discordSRV.eventBus().publish(
|
||||
@ -51,12 +62,10 @@ public class BukkitStatusMessageListener implements Listener {
|
||||
));
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation") // Paper
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||
DiscordSRVPlayer player = discordSRV.playerProvider().player(event.getPlayer());
|
||||
MinecraftComponent component = PaperComponentUtil.getComponent(
|
||||
discordSRV, event, "quitMessage", PlayerQuitEvent::getQuitMessage);
|
||||
MinecraftComponent component = quitHandle.getComponent(discordSRV, event);
|
||||
|
||||
discordSRV.scheduler().run(() -> discordSRV.eventBus().publish(
|
||||
new LeaveMessageReceiveEvent(player, null, component, false)
|
||||
|
@ -20,7 +20,7 @@ package com.discordsrv.bukkit.player;
|
||||
|
||||
import com.discordsrv.bukkit.BukkitDiscordSRV;
|
||||
import com.discordsrv.bukkit.command.game.sender.BukkitCommandSender;
|
||||
import com.discordsrv.bukkit.component.util.PaperComponentUtil;
|
||||
import com.discordsrv.bukkit.component.PaperComponentHandle;
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import com.discordsrv.common.component.util.ComponentUtil;
|
||||
import com.discordsrv.common.player.IPlayer;
|
||||
@ -31,6 +31,17 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class BukkitPlayer extends BukkitCommandSender implements IPlayer {
|
||||
|
||||
private static final PaperComponentHandle<Player> DISPLAY_NAME_HANDLE = makeDisplayNameHandle();
|
||||
|
||||
@SuppressWarnings("deprecation") // Paper
|
||||
private static PaperComponentHandle<Player> makeDisplayNameHandle() {
|
||||
return new PaperComponentHandle<>(
|
||||
Player.class,
|
||||
"displayName",
|
||||
Player::getDisplayName
|
||||
);
|
||||
}
|
||||
|
||||
private final Player player;
|
||||
private final Identity identity;
|
||||
|
||||
@ -50,12 +61,9 @@ public class BukkitPlayer extends BukkitCommandSender implements IPlayer {
|
||||
return player.getName();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation") // Paper
|
||||
@Override
|
||||
public @NotNull Component displayName() {
|
||||
return ComponentUtil.fromAPI(
|
||||
PaperComponentUtil.getComponent(discordSRV, player, "displayName", Player::getDisplayName)
|
||||
);
|
||||
return ComponentUtil.fromAPI(DISPLAY_NAME_HANDLE.getComponent(discordSRV, player));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -35,6 +35,16 @@ import java.util.Locale;
|
||||
|
||||
public class ComponentFactory implements MinecraftComponentFactory {
|
||||
|
||||
public static final Class<?> UNRELOCATED_ADVENTURE_COMPONENT;
|
||||
|
||||
static {
|
||||
Class<?> clazz = null;
|
||||
try {
|
||||
clazz = Class.forName("net.kyo".concat("ri.adventure.text.Component"));
|
||||
} catch (ClassNotFoundException ignored) {}
|
||||
UNRELOCATED_ADVENTURE_COMPONENT = clazz;
|
||||
}
|
||||
|
||||
private final DiscordSRV discordSRV;
|
||||
private final MinecraftSerializer minecraftSerializer;
|
||||
private final DiscordSerializer discordSerializer;
|
||||
|
Loading…
Reference in New Issue
Block a user