diff --git a/build.gradle.kts b/build.gradle.kts
index 95dab4d..53b2149 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -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/")
+ }
}
\ No newline at end of file
diff --git a/bukkit/build.gradle.kts b/bukkit/build.gradle.kts
new file mode 100644
index 0000000..a90f838
--- /dev/null
+++ b/bukkit/build.gradle.kts
@@ -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)
+}
\ No newline at end of file
diff --git a/bukkit/src/main/java/fr/redsavant/LagoonPlugin.java b/bukkit/src/main/java/fr/redsavant/LagoonPlugin.java
new file mode 100644
index 0000000..b806a81
--- /dev/null
+++ b/bukkit/src/main/java/fr/redsavant/LagoonPlugin.java
@@ -0,0 +1,12 @@
+package fr.redsavant;
+
+public class LagoonPlugin extends BootstrapPlugin {
+
+ @Override
+ protected void onStart() {
+ }
+
+ @Override
+ protected void onStop() {
+ }
+}
diff --git a/bukkit/src/main/resources/plugin.yml b/bukkit/src/main/resources/plugin.yml
new file mode 100644
index 0000000..5504cdf
--- /dev/null
+++ b/bukkit/src/main/resources/plugin.yml
@@ -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
\ No newline at end of file
diff --git a/commun/build.gradle.kts b/commun/build.gradle.kts
new file mode 100644
index 0000000..1d618f4
--- /dev/null
+++ b/commun/build.gradle.kts
@@ -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")
+}
\ No newline at end of file
diff --git a/commun/src/main/java/fr/redsavant/BootstrapPlugin.java b/commun/src/main/java/fr/redsavant/BootstrapPlugin.java
new file mode 100644
index 0000000..13b6d53
--- /dev/null
+++ b/commun/src/main/java/fr/redsavant/BootstrapPlugin.java
@@ -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("" + line + "");
+ log.mini("Enabling Lagoon, Version : " + version + "");
+ log.mini("" + line + "");
+ } 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 getInstance() {
+ return (T) instance;
+ }
+}
\ No newline at end of file
diff --git a/commun/src/main/java/fr/redsavant/logging/CommunLog.java b/commun/src/main/java/fr/redsavant/logging/CommunLog.java
new file mode 100644
index 0000000..b35c9f6
--- /dev/null
+++ b/commun/src/main/java/fr/redsavant/logging/CommunLog.java
@@ -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) namedColorClass, "GRAY"); }
+ case WARNING -> { prefix = "▲ "; color = Enum.valueOf((Class) namedColorClass, "YELLOW"); }
+ case SEVERE -> { prefix = "✖ "; color = Enum.valueOf((Class) namedColorClass, "RED"); }
+ default -> { prefix = ""; color = Enum.valueOf((Class) 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 }
+}
\ No newline at end of file
diff --git a/commun/src/main/java/fr/redsavant/logging/MiniToLegacySpigot.java b/commun/src/main/java/fr/redsavant/logging/MiniToLegacySpigot.java
new file mode 100644
index 0000000..817d991
--- /dev/null
+++ b/commun/src/main/java/fr/redsavant/logging/MiniToLegacySpigot.java
@@ -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("", ChatColor.BLACK.toString())
+ .replace("", ChatColor.DARK_BLUE.toString())
+ .replace("", ChatColor.DARK_GREEN.toString())
+ .replace("", ChatColor.DARK_AQUA.toString())
+ .replace("", ChatColor.DARK_RED.toString())
+ .replace("", ChatColor.DARK_PURPLE.toString())
+ .replace("", ChatColor.GOLD.toString())
+ .replace("", ChatColor.GRAY.toString())
+ .replace("", ChatColor.DARK_GRAY.toString())
+ .replace("", ChatColor.BLUE.toString())
+ .replace("", ChatColor.GREEN.toString())
+ .replace("", ChatColor.AQUA.toString())
+ .replace("", ChatColor.RED.toString())
+ .replace("", ChatColor.LIGHT_PURPLE.toString())
+ .replace("", ChatColor.YELLOW.toString())
+ .replace("", ChatColor.WHITE.toString())
+ .replace("", ChatColor.BOLD.toString())
+ .replace("", ChatColor.ITALIC.toString())
+ .replace("", ChatColor.UNDERLINE.toString())
+ .replace("", ChatColor.STRIKETHROUGH.toString())
+ .replace("", ChatColor.RESET.toString())
+ .replace("", ChatColor.RESET.toString())
+ .replace("", ChatColor.RESET.toString())
+ .replace("", ChatColor.RESET.toString())
+ .replace("", ChatColor.RESET.toString())
+ .replaceAll("(?i)?gradient(:[^>]*)?>", "")
+ .replaceAll("(?i)<[^>]+>", "");
+ }
+}
\ No newline at end of file
diff --git a/commun/src/main/java/fr/redsavant/utils/Colorize.java b/commun/src/main/java/fr/redsavant/utils/Colorize.java
new file mode 100644
index 0000000..3b62da2
--- /dev/null
+++ b/commun/src/main/java/fr/redsavant/utils/Colorize.java
@@ -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);
+ }
+}
\ No newline at end of file
diff --git a/settings.gradle.kts b/settings.gradle.kts
index fa8c686..aadc370 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -1 +1,3 @@
-rootProject.name = "Lagoon"
\ No newline at end of file
+rootProject.name = "Lagoon"
+
+include("commun", "bukkit")
\ No newline at end of file
diff --git a/src/main/java/fr/redsavant/Main.java b/src/main/java/fr/redsavant/Main.java
deleted file mode 100644
index ecdfa42..0000000
--- a/src/main/java/fr/redsavant/Main.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package fr.redsavant;
-
-//TIP To Run code, press or
-// click the icon in the gutter.
-public class Main {
- public static void main(String[] args) {
- //TIP Press 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 to start debugging your code. We have set one breakpoint
- // for you, but you can always add more by pressing .
- System.out.println("i = " + i);
- }
- }
-}
\ No newline at end of file