Refactoring Pandalib-bungee + added some source files from Pandacube sources

This commit is contained in:
2022-12-21 16:31:21 +01:00
parent a7aa012fa4
commit ebb7b5b4c5
9 changed files with 211 additions and 64 deletions

View File

@@ -21,17 +21,44 @@
</repositories>
<dependencies>
<dependency>
<groupId>fr.pandacube.lib</groupId>
<artifactId>pandalib-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>fr.pandacube.lib</groupId>
<artifactId>pandalib-util</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>fr.pandacube.lib</groupId>
<artifactId>pandalib-players</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>fr.pandacube.lib</groupId>
<artifactId>pandalib-reflect</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-protocol</artifactId>
<version>${bungeecord.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>${bungeecord.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>fr.pandacube.lib</groupId>
<artifactId>pandalib-core</artifactId>
<version>${project.version}</version>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-log</artifactId>
<version>${bungeecord.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>

View File

@@ -0,0 +1,29 @@
package fr.pandacube.lib.bungee;
import fr.pandacube.lib.bungee.util.DailyLogRotateFileHandler;
import fr.pandacube.lib.bungee.util.PluginMessagePassthrough;
import net.md_5.bungee.api.plugin.Plugin;
public class PandaLibBungee {
private static Plugin plugin;
public static void onLoad(Plugin plugin) {
PandaLibBungee.plugin = plugin;
}
public static void onEnable() {
PluginMessagePassthrough.init(plugin);
DailyLogRotateFileHandler.init(true);
}
public static void disable() {
}
public static Plugin getPlugin() {
return plugin;
}
}

View File

@@ -0,0 +1,29 @@
package fr.pandacube.lib.bungee.players;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import fr.pandacube.lib.players.standalone.AbstractOffPlayer;
/**
* Represents any player on a Bungeecord proxy, either offline or online.
*/
public interface BungeeOffPlayer extends AbstractOffPlayer {
/*
* Related class instances
*/
/**
* Returns the {@link ProxiedPlayer} instance of this player, or null if not available (offline).
* @return the {@link ProxiedPlayer} instance of this player, or null if not available (offline).
*/
default ProxiedPlayer getBungeeProxiedPlayer() {
return ProxyServer.getInstance().getPlayer(getUniqueId());
}
@Override
BungeeOnlinePlayer getOnlineInstance();
}

View File

@@ -0,0 +1,283 @@
package fr.pandacube.lib.bungee.players;
import java.util.Locale;
import java.util.UUID;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import net.kyori.adventure.identity.Identified;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.ComponentLike;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.SkinConfiguration;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.connection.ProxiedPlayer.ChatMode;
import net.md_5.bungee.api.connection.ProxiedPlayer.MainHand;
import net.md_5.bungee.api.connection.Server;
import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.packet.ClientSettings;
import net.md_5.bungee.protocol.packet.PluginMessage;
import fr.pandacube.lib.chat.Chat;
import fr.pandacube.lib.players.standalone.AbstractOnlinePlayer;
import fr.pandacube.lib.reflect.Reflect;
import fr.pandacube.lib.util.MinecraftVersion;
/**
* Represents any online player on a Bungeecord proxy.
*/
public interface BungeeOnlinePlayer extends BungeeOffPlayer, AbstractOnlinePlayer {
/*
* General data and state
*/
@Override
default String getName() {
return getBungeeProxiedPlayer().getName();
}
@Override
default String getServerName() {
if (getServer() == null) return null;
return getServer().getInfo().getName();
}
/**
* Returns the server on which the player is.
* @return the server on which the player is.
*/
default Server getServer() {
return getBungeeProxiedPlayer().getServer();
}
/**
* Gets the minecraft version of this players client.
* @return the minecraft version of this players client.
*/
default MinecraftVersion getMinecraftVersion() {
return MinecraftVersion.getVersion(getBungeeProxiedPlayer().getPendingConnection().getVersion());
}
/*
* Permissions and groups
*/
/**
* Tells if this online player has the specified permission.
*/
default boolean hasPermission(String permission) {
return getBungeeProxiedPlayer().hasPermission(permission);
}
/*
* Sending packet and stuff to player
*/
@Override
default void sendMessage(Component message) {
getBungeeProxiedPlayer().sendMessage(Chat.toBungee(message));
}
@Override
default void sendMessage(ComponentLike message, UUID sender) {
getBungeeProxiedPlayer().sendMessage(sender, Chat.toBungee(message.asComponent()));
}
@Override
default void sendMessage(Component message, Identified sender) {
getBungeeProxiedPlayer().sendMessage(sender == null ? null : sender.identity().uuid(), Chat.toBungee(message));
}
/**
* Display the provided message in the players chat, if they allows to display CHAT messages.
* @param message the message to send.
* @param sender the player causing the send of this message. Client side filtering may occur. May be null if we
* dont want client filtering, but still consider the message as CHAT message.
*/
default void sendMessage(ComponentLike message, ProxiedPlayer sender) {
getBungeeProxiedPlayer().sendMessage(sender == null ? null : sender.getUniqueId(), Chat.toBungee(message.asComponent()));
}
@Override
default void sendTitle(Component title, Component subtitle, int fadeIn, int stay, int fadeOut) {
ProxyServer.getInstance().createTitle()
.title(Chat.toBungee(title)).subTitle(Chat.toBungee(subtitle))
.fadeIn(fadeIn).stay(stay).fadeOut(fadeOut)
.send(getBungeeProxiedPlayer());
}
@Override
default void sendServerBrand(String legacyText) {
try {
ByteBuf payload = ByteBufAllocator.DEFAULT.heapBuffer();
DefinedPacket.writeString(legacyText, payload);
getBungeeProxiedPlayer().unsafe().sendPacket(new PluginMessage("minecraft:brand", DefinedPacket.toArray(payload), false));
payload.release();
} catch (Exception ignored) { }
}
/*
* Client options
*/
@Override
default BungeeClientOptions getClientOptions() {
return new BungeeClientOptions(this);
}
/**
* Provides various configuration values of the Minecraft client.
*/
class BungeeClientOptions implements AbstractOnlinePlayer.ClientOptions {
private final BungeeOnlinePlayer op;
/**
* Create a new instance of {@link BungeeClientOptions}.
* @param op the {@link BungeeOnlinePlayer} instance.
*/
public BungeeClientOptions(BungeeOnlinePlayer op) {
this.op = op;
}
private ClientSettings getBungeeSettings() {
ProxiedPlayer pp = op.getBungeeProxiedPlayer();
try {
return (ClientSettings) Reflect.ofClassOfInstance(pp).method("getSettings").invoke(pp);
} catch (ReflectiveOperationException e) {
throw new RuntimeException(e);
}
}
@Override
public boolean hasChatColorEnabled() {
return op.getBungeeProxiedPlayer().hasChatColors();
}
/**
* Gets the chat visibility configuration.
* @return the chat visibility configuration.
*/
public ChatMode getChatMode() {
return op.getBungeeProxiedPlayer().getChatMode();
}
@Override
public boolean isChatFullyVisible() {
ChatMode v = getChatMode();
return v == ChatMode.SHOWN || v == null;
}
@Override
public boolean isChatOnlyDisplayingSystemMessages() {
return getChatMode() == ChatMode.COMMANDS_ONLY;
}
@Override
public boolean isChatHidden() {
return getChatMode() == ChatMode.HIDDEN;
}
@Override
public Locale getLocale() {
return op.getBungeeProxiedPlayer().getLocale();
}
@Override
public int getViewDistance() {
return op.getBungeeProxiedPlayer().getViewDistance();
}
/**
* Gets the players main hand.
* @return the players main hand.
*/
public MainHand getMainHand() {
return op.getBungeeProxiedPlayer().getMainHand();
}
@Override
public boolean isLeftHanded() {
return getMainHand() == MainHand.LEFT;
}
@Override
public boolean isRightHanded() {
return getMainHand() == MainHand.RIGHT;
}
@Override
public boolean isTextFilteringEnabled() {
ClientSettings settings = getBungeeSettings();
return settings != null && settings.isDisableTextFiltering(); // Bungee badly named the method
}
@Override
public boolean allowsServerListing() {
ClientSettings settings = getBungeeSettings();
return settings != null && settings.isAllowServerListing();
}
/**
* Gets the players skin configuration.
* @return the players skin configuration.
*/
public SkinConfiguration getSkinParts() {
return op.getBungeeProxiedPlayer().getSkinParts();
}
@Override
public boolean hasSkinCapeEnabled() {
return getSkinParts().hasCape();
}
@Override
public boolean hasSkinJacketEnabled() {
return getSkinParts().hasJacket();
}
@Override
public boolean hasSkinLeftSleeveEnabled() {
return getSkinParts().hasLeftSleeve();
}
@Override
public boolean hasSkinRightSleeveEnabled() {
return getSkinParts().hasRightSleeve();
}
@Override
public boolean hasSkinLeftPantsEnabled() {
return getSkinParts().hasLeftPants();
}
@Override
public boolean hasSkinRightPantsEnabled() {
return getSkinParts().hasRightPants();
}
@Override
public boolean hasSkinHatsEnabled() {
return getSkinParts().hasHat();
}
}
}

View File

@@ -0,0 +1,150 @@
package fr.pandacube.lib.bungee.util;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ThreadFactory;
import java.util.logging.ErrorManager;
import java.util.logging.Filter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.zip.GZIPOutputStream;
import com.google.common.io.Files;
import fr.pandacube.lib.bungee.PandaLibBungee;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.log.ConciseFormatter;
public class DailyLogRotateFileHandler extends Handler {
private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
public static void init(boolean hideInitialHandlerLogEntries) {
ProxyServer.getInstance().getLogger().addHandler(new DailyLogRotateFileHandler(hideInitialHandlerLogEntries));
}
private BufferedWriter currentFile = null;
private String currentFileDate = getCurrentDay();
private boolean closed = false;
private DailyLogRotateFileHandler(boolean hideInitialHandlerLogEntries) {
if (hideInitialHandlerLogEntries)
setFilter(new InitialHandlerLogRemover());
setFormatter(new ConciseFormatter(false));
setLevel(Level.parse(System.getProperty("net.md_5.bungee.file-log-level", "INFO")));
}
@Override
public synchronized void close() throws SecurityException {
closed = true;
if (currentFile != null) try {
currentFile.close();
} catch (IOException ignored) {
}
}
@Override
public synchronized void flush() {
if (closed) return;
if (currentFile == null) return;
try {
currentFile.flush();
} catch (IOException ignored) {
}
}
@Override
public synchronized void publish(LogRecord record) {
if (closed || !isLoggable(record))
return;
if (currentFile == null || !currentFileDate.equals(getCurrentDay()))
changeFile();
if (currentFile == null)
return;
String formattedMessage;
try {
formattedMessage = getFormatter().format(record);
} catch (Exception ex) {
reportError(null, ex, ErrorManager.FORMAT_FAILURE);
return;
}
try {
currentFile.write(formattedMessage);
currentFile.flush();
} catch (Exception ex) {
reportError(null, ex, ErrorManager.WRITE_FAILURE);
}
}
private void changeFile() {
if (currentFile != null) {
try {
currentFile.flush();
currentFile.close();
} catch (IOException ignored) {
}
File fileNewName = new File("logs/" + currentFileDate + ".log");
new File("logs/latest.log").renameTo(fileNewName);
ProxyServer.getInstance().getScheduler().runAsync(PandaLibBungee.getPlugin(), () -> compress(fileNewName));
}
currentFileDate = getCurrentDay();
try {
File logDir = new File("logs");
logDir.mkdir();
currentFile = new BufferedWriter(new FileWriter("logs/latest.log", true));
} catch (SecurityException | IOException e) {
reportError("Erreur lors de l'initialisation d'un fichier log", e, ErrorManager.OPEN_FAILURE);
currentFile = null;
}
}
private String getCurrentDay() {
return dateFormat.format(new Date());
}
private void compress(File sourceFile) {
File destFile = new File(sourceFile.getParentFile(), sourceFile.getName() + ".gz");
if (destFile.exists())
destFile.delete();
try (GZIPOutputStream os = new GZIPOutputStream(new FileOutputStream(destFile))) {
Files.copy(sourceFile, os);
} catch (IOException e) {
if (destFile.exists())
destFile.delete();
throw new RuntimeException(e);
}
sourceFile.delete();
}
private class InitialHandlerLogRemover implements Filter {
@Override
public boolean isLoggable(LogRecord record) {
String formattedRecord = getFormatter().format(record);
if (formattedRecord.contains("<-> InitialHandler has connected")) return false;
if (formattedRecord.contains("<-> InitialHandler has pinged")) return false;
return true;
}
}
}

View File

@@ -1,4 +1,4 @@
package fr.pandacube.lib.bungee;
package fr.pandacube.lib.bungee.util;
import java.util.ArrayList;
import java.util.Collections;