Creating base multi-module project + logging

This commit is contained in:
RedSavant
2026-03-23 19:16:10 +01:00
parent 7f94b99f1b
commit 88547c6d5e
11 changed files with 281 additions and 30 deletions

View File

@@ -1,20 +1,24 @@
plugins {
id("java")
java
id("com.gradleup.shadow") version "8.3.6" apply false
id("xyz.jpenilla.run-paper") version "2.3.1" apply false
}
group = "fr.redsavant"
version = "1.0-SNAPSHOT"
version = "1.0.0"
repositories {
mavenCentral()
}
subprojects {
apply(plugin = "java")
dependencies {
testImplementation(platform("org.junit:junit-bom:5.10.0"))
testImplementation("org.junit.jupiter:junit-jupiter")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(21))
}
}
tasks.test {
useJUnitPlatform()
repositories {
mavenCentral()
maven("https://hub.spigotmc.org/nexus/content/groups/public/")
maven("https://repo.papermc.io/repository/maven-public/")
}
}

19
bukkit/build.gradle.kts Normal file
View File

@@ -0,0 +1,19 @@
plugins {
id("com.gradleup.shadow")
}
version = "1.0.0"
dependencies {
compileOnly("org.spigotmc:spigot-api:1.21-R0.1-SNAPSHOT")
implementation(project(":commun"))
}
tasks.shadowJar {
archiveBaseName.set("LagoonPlugin")
archiveClassifier.set("")
archiveVersion.set(version.toString())
}
tasks.build {
dependsOn(tasks.shadowJar)
}

View File

@@ -0,0 +1,12 @@
package fr.redsavant;
public class LagoonPlugin extends BootstrapPlugin {
@Override
protected void onStart() {
}
@Override
protected void onStop() {
}
}

View File

@@ -0,0 +1,9 @@
name: LagoonPlugin
version: 1.0.0
description: A plugin to link proximity chat of Lagoon
website: https://lagoon.under-scape.com
authors:
- RedSavant
- UnderScape (lagoon)
api-version: '1.21'
main: fr.redsavant.LagoonPlugin

8
commun/build.gradle.kts Normal file
View File

@@ -0,0 +1,8 @@
dependencies {
compileOnly("io.papermc.paper:paper-api:1.21.11-R0.1-SNAPSHOT")
implementation("net.kyori:adventure-api:4.17.0")
implementation("net.kyori:adventure-text-minimessage:4.17.0")
implementation("net.kyori:adventure-text-serializer-plain:4.17.0")
implementation("net.kyori:adventure-text-logger-slf4j:4.17.0")
implementation("org.slf4j:slf4j-api:2.0.9")
}

View File

@@ -0,0 +1,52 @@
package fr.redsavant;
import fr.redsavant.logging.CommunLog;
import org.bukkit.plugin.java.JavaPlugin;
public abstract class BootstrapPlugin extends JavaPlugin {
private static BootstrapPlugin instance;
private CommunLog log;
protected static String version = "1.0.0";
@Override
public final void onEnable() {
instance = this;
this.log = new CommunLog(this);
StartLog();
onStart();
}
@Override
public final void onDisable() {
onStop();
getLogger().info("GoodBye !");
}
private void StartLog() {
final String line = "―――――――――――――――――――――――――――――――――";
if (log.isPaper()) {
// Paper: MiniMessage -> Component (via CommunLog.mini)
log.mini("<gold>" + line + "</gold>");
log.mini("<gold>Enabling Lagoon, Version : </gold><yellow>" + version + "</yellow>");
log.mini("<gold>" + line + "</gold>");
} else {
getLogger().info(line);
getLogger().info("Enabling Lagoon, Version : " + version);
getLogger().info(line);
}
}
protected abstract void onStart();
protected abstract void onStop();
@SuppressWarnings("unchecked")
public static <T extends BootstrapPlugin> T getInstance() {
return (T) instance;
}
}

View File

@@ -0,0 +1,112 @@
package fr.redsavant.logging;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
import java.lang.reflect.Method;
import java.util.logging.Logger;
public final class CommunLog {
private final JavaPlugin plugin;
private final Logger jul;
public CommunLog(JavaPlugin plugin) {
this.plugin = plugin;
this.jul = plugin.getLogger();
}
public void info(String message) { send(Level.INFO, message); }
public void warning(String message) { send(Level.WARNING, message); }
public void severe(String message) { send(Level.SEVERE, message); }
/** MiniMessage (Paper) / blanc (Spigot) */
public void mini(String miniMessage) {
if (isPaper() && trySendMiniMessageToConsole(miniMessage)) return;
jul.info(stripColorish(miniMessage));
}
private void send(Level level, String message) {
if (isPaper() && tryPaperAdventureLog(level, message)) return;
String plain = stripColorish(message);
switch (level) {
case INFO -> jul.info(plain);
case WARNING -> jul.warning(plain);
case SEVERE -> jul.severe(plain);
}
}
public boolean isPaper() {
try { Class.forName("io.papermc.paper.configuration.Configuration"); return true; }
catch (Throwable ignored) { }
try { Class.forName("com.destroystokyo.paper.PaperConfig"); return true; }
catch (Throwable ignored) { }
String name = Bukkit.getName();
return name != null && name.toLowerCase().contains("paper");
}
private boolean trySendMiniMessageToConsole(String mini) {
try {
Object console = Bukkit.getConsoleSender();
// MiniMessage.miniMessage().deserialize(String)
Class<?> miniMessageClass = Class.forName("net.kyori.adventure.text.minimessage.MiniMessage");
Method miniMessageFactory = miniMessageClass.getMethod("miniMessage");
Object mm = miniMessageFactory.invoke(null);
Method deserialize = miniMessageClass.getMethod("deserialize", String.class);
Object component = deserialize.invoke(mm, mini);
Class<?> componentClass = Class.forName("net.kyori.adventure.text.Component");
Method sendMessage = console.getClass().getMethod("sendMessage", componentClass);
sendMessage.invoke(console, component);
return true;
} catch (Throwable ignored) {
return false;
}
}
private boolean tryPaperAdventureLog(Level level, String message) {
try {
Object console = Bukkit.getConsoleSender();
Class<?> componentClass = Class.forName("net.kyori.adventure.text.Component");
Class<?> namedColorClass = Class.forName("net.kyori.adventure.text.format.NamedTextColor");
Class<?> textColorClass = Class.forName("net.kyori.adventure.text.format.TextColor");
Method textMethod = componentClass.getMethod("text", String.class);
Object color;
String prefix;
switch (level) {
case INFO -> { prefix = ""; color = Enum.valueOf((Class<Enum>) namedColorClass, "GRAY"); }
case WARNING -> { prefix = ""; color = Enum.valueOf((Class<Enum>) namedColorClass, "YELLOW"); }
case SEVERE -> { prefix = ""; color = Enum.valueOf((Class<Enum>) namedColorClass, "RED"); }
default -> { prefix = ""; color = Enum.valueOf((Class<Enum>) namedColorClass, "WHITE"); }
}
Object component = textMethod.invoke(null, prefix + message);
Method colorMethod = component.getClass().getMethod("color", textColorClass);
Object coloredComponent = colorMethod.invoke(component, color);
Method sendMessage = console.getClass().getMethod("sendMessage", componentClass);
sendMessage.invoke(console, coloredComponent);
return true;
} catch (Throwable ignored) {
return false;
}
}
private String stripColorish(String s) {
if (s == null) return "";
return s
.replaceAll("(?i)[§&][0-9A-FK-OR]", "")
.replaceAll("(?i)<[^>]+>", "");
}
private enum Level { INFO, WARNING, SEVERE }
}

View File

@@ -0,0 +1,39 @@
package fr.redsavant.logging;
import org.bukkit.ChatColor;
public final class MiniToLegacySpigot {
private MiniToLegacySpigot() {}
public static String miniToLegacy(String s) {
if (s == null) return "";
return s
.replace("<black>", ChatColor.BLACK.toString())
.replace("<dark_blue>", ChatColor.DARK_BLUE.toString())
.replace("<dark_green>", ChatColor.DARK_GREEN.toString())
.replace("<dark_aqua>", ChatColor.DARK_AQUA.toString())
.replace("<dark_red>", ChatColor.DARK_RED.toString())
.replace("<dark_purple>", ChatColor.DARK_PURPLE.toString())
.replace("<gold>", ChatColor.GOLD.toString())
.replace("<gray>", ChatColor.GRAY.toString())
.replace("<dark_gray>", ChatColor.DARK_GRAY.toString())
.replace("<blue>", ChatColor.BLUE.toString())
.replace("<green>", ChatColor.GREEN.toString())
.replace("<aqua>", ChatColor.AQUA.toString())
.replace("<red>", ChatColor.RED.toString())
.replace("<light_purple>", ChatColor.LIGHT_PURPLE.toString())
.replace("<yellow>", ChatColor.YELLOW.toString())
.replace("<white>", ChatColor.WHITE.toString())
.replace("<bold>", ChatColor.BOLD.toString())
.replace("<italic>", ChatColor.ITALIC.toString())
.replace("<underlined>", ChatColor.UNDERLINE.toString())
.replace("<strikethrough>", ChatColor.STRIKETHROUGH.toString())
.replace("<reset>", ChatColor.RESET.toString())
.replace("</bold>", ChatColor.RESET.toString())
.replace("</italic>", ChatColor.RESET.toString())
.replace("</underlined>", ChatColor.RESET.toString())
.replace("</strikethrough>", ChatColor.RESET.toString())
.replaceAll("(?i)</?gradient(:[^>]*)?>", "")
.replaceAll("(?i)<[^>]+>", "");
}
}

View File

@@ -0,0 +1,11 @@
package fr.redsavant.utils;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
public class Colorize {
private static final MiniMessage minimessage = MiniMessage.miniMessage();
public static Component colorize(String message) {
return minimessage.deserialize(message);
}
}

View File

@@ -1 +1,3 @@
rootProject.name = "Lagoon"
rootProject.name = "Lagoon"
include("commun", "bukkit")

View File

@@ -1,17 +0,0 @@
package fr.redsavant;
//TIP To <b>Run</b> code, press <shortcut actionId="Run"/> or
// click the <icon src="AllIcons.Actions.Execute"/> icon in the gutter.
public class Main {
public static void main(String[] args) {
//TIP Press <shortcut actionId="ShowIntentionActions"/> with your caret at the highlighted text
// to see how IntelliJ IDEA suggests fixing it.
System.out.printf("Hello and welcome!");
for (int i = 1; i <= 5; i++) {
//TIP Press <shortcut actionId="Debug"/> to start debugging your code. We have set one <icon src="AllIcons.Debugger.Db_set_breakpoint"/> breakpoint
// for you, but you can always add more by pressing <shortcut actionId="ToggleLineBreakpoint"/>.
System.out.println("i = " + i);
}
}
}