commit 351a46ee177306845a21dda9365c25eb4986c0a0 Author: bensuisse Date: Mon Aug 3 22:31:13 2026 +0200 init mining-man system diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..ab1f416 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,10 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Ignored default folder with query files +/queries/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..2371cc6 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..aa00ffa --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 0000000..828a0d8 --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/material_theme_project_new.xml b/.idea/material_theme_project_new.xml new file mode 100644 index 0000000..b9b6d2e --- /dev/null +++ b/.idea/material_theme_project_new.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..d61b968 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..a54b4d0 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/LunaraSystem.iml b/LunaraSystem.iml new file mode 100644 index 0000000..3cf00db --- /dev/null +++ b/LunaraSystem.iml @@ -0,0 +1,13 @@ + + + + + + + PAPER + + 1 + + + + \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..47ee314 --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +# MiningMan + +Minecraft-Plugin (Paper/Bukkit), benötigt LuckPerms. + +## Funktionen + +- **Join/Quit-Nachrichten** mit LuckPerms-Rangprefix +- **Chat-Formatierung** (`Name: Nachricht`), Highlight für Spieler mit `miningman.chat.highlight` +- `/clearchat` (`/cc`) – Chat leeren — `miningman.clearchat` +- `/announce small ` – kleine Broadcast-Nachricht +- `/announce big ` – große Broadcast-Nachricht als Title + Chat-Banner +- `/announce restart ` – Countdown mit Broadcasts, stoppt den Server danach — `miningman.announce` +- `/discord`, `/dc` – sendet Discord-Invite-Link +- **Tablist**: Gruppierung/Sortierung nach LuckPerms-Rang, Rang-Prefixe vor Namen, Header/Footer mit Spielerzahl + +## Build + +``` +mvn clean package +``` diff --git a/dependency-reduced-pom.xml b/dependency-reduced-pom.xml new file mode 100644 index 0000000..6432b2a --- /dev/null +++ b/dependency-reduced-pom.xml @@ -0,0 +1,63 @@ + + + 4.0.0 + ch.bensuisse + LunaraSystem + LunaraSystem + 1.0 + + clean package + + + true + src/main/resources + + + + + maven-compiler-plugin + 3.13.0 + + ${java.version} + ${java.version} + + + + maven-shade-plugin + 3.5.3 + + + package + + shade + + + + + + + + + papermc-repo + https://repo.papermc.io/repository/maven-public/ + + + + + io.papermc.paper + paper-api + 1.21.11-R0.1-SNAPSHOT + provided + + + net.luckperms + api + 5.4 + provided + + + + 21 + UTF-8 + + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..a479cff --- /dev/null +++ b/pom.xml @@ -0,0 +1,75 @@ + + + 4.0.0 + + ch.bensuisse + MiningMan + 1.0 + jar + + MiningMan + + + 21 + UTF-8 + + + + clean package + + + org.apache.maven.plugins + maven-compiler-plugin + 3.13.0 + + ${java.version} + ${java.version} + + + + org.apache.maven.plugins + maven-shade-plugin + 3.5.3 + + + package + + shade + + + + + + + + src/main/resources + true + + + + + + + papermc-repo + https://repo.papermc.io/repository/maven-public/ + + + + + + io.papermc.paper + paper-api + 1.21.11-R0.1-SNAPSHOT + provided + + + + net.luckperms + api + 5.4 + provided + + + diff --git a/src/main/java/ch/bensuisse/miningman/MiningMan.java b/src/main/java/ch/bensuisse/miningman/MiningMan.java new file mode 100644 index 0000000..a0243ee --- /dev/null +++ b/src/main/java/ch/bensuisse/miningman/MiningMan.java @@ -0,0 +1,79 @@ +package ch.bensuisse.miningman; + +import ch.bensuisse.miningman.commands.SocialCommands; +import ch.bensuisse.miningman.features.announce.AnnounceCommand; +import ch.bensuisse.miningman.features.chat.ChatListener; +import ch.bensuisse.miningman.features.chat.ClearChatCommand; +import ch.bensuisse.miningman.features.general.ConnectionListener; +import ch.bensuisse.miningman.features.tablist.TablistService; +import ch.bensuisse.miningman.managers.JoinManager; +import net.luckperms.api.LuckPerms; +import org.bukkit.Bukkit; +import org.bukkit.plugin.RegisteredServiceProvider; +import org.bukkit.plugin.java.JavaPlugin; + +public final class MiningMan extends JavaPlugin { + + private LuckPerms luckPerms; + private TablistService tablistService; + + @Override + public void onEnable() { + if (!setupLuckPerms()) { + getLogger().severe("LuckPerms nicht gefunden! Plugin schaltet ab."); + getServer().getPluginManager().disablePlugin(this); + return; + } + + this.tablistService = new TablistService(this, luckPerms); + + registerListeners(); + registerCommands(); + new JoinManager(this); + + getLogger().info("MiningMan v1.0 erfolgreich gestartet."); + } + + @Override + public void onDisable() { + if (tablistService != null) + tablistService.onDisable(); + } + + private boolean setupLuckPerms() { + RegisteredServiceProvider provider = Bukkit.getServicesManager().getRegistration(LuckPerms.class); + if (provider != null) { + this.luckPerms = provider.getProvider(); + return true; + } + return false; + } + + private void registerListeners() { + var pm = getServer().getPluginManager(); + + pm.registerEvents(new ConnectionListener(luckPerms), this); + pm.registerEvents(new ChatListener(this), this); + pm.registerEvents(this.tablistService, this); + } + + private void registerCommands() { + AnnounceCommand announceCmd = new AnnounceCommand(this); + getCommand("announce").setExecutor(announceCmd); + getCommand("announce").setTabCompleter(announceCmd); + + SocialCommands socialCommands = new SocialCommands(); + getCommand("discord").setExecutor(socialCommands); + getCommand("discord").setTabCompleter(socialCommands); + getCommand("dc").setExecutor(socialCommands); + getCommand("dc").setTabCompleter(socialCommands); + + ClearChatCommand clearChatCommand = new ClearChatCommand(); + getCommand("clearchat").setExecutor(clearChatCommand); + getCommand("clearchat").setTabCompleter(clearChatCommand); + } + + public TablistService getTablistService() { + return tablistService; + } +} diff --git a/src/main/java/ch/bensuisse/miningman/api/ColorUtil.java b/src/main/java/ch/bensuisse/miningman/api/ColorUtil.java new file mode 100644 index 0000000..bf5a438 --- /dev/null +++ b/src/main/java/ch/bensuisse/miningman/api/ColorUtil.java @@ -0,0 +1,31 @@ +package ch.bensuisse.miningman.api; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.TextColor; +import java.util.ArrayList; +import java.util.List; + +public class ColorUtil { + + public static List createGradient(TextColor start, TextColor end, int steps) { + List colors = new ArrayList<>(); + for (int i = 0; i < steps; i++) { + float ratio = (float) i / (steps - 1); + int r = (int) (start.red() * (1 - ratio) + end.red() * ratio); + int g = (int) (start.green() * (1 - ratio) + end.green() * ratio); + int b = (int) (start.blue() * (1 - ratio) + end.blue() * ratio); + colors.add(TextColor.color(r, g, b)); + } + return colors; + } + + public static Component applyGradient(String text, List colors) { + Component result = Component.empty(); + for (int i = 0; i < text.length(); i++) { + double progress = Math.min(1.0, (double) i / (text.length() - 1)); + int colorIndex = (int) (progress * (colors.size() - 1)); + result = result.append(Component.text(String.valueOf(text.charAt(i))).color(colors.get(colorIndex))); + } + return result; + } +} \ No newline at end of file diff --git a/src/main/java/ch/bensuisse/miningman/commands/SocialCommands.java b/src/main/java/ch/bensuisse/miningman/commands/SocialCommands.java new file mode 100644 index 0000000..a53c941 --- /dev/null +++ b/src/main/java/ch/bensuisse/miningman/commands/SocialCommands.java @@ -0,0 +1,57 @@ +package ch.bensuisse.miningman.commands; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.ClickEvent; +import net.kyori.adventure.text.format.TextColor; +import net.kyori.adventure.text.format.TextDecoration; +import org.bukkit.Sound; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; + +public class SocialCommands implements CommandExecutor, TabCompleter { + + private static final TextColor THEME_COLOR = TextColor.fromHexString("#56CF94"); + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, + @NotNull String[] args) { + if (!(sender instanceof Player player)) { + return true; + } + + if (command.getName().equalsIgnoreCase("discord") || command.getName().equalsIgnoreCase("dc")) { + sendDiscordMessage(player); + } + + return true; + } + + private void sendDiscordMessage(Player player) { + Component message = Component.text() + .append(Component.newline()) + .append(Component.text("ᴊᴏɪɴ ᴛʜᴇ ʟᴜɴᴀʀᴀᴍᴄ ᴅɪsᴄᴏʀᴅ ᴄᴏᴍᴍᴜɴɪᴛʏ!") + .color(THEME_COLOR)) + .append(Component.newline()) + .append(Component.text("discord.gg/lunaramc") + .color(TextColor.color(255, 255, 255)) + .decorate(TextDecoration.UNDERLINED) + .clickEvent(ClickEvent.openUrl("https://discord.gg/lunaramc"))) + .append(Component.newline()) + .build(); + + player.sendMessage(message); + player.playSound(player.getLocation(), Sound.BLOCK_NOTE_BLOCK_CHIME, 1.0f, 1.0f); + } + + @Override + public List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) { + return Collections.emptyList(); + } +} diff --git a/src/main/java/ch/bensuisse/miningman/features/announce/AnnounceCommand.java b/src/main/java/ch/bensuisse/miningman/features/announce/AnnounceCommand.java new file mode 100644 index 0000000..23f5eaf --- /dev/null +++ b/src/main/java/ch/bensuisse/miningman/features/announce/AnnounceCommand.java @@ -0,0 +1,140 @@ +package ch.bensuisse.miningman.features.announce; + +import ch.bensuisse.miningman.MiningMan; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.TextDecoration; +import net.kyori.adventure.title.Title; +import org.bukkit.Bukkit; +import org.bukkit.Sound; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; +import org.bukkit.scheduler.BukkitRunnable; +import org.jetbrains.annotations.NotNull; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class AnnounceCommand implements CommandExecutor, TabCompleter { + + private final MiningMan plugin; + + public AnnounceCommand(MiningMan plugin) { + this.plugin = plugin; + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String label, + @NotNull String[] args) { + if (args.length < 2) { + sender.sendMessage(Component.text("ᴜsᴀɢᴇ: /ᴀɴɴᴏᴜɴᴄᴇ <ᴍᴇssᴀɢᴇ>", NamedTextColor.RED)); + return true; + } + + String type = args[0].toLowerCase(); + + if (type.equals("restart")) { + try { + startRestart(Integer.parseInt(args[1])); + } catch (NumberFormatException e) { + sender.sendMessage(Component.text("ᴘʟᴇᴀsᴇ ᴘʀᴏᴠɪᴅᴇ ᴀ ᴠᴀʟɪᴅ ɴᴜᴍʙᴇʀ", NamedTextColor.RED)); + } + return true; + } + + String msg = String.join(" ", Arrays.copyOfRange(args, 1, args.length)); + + switch (type) { + case "small" -> sendSmall(msg); + case "big" -> sendBig(msg); + default -> sender.sendMessage(Component.text("ᴜɴᴋɴᴏᴡɴ ᴛʏᴘᴇ", NamedTextColor.RED)); + } + return true; + } + + private void sendSmall(String msg) { + Component content = Component.text("\n[ᴀɴɴᴏᴜɴᴄᴇᴍᴇɴᴛ] ", NamedTextColor.GOLD, TextDecoration.BOLD) + .append(Component.text(msg, NamedTextColor.WHITE).decoration(TextDecoration.BOLD, false)) + .append(Component.newline()); + Bukkit.broadcast(content); + Bukkit.getOnlinePlayers() + .forEach(p -> p.playSound(p.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1f, 1f)); + } + + private void sendBig(String msg) { + Title title = Title.title( + Component.text("ɪᴍᴘᴏʀᴛᴀɴᴛ", NamedTextColor.RED, TextDecoration.BOLD), + Component.text("➤ ʟᴏᴏᴋ ɪɴ ᴛʜᴇ ᴄʜᴀᴛ", NamedTextColor.GRAY, TextDecoration.ITALIC), + Title.Times.times(Duration.ofMillis(500), Duration.ofSeconds(4), Duration.ofMillis(500))); + Bukkit.getServer().showTitle(title); + + Component line = Component.text(" ", NamedTextColor.GOLD, + TextDecoration.STRIKETHROUGH); + Component content = Component.newline().append(line).append(Component.newline()) + .append(Component.text(" » ", NamedTextColor.WHITE, TextDecoration.BOLD)) + .append(Component.text("ɪᴍᴘᴏʀᴛᴀɴᴛ ᴀɴɴᴏᴜɴᴄᴇᴍᴇɴᴛ", NamedTextColor.RED, TextDecoration.BOLD)) + .append(Component.newline()).append(Component.newline()) + .append(Component.text(" » ", NamedTextColor.YELLOW).append(Component.text(msg))) + .append(Component.newline()).append(line).append(Component.newline()); + + Bukkit.broadcast(content); + Bukkit.getOnlinePlayers().forEach(p -> { + p.playSound(p.getLocation(), Sound.ENTITY_ENDER_DRAGON_GROWL, 0.7f, 1.0f); + p.playSound(p.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1.0f, 0.5f); + }); + } + + private void startRestart(int seconds) { + new BukkitRunnable() { + int remaining = seconds; + + @Override + public void run() { + if (remaining <= 0) { + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "stop"); + cancel(); + return; + } + if (remaining > 60 && remaining % 30 == 0) + broadcastRestart(remaining); + else if (remaining > 10 && remaining % 15 == 0) + broadcastRestart(remaining); + else if (remaining <= 10) + broadcastRestart(remaining); + remaining--; + } + }.runTaskTimer(plugin, 0L, 20L); + } + + private void broadcastRestart(int seconds) { + Component msg = Component.text("sᴇʀᴠᴇʀ ʀᴇsᴛᴀʀᴛ ɪɴ ", NamedTextColor.RED, TextDecoration.BOLD) + .append(Component.text(seconds + " sᴇᴄᴏɴᴅs", NamedTextColor.YELLOW)); + + Title title = Title.title( + Component.text("ʀᴇsᴛᴀʀᴛ", NamedTextColor.RED, TextDecoration.BOLD), + Component.text("ɪɴ " + seconds + " sᴇᴄᴏɴᴅs", NamedTextColor.WHITE), + Title.Times.times(Duration.ofMillis(200), Duration.ofMillis(600), Duration.ofMillis(200))); + + Bukkit.broadcast(msg); + Bukkit.getServer().showTitle(title); + Bukkit.getOnlinePlayers().forEach(p -> p.playSound(p.getLocation(), Sound.BLOCK_NOTE_BLOCK_HARP, 1f, 1f)); + } + + @Override + public List onTabComplete(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String alias, + @NotNull String[] args) { + if (args.length == 1) { + return List.of("small", "restart", "big").stream() + .filter(s -> s.startsWith(args[0].toLowerCase())).toList(); + } else if (args.length == 2 && args[0].equalsIgnoreCase("restart")) { + return List.of("30", "60", "120", "300").stream().filter(s -> s.startsWith(args[1])).toList(); + } else if (args.length == 2) { + return List.of(""); + } + return new ArrayList<>(); + } +} \ No newline at end of file diff --git a/src/main/java/ch/bensuisse/miningman/features/chat/ChatListener.java b/src/main/java/ch/bensuisse/miningman/features/chat/ChatListener.java new file mode 100644 index 0000000..ef5ec3f --- /dev/null +++ b/src/main/java/ch/bensuisse/miningman/features/chat/ChatListener.java @@ -0,0 +1,44 @@ +package ch.bensuisse.miningman.features.chat; + +import ch.bensuisse.miningman.MiningMan; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.TextDecoration; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.AsyncPlayerChatEvent; + +public class ChatListener implements Listener { + + private static final String HIGHLIGHT_PERMISSION = "miningman.chat.highlight"; + + private final MiningMan plugin; + + public ChatListener(MiningMan plugin) { + this.plugin = plugin; + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onChat(AsyncPlayerChatEvent event) { + event.setCancelled(true); + Player player = event.getPlayer(); + String message = event.getMessage(); + + Component formatted = player.displayName() + .append(Component.text(": ", NamedTextColor.GRAY).decoration(TextDecoration.BOLD, false)) + .append(Component.text(message, NamedTextColor.WHITE).decoration(TextDecoration.BOLD, false)); + + Bukkit.getScheduler().runTask(plugin, () -> { + if (player.hasPermission(HIGHLIGHT_PERMISSION)) { + Bukkit.broadcast(Component.empty()); + Bukkit.broadcast(formatted); + Bukkit.broadcast(Component.empty()); + } else { + Bukkit.broadcast(formatted); + } + }); + } +} diff --git a/src/main/java/ch/bensuisse/miningman/features/chat/ClearChatCommand.java b/src/main/java/ch/bensuisse/miningman/features/chat/ClearChatCommand.java new file mode 100644 index 0000000..7fa035a --- /dev/null +++ b/src/main/java/ch/bensuisse/miningman/features/chat/ClearChatCommand.java @@ -0,0 +1,45 @@ +package ch.bensuisse.miningman.features.chat; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.minimessage.MiniMessage; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; + +public class ClearChatCommand implements CommandExecutor, TabCompleter { + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, + @NotNull String[] args) { + if (!sender.hasPermission("miningman.clearchat")) { + sender.sendMessage(Component.text("No permission.", NamedTextColor.RED)); + return true; + } + + Component blank = Component.empty(); + Component message = MiniMessage.miniMessage() + .deserialize("ᴛʜᴇ ᴄʜᴀᴛ ʜᴀs ʙᴇᴇɴ ᴄʟᴇᴀʀᴇᴅ"); + + for (Player player : Bukkit.getOnlinePlayers()) { + for (int i = 0; i < 100; i++) { + player.sendMessage(blank); + } + player.sendMessage(message); + } + + return true; + } + + @Override + public List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) { + return Collections.emptyList(); + } +} diff --git a/src/main/java/ch/bensuisse/miningman/features/general/ConnectionListener.java b/src/main/java/ch/bensuisse/miningman/features/general/ConnectionListener.java new file mode 100644 index 0000000..c7f718a --- /dev/null +++ b/src/main/java/ch/bensuisse/miningman/features/general/ConnectionListener.java @@ -0,0 +1,41 @@ +package ch.bensuisse.miningman.features.general; + +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.luckperms.api.LuckPerms; +import net.luckperms.api.model.user.User; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +public class ConnectionListener implements Listener { + + private final LuckPerms luckPerms; + + public ConnectionListener(LuckPerms luckPerms) { + this.luckPerms = luckPerms; + } + + @EventHandler + public void onJoin(PlayerJoinEvent event) { + String prefix = getPrefix(event.getPlayer()); + String msg = "[+] " + prefix + " " + event.getPlayer().getName(); + event.joinMessage(MiniMessage.miniMessage().deserialize(msg)); + } + + @EventHandler + public void onQuit(PlayerQuitEvent event) { + String prefix = getPrefix(event.getPlayer()); + String msg = "[-] " + prefix + " " + event.getPlayer().getName(); + event.quitMessage(MiniMessage.miniMessage().deserialize(msg)); + } + + private String getPrefix(Player player) { + User user = luckPerms.getUserManager().getUser(player.getUniqueId()); + if (user == null) + return ""; + String prefix = user.getCachedData().getMetaData().getPrefix(); + return prefix != null ? prefix : ""; + } +} \ No newline at end of file diff --git a/src/main/java/ch/bensuisse/miningman/features/tablist/TablistService.java b/src/main/java/ch/bensuisse/miningman/features/tablist/TablistService.java new file mode 100644 index 0000000..c946aac --- /dev/null +++ b/src/main/java/ch/bensuisse/miningman/features/tablist/TablistService.java @@ -0,0 +1,168 @@ +package ch.bensuisse.miningman.features.tablist; + +import ch.bensuisse.miningman.MiningMan; +import ch.bensuisse.miningman.api.ColorUtil; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.TextColor; +import net.kyori.adventure.text.format.TextDecoration; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.luckperms.api.LuckPerms; +import net.luckperms.api.model.group.Group; +import net.luckperms.api.model.user.User; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.scoreboard.Scoreboard; +import org.bukkit.scoreboard.Team; + +import java.util.Comparator; +import java.util.List; + +public class TablistService implements Listener { + + private final MiningMan plugin; + private final LuckPerms luckPerms; + private final List gradientColors; + + public TablistService(MiningMan plugin, LuckPerms luckPerms) { + this.plugin = plugin; + this.luckPerms = luckPerms; + + this.gradientColors = ColorUtil.createGradient(TextColor.fromHexString("#1E8967"), + TextColor.fromHexString("#00FCFC"), 18); + + Bukkit.getScheduler().runTaskTimer(plugin, this::updateAll, 20L, 40L); + } + + public void onDisable() { + Bukkit.getOnlinePlayers().forEach(p -> p.sendPlayerListHeaderAndFooter(Component.empty(), Component.empty())); + } + + @EventHandler + public void onJoin(PlayerJoinEvent event) { + Bukkit.getScheduler().runTaskLater(plugin, this::updateSorting, 10L); + } + + @EventHandler + public void onQuit(PlayerQuitEvent event) { + Bukkit.getScheduler().runTaskLater(plugin, this::updateSorting, 5L); + } + + private void updateAll() { + updateSorting(); + for (Player player : Bukkit.getOnlinePlayers()) { + updateHeaderFooter(player); + } + } + + private void updateSorting() { + List groups = luckPerms.getGroupManager().getLoadedGroups().stream() + .sorted(Comparator.comparingInt(g -> ((Group) g).getWeight().orElse(0)).reversed()) + .toList(); + + for (Player viewer : Bukkit.getOnlinePlayers()) { + Scoreboard board = viewer.getScoreboard(); + + for (int i = 0; i < groups.size(); i++) { + Group group = groups.get(i); + String teamName = String.format("%03d_%s", i, group.getName()); + if (teamName.length() > 16) + teamName = teamName.substring(0, 16); + + Team team = board.getTeam(teamName); + if (team == null) + team = board.registerNewTeam(teamName); + + String prefix = group.getCachedData().getMetaData().getPrefix(); + if (prefix != null) { + Component rankComponent = MiniMessage.miniMessage().deserialize(prefix); + + Component separator = Component.text(" ") + .decoration(TextDecoration.BOLD, false) + .color(NamedTextColor.WHITE); + + team.prefix(rankComponent.append(separator)); + } else { + team.prefix(Component.empty()); + } + } + + for (Player target : Bukkit.getOnlinePlayers()) { + User user = luckPerms.getUserManager().getUser(target.getUniqueId()); + if (user == null) + continue; + + String groupName = user.getPrimaryGroup(); + int weightIndex = -1; + for (int i = 0; i < groups.size(); i++) { + if (groups.get(i).getName().equalsIgnoreCase(groupName)) { + weightIndex = i; + break; + } + } + + if (weightIndex != -1) { + String teamName = String.format("%03d_%s", weightIndex, groups.get(weightIndex).getName()); + if (teamName.length() > 16) + teamName = teamName.substring(0, 16); + Team team = board.getTeam(teamName); + if (team != null && !team.hasEntry(target.getName())) { + team.addEntry(target.getName()); + } + } + + updateNametagAboveHead(target, user); + } + } + } + + private void updateNametagAboveHead(Player player, User user) { + String prefix = user.getCachedData().getMetaData().getPrefix(); + Component nameComponent = Component.text(player.getName(), NamedTextColor.WHITE); + + if (prefix != null && !prefix.isEmpty()) { + Component rankComp = MiniMessage.miniMessage().deserialize(prefix); + + Component nameWithSeparator = Component.text(" » ", NamedTextColor.GRAY) + .decoration(TextDecoration.BOLD, false) + .append(Component.text(player.getName(), NamedTextColor.WHITE) + .decoration(TextDecoration.BOLD, false)); + + player.displayName(rankComp.append(nameWithSeparator)); + } else { + player.displayName(nameComponent); + } + } + + private void updateHeaderFooter(Player player) { + Component title = ColorUtil.applyGradient("ʟᴜɴᴀʀᴀᴍᴄ.xʏᴢ", gradientColors) + .decorate(TextDecoration.BOLD); + + int playerCount = Bukkit.getOnlinePlayers().size(); + Component players = Component.text("ᴘʟᴀʏᴇʀs: " + playerCount, TextColor.fromHexString("#A8A8A8")); + + Component header = Component.newline() + .append(title) + .append(Component.newline()) + .append(players) + .append(Component.newline()); + + Component storeLine = Component.text("sᴛᴏʀᴇ: ", TextColor.fromHexString("#FC0000")) + .append(Component.text("ᴄᴏᴍᴍɪɴɢ sᴏᴏɴ", NamedTextColor.WHITE)); + + Component discordLine = Component.text(" ᴅɪsᴄᴏʀᴅ: ", TextColor.fromHexString("#5454FC")) + .append(Component.text("ᴅɪsᴄᴏʀᴅ.ɢɢ/ʟᴜɴᴀʀᴀᴍᴄ ", NamedTextColor.WHITE)); + + Component footer = Component.newline() + .append(storeLine) + .append(Component.newline()) + .append(discordLine) + .append(Component.newline()); + + player.sendPlayerListHeaderAndFooter(header, footer); + } +} \ No newline at end of file diff --git a/src/main/java/ch/bensuisse/miningman/managers/JoinManager.java b/src/main/java/ch/bensuisse/miningman/managers/JoinManager.java new file mode 100644 index 0000000..d9a4b6c --- /dev/null +++ b/src/main/java/ch/bensuisse/miningman/managers/JoinManager.java @@ -0,0 +1,18 @@ +package ch.bensuisse.miningman.managers; + +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.plugin.java.JavaPlugin; + +public class JoinManager implements Listener { + + public JoinManager(JavaPlugin plugin) { + plugin.getServer().getPluginManager().registerEvents(this, plugin); + } + + @EventHandler + public void onJoin(PlayerJoinEvent event) { + event.getPlayer().setLevel(2026); + } +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml new file mode 100644 index 0000000..f4e290c --- /dev/null +++ b/src/main/resources/plugin.yml @@ -0,0 +1,20 @@ +name: MiningMan +version: '1.0' +main: ch.bensuisse.miningman.MiningMan +api-version: '1.21' +authors: [BenSuisse] +depend: + - LuckPerms + +commands: + announce: + usage: /announce + permission: miningman.announce + discord: + usage: /discord + dc: + usage: /dc + clearchat: + usage: /clearchat + aliases: [cc] + permission: miningman.clearchat diff --git a/target/classes/ch/bensuisse/miningman/MiningMan.class b/target/classes/ch/bensuisse/miningman/MiningMan.class new file mode 100644 index 0000000..b68846f Binary files /dev/null and b/target/classes/ch/bensuisse/miningman/MiningMan.class differ diff --git a/target/classes/ch/bensuisse/miningman/api/ColorUtil.class b/target/classes/ch/bensuisse/miningman/api/ColorUtil.class new file mode 100644 index 0000000..3767f88 Binary files /dev/null and b/target/classes/ch/bensuisse/miningman/api/ColorUtil.class differ diff --git a/target/classes/ch/bensuisse/miningman/commands/SocialCommands.class b/target/classes/ch/bensuisse/miningman/commands/SocialCommands.class new file mode 100644 index 0000000..e4b6cc1 Binary files /dev/null and b/target/classes/ch/bensuisse/miningman/commands/SocialCommands.class differ diff --git a/target/classes/ch/bensuisse/miningman/features/announce/AnnounceCommand$1.class b/target/classes/ch/bensuisse/miningman/features/announce/AnnounceCommand$1.class new file mode 100644 index 0000000..0efda2a Binary files /dev/null and b/target/classes/ch/bensuisse/miningman/features/announce/AnnounceCommand$1.class differ diff --git a/target/classes/ch/bensuisse/miningman/features/announce/AnnounceCommand.class b/target/classes/ch/bensuisse/miningman/features/announce/AnnounceCommand.class new file mode 100644 index 0000000..06fe333 Binary files /dev/null and b/target/classes/ch/bensuisse/miningman/features/announce/AnnounceCommand.class differ diff --git a/target/classes/ch/bensuisse/miningman/features/chat/ChatListener.class b/target/classes/ch/bensuisse/miningman/features/chat/ChatListener.class new file mode 100644 index 0000000..a952f02 Binary files /dev/null and b/target/classes/ch/bensuisse/miningman/features/chat/ChatListener.class differ diff --git a/target/classes/ch/bensuisse/miningman/features/chat/ClearChatCommand.class b/target/classes/ch/bensuisse/miningman/features/chat/ClearChatCommand.class new file mode 100644 index 0000000..0d38201 Binary files /dev/null and b/target/classes/ch/bensuisse/miningman/features/chat/ClearChatCommand.class differ diff --git a/target/classes/ch/bensuisse/miningman/features/general/ConnectionListener.class b/target/classes/ch/bensuisse/miningman/features/general/ConnectionListener.class new file mode 100644 index 0000000..9c82bae Binary files /dev/null and b/target/classes/ch/bensuisse/miningman/features/general/ConnectionListener.class differ diff --git a/target/classes/ch/bensuisse/miningman/features/tablist/TablistService.class b/target/classes/ch/bensuisse/miningman/features/tablist/TablistService.class new file mode 100644 index 0000000..b8ba4c7 Binary files /dev/null and b/target/classes/ch/bensuisse/miningman/features/tablist/TablistService.class differ diff --git a/target/classes/ch/bensuisse/miningman/managers/JoinManager.class b/target/classes/ch/bensuisse/miningman/managers/JoinManager.class new file mode 100644 index 0000000..a590c65 Binary files /dev/null and b/target/classes/ch/bensuisse/miningman/managers/JoinManager.class differ diff --git a/target/classes/plugin.yml b/target/classes/plugin.yml new file mode 100644 index 0000000..f4e290c --- /dev/null +++ b/target/classes/plugin.yml @@ -0,0 +1,20 @@ +name: MiningMan +version: '1.0' +main: ch.bensuisse.miningman.MiningMan +api-version: '1.21' +authors: [BenSuisse] +depend: + - LuckPerms + +commands: + announce: + usage: /announce + permission: miningman.announce + discord: + usage: /discord + dc: + usage: /dc + clearchat: + usage: /clearchat + aliases: [cc] + permission: miningman.clearchat diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst new file mode 100644 index 0000000..5b3348a --- /dev/null +++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst @@ -0,0 +1,10 @@ +ch\bensuisse\miningman\features\announce\AnnounceCommand.class +ch\bensuisse\miningman\MiningMan.class +ch\bensuisse\miningman\commands\SocialCommands.class +ch\bensuisse\miningman\features\tablist\TablistService.class +ch\bensuisse\miningman\api\ColorUtil.class +ch\bensuisse\miningman\managers\JoinManager.class +ch\bensuisse\miningman\features\chat\ClearChatCommand.class +ch\bensuisse\miningman\features\announce\AnnounceCommand$1.class +ch\bensuisse\miningman\features\chat\ChatListener.class +ch\bensuisse\miningman\features\general\ConnectionListener.class diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst new file mode 100644 index 0000000..bb975b2 --- /dev/null +++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst @@ -0,0 +1,9 @@ +C:\Users\benib\Dev\Intellij\Minecraft\LunaraSystem\src\main\java\ch\bensuisse\miningman\api\ColorUtil.java +C:\Users\benib\Dev\Intellij\Minecraft\LunaraSystem\src\main\java\ch\bensuisse\miningman\commands\SocialCommands.java +C:\Users\benib\Dev\Intellij\Minecraft\LunaraSystem\src\main\java\ch\bensuisse\miningman\features\announce\AnnounceCommand.java +C:\Users\benib\Dev\Intellij\Minecraft\LunaraSystem\src\main\java\ch\bensuisse\miningman\features\chat\ChatListener.java +C:\Users\benib\Dev\Intellij\Minecraft\LunaraSystem\src\main\java\ch\bensuisse\miningman\features\chat\ClearChatCommand.java +C:\Users\benib\Dev\Intellij\Minecraft\LunaraSystem\src\main\java\ch\bensuisse\miningman\features\general\ConnectionListener.java +C:\Users\benib\Dev\Intellij\Minecraft\LunaraSystem\src\main\java\ch\bensuisse\miningman\features\tablist\TablistService.java +C:\Users\benib\Dev\Intellij\Minecraft\LunaraSystem\src\main\java\ch\bensuisse\miningman\managers\JoinManager.java +C:\Users\benib\Dev\Intellij\Minecraft\LunaraSystem\src\main\java\ch\bensuisse\miningman\MiningMan.java