port: compat layer
- add compat/Adventure (BukkitAudiences lifecycle with legacy fallback) - add compat/Msg (send/broadcast/actionBar/title/legacy/plain/displayName/playerListName/kick/itemMeta/inventoryTitle) - wire Adventure.init/close in LoChat onEnable/onDisable - remove unused reflection-based utils/platform/AdventureManager
This commit is contained in:
parent
dd725ad255
commit
88e4e68cca
4 changed files with 227 additions and 96 deletions
|
|
@ -47,7 +47,8 @@ public final class LoChat extends JavaPlugin {
|
|||
@Override
|
||||
public void onEnable() {
|
||||
instance = this;
|
||||
getLogger().info("Загрузка LoChat v" + getPluginMeta().getVersion() + " для Paper/Folia " + Bukkit.getMinecraftVersion() + "...");
|
||||
com.loki.lochat.compat.Adventure.init(this);
|
||||
getLogger().info("Загрузка LoChat v" + getDescription().getVersion() + " для Spigot " + Bukkit.getBukkitVersion() + "...");
|
||||
|
||||
// Инициализация
|
||||
initializer = new PluginInitializer(this);
|
||||
|
|
@ -95,6 +96,7 @@ public final class LoChat extends JavaPlugin {
|
|||
@Override
|
||||
public void onDisable() {
|
||||
shutdown.shutdown(serviceRegistry, autoMessageManager, discordIntegration, gradientModule);
|
||||
com.loki.lochat.compat.Adventure.close();
|
||||
}
|
||||
|
||||
public void reload() {
|
||||
|
|
|
|||
50
src/main/java/com/loki/lochat/compat/Adventure.java
Normal file
50
src/main/java/com/loki/lochat/compat/Adventure.java
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
package com.loki.lochat.compat;
|
||||
|
||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Holds BukkitAudiences for Spigot. Falls back to legacy text if creation fails.
|
||||
*/
|
||||
public final class Adventure {
|
||||
|
||||
private static BukkitAudiences audiences;
|
||||
private static boolean fallback;
|
||||
|
||||
private Adventure() {
|
||||
}
|
||||
|
||||
public static void init(Plugin plugin) {
|
||||
try {
|
||||
audiences = BukkitAudiences.create(plugin);
|
||||
fallback = false;
|
||||
} catch (Throwable t) {
|
||||
audiences = null;
|
||||
fallback = true;
|
||||
plugin.getLogger().warning(
|
||||
"[LoChat] BukkitAudiences init failed, falling back to legacy text: " + t.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public static void close() {
|
||||
if (audiences != null) {
|
||||
try {
|
||||
audiences.close();
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
audiences = null;
|
||||
}
|
||||
fallback = false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static BukkitAudiences audiences() {
|
||||
return audiences;
|
||||
}
|
||||
|
||||
public static boolean isFallback() {
|
||||
return fallback || audiences == null;
|
||||
}
|
||||
}
|
||||
174
src/main/java/com/loki/lochat/compat/Msg.java
Normal file
174
src/main/java/com/loki/lochat/compat/Msg.java
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
package com.loki.lochat.compat;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||
import net.kyori.adventure.title.Title;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Static helpers for sending Adventure components on Spigot via BukkitAudiences.
|
||||
* Falls back to legacy String when audiences not available.
|
||||
*/
|
||||
public final class Msg {
|
||||
|
||||
private static final LegacyComponentSerializer LEGACY = LegacyComponentSerializer.builder()
|
||||
.character('§')
|
||||
.hexColors()
|
||||
.useUnusualXRepeatedCharacterHexFormat()
|
||||
.build();
|
||||
|
||||
private static final PlainTextComponentSerializer PLAIN = PlainTextComponentSerializer.plainText();
|
||||
|
||||
private Msg() {
|
||||
}
|
||||
|
||||
public static void send(CommandSender sender, Component component) {
|
||||
if (sender == null || component == null) {
|
||||
return;
|
||||
}
|
||||
if (!Adventure.isFallback() && Adventure.audiences() != null) {
|
||||
try {
|
||||
Adventure.audiences().sender(sender).sendMessage(component);
|
||||
return;
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
}
|
||||
sender.sendMessage(legacy(component));
|
||||
}
|
||||
|
||||
public static void send(Collection<? extends CommandSender> senders, Component component) {
|
||||
if (senders == null || component == null) {
|
||||
return;
|
||||
}
|
||||
for (CommandSender s : senders) {
|
||||
send(s, component);
|
||||
}
|
||||
}
|
||||
|
||||
public static void broadcast(Component component) {
|
||||
if (component == null) {
|
||||
return;
|
||||
}
|
||||
if (!Adventure.isFallback() && Adventure.audiences() != null) {
|
||||
try {
|
||||
Adventure.audiences().all().sendMessage(component);
|
||||
return;
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
}
|
||||
String legacy = legacy(component);
|
||||
Bukkit.getOnlinePlayers().forEach(p -> p.sendMessage(legacy));
|
||||
Bukkit.getConsoleSender().sendMessage(legacy);
|
||||
}
|
||||
|
||||
public static void actionBar(Player player, Component component) {
|
||||
if (player == null || component == null) {
|
||||
return;
|
||||
}
|
||||
if (!Adventure.isFallback() && Adventure.audiences() != null) {
|
||||
try {
|
||||
Adventure.audiences().player(player).sendActionBar(component);
|
||||
return;
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
}
|
||||
// Fallback: send as chat
|
||||
player.sendMessage(legacy(component));
|
||||
}
|
||||
|
||||
public static void title(Player player, Component title, Component subtitle, Title.Times times) {
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
Component t = title != null ? title : Component.empty();
|
||||
Component s = subtitle != null ? subtitle : Component.empty();
|
||||
Title.Times tm = times != null ? times : Title.Times.times(
|
||||
Duration.ofMillis(500), Duration.ofMillis(3000), Duration.ofMillis(500));
|
||||
if (!Adventure.isFallback() && Adventure.audiences() != null) {
|
||||
try {
|
||||
Adventure.audiences().player(player).showTitle(Title.title(t, s, tm));
|
||||
return;
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
}
|
||||
// Fallback via Bukkit API (legacy strings, 1.20.1 supports titles)
|
||||
player.sendTitle(legacy(t), legacy(s),
|
||||
(int) (tm.fadeIn().toMillis() / 50),
|
||||
(int) (tm.stay().toMillis() / 50),
|
||||
(int) (tm.fadeOut().toMillis() / 50));
|
||||
}
|
||||
|
||||
public static String legacy(Component component) {
|
||||
if (component == null) {
|
||||
return "";
|
||||
}
|
||||
return LEGACY.serialize(component);
|
||||
}
|
||||
|
||||
public static String plain(Component component) {
|
||||
if (component == null) {
|
||||
return "";
|
||||
}
|
||||
return PLAIN.serialize(component);
|
||||
}
|
||||
|
||||
public static void setDisplayName(Player player, Component component) {
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
player.setDisplayName(component == null ? "" : legacy(component));
|
||||
}
|
||||
|
||||
public static void setPlayerListName(Player player, Component component) {
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
player.setPlayerListName(component == null ? "" : legacy(component));
|
||||
}
|
||||
|
||||
public static void kick(Player player, Component reason) {
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
String msg = reason == null ? "" : legacy(reason);
|
||||
// Must be on main thread; caller should ensure via scheduler if needed
|
||||
if (Bukkit.isPrimaryThread()) {
|
||||
player.kickPlayer(msg);
|
||||
} else {
|
||||
Bukkit.getScheduler().runTask(
|
||||
Bukkit.getPluginManager().getPlugin("LoChat"), () -> player.kickPlayer(msg));
|
||||
}
|
||||
}
|
||||
|
||||
public static void itemName(ItemMeta meta, Component name) {
|
||||
if (meta == null) {
|
||||
return;
|
||||
}
|
||||
meta.setDisplayName(name == null ? null : legacy(name));
|
||||
}
|
||||
|
||||
public static void itemLore(ItemMeta meta, List<Component> lore) {
|
||||
if (meta == null) {
|
||||
return;
|
||||
}
|
||||
if (lore == null) {
|
||||
meta.setLore(null);
|
||||
return;
|
||||
}
|
||||
List<String> lines = lore.stream().map(Msg::legacy).toList();
|
||||
meta.setLore(lines);
|
||||
}
|
||||
|
||||
public static String inventoryTitle(Component title) {
|
||||
return legacy(title);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
package com.loki.lochat.utils.platform;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* Менеджер для работы с Adventure API на Arclight/Forge серверах
|
||||
*/
|
||||
public class AdventureManager {
|
||||
|
||||
private AdventureManager() {
|
||||
}
|
||||
|
||||
private static boolean adventureAvailable = false;
|
||||
private static Object audiences;
|
||||
|
||||
public static void init(Plugin plugin) {
|
||||
try {
|
||||
// Проверяем наличие Adventure API
|
||||
Class.forName("net.kyori.adventure.text.Component");
|
||||
Class<?> audiencesClass = Class.forName("net.kyori.adventure.platform.bukkit.BukkitAudiences");
|
||||
|
||||
// Создаем BukkitAudiences через рефлексию
|
||||
Object audiencesInstance = audiencesClass.getMethod("create", Plugin.class).invoke(null, plugin);
|
||||
audiences = audiencesInstance;
|
||||
adventureAvailable = true;
|
||||
|
||||
plugin.getLogger().info("Adventure API обнаружен - используем нативную поддержку");
|
||||
} catch (Exception e) {
|
||||
adventureAvailable = false;
|
||||
plugin.getLogger().info("Adventure API не найден - используем legacy режим");
|
||||
}
|
||||
}
|
||||
|
||||
public static void shutdown() {
|
||||
if (audiences != null && adventureAvailable) {
|
||||
try {
|
||||
audiences.getClass().getMethod("close").invoke(audiences);
|
||||
} catch (Exception e) {
|
||||
// Игнорируем ошибки при закрытии
|
||||
}
|
||||
audiences = null;
|
||||
}
|
||||
adventureAvailable = false;
|
||||
}
|
||||
|
||||
public static void sendMessage(CommandSender sender, Object message) {
|
||||
if (adventureAvailable && audiences != null) {
|
||||
try {
|
||||
// Используем Adventure API
|
||||
Object senderAudience = audiences.getClass().getMethod("sender", CommandSender.class).invoke(audiences, sender);
|
||||
senderAudience.getClass()
|
||||
.getMethod("sendMessage", Class.forName("net.kyori.adventure.text.Component"))
|
||||
.invoke(senderAudience, message);
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
// Fallback на legacy
|
||||
}
|
||||
}
|
||||
|
||||
// Legacy fallback
|
||||
if (message instanceof String) {
|
||||
sender.sendMessage((String) message);
|
||||
} else {
|
||||
sender.sendMessage(message.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public static void sendMessage(Player player, Object message) {
|
||||
if (adventureAvailable && audiences != null) {
|
||||
try {
|
||||
// Используем Adventure API
|
||||
Object playerAudience = audiences.getClass().getMethod("player", Player.class).invoke(audiences, player);
|
||||
playerAudience.getClass()
|
||||
.getMethod("sendMessage", Class.forName("net.kyori.adventure.text.Component"))
|
||||
.invoke(playerAudience, message);
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
// Fallback на legacy
|
||||
}
|
||||
}
|
||||
|
||||
// Legacy fallback
|
||||
if (message instanceof String) {
|
||||
player.sendMessage((String) message);
|
||||
} else {
|
||||
player.sendMessage(message.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isAdventureAvailable() {
|
||||
return adventureAvailable;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue