From 3092336ea5e2cb89fdfcf0bc508262649f550c4d Mon Sep 17 00:00:00 2001 From: M_Viper Date: Tue, 3 Feb 2026 22:24:03 +0100 Subject: [PATCH] Update from Git Manager GUI --- .../mc/titlemanager/TitleManagerPlugin.java | 508 ++++++++++++++++++ .../titlemanager/api/v2/TitleManagerAPI.java | 140 +++++ .../api/v2/animation/Animation.java | 17 + .../api/v2/animation/AnimationPart.java | 28 + .../internal/commands/TMCommand.java | 51 ++ .../DaggerTitleManagerComponent.java | 85 +++ .../components/TitleManagerComponent.java | 24 + .../internal/config/ConfigMigration.java | 18 + .../internal/config/PrettyConfig.java | 37 ++ .../internal/config/TMConfigMain.java | 16 + .../animation/StandardAnimationFrame.java | 38 ++ .../internal/placeholder/CombatLogXHook.java | 11 + .../internal/reflections/NMSManager.java | 39 ++ .../services/TitleManagerService.java | 22 + .../services/actionbar/ActionbarService.java | 38 ++ .../services/animation/AnimationsService.java | 76 +++ .../placeholder/PlaceholderService.java | 27 + .../playerlist/PlayerListService.java | 73 +++ .../scoreboard/ScoreboardService.java | 85 +++ .../services/script/ScriptService.java | 25 + .../internal/services/title/TitleService.java | 86 +++ .../resources/animations/left-to-right.txt | 18 + .../resources/animations/right-to-left.txt | 18 + src/main/resources/config.yml | 363 +++++++++++++ src/main/resources/playerinfo.sql | 4 + src/main/resources/plugin.yml | 34 ++ src/main/resources/titlemanager_engine.js | 61 +++ 27 files changed, 1942 insertions(+) create mode 100644 src/main/java/io/mviper/mc/titlemanager/TitleManagerPlugin.java create mode 100644 src/main/java/io/mviper/mc/titlemanager/api/v2/TitleManagerAPI.java create mode 100644 src/main/java/io/mviper/mc/titlemanager/api/v2/animation/Animation.java create mode 100644 src/main/java/io/mviper/mc/titlemanager/api/v2/animation/AnimationPart.java create mode 100644 src/main/java/io/mviper/mc/titlemanager/internal/commands/TMCommand.java create mode 100644 src/main/java/io/mviper/mc/titlemanager/internal/components/DaggerTitleManagerComponent.java create mode 100644 src/main/java/io/mviper/mc/titlemanager/internal/components/TitleManagerComponent.java create mode 100644 src/main/java/io/mviper/mc/titlemanager/internal/config/ConfigMigration.java create mode 100644 src/main/java/io/mviper/mc/titlemanager/internal/config/PrettyConfig.java create mode 100644 src/main/java/io/mviper/mc/titlemanager/internal/config/TMConfigMain.java create mode 100644 src/main/java/io/mviper/mc/titlemanager/internal/model/animation/StandardAnimationFrame.java create mode 100644 src/main/java/io/mviper/mc/titlemanager/internal/placeholder/CombatLogXHook.java create mode 100644 src/main/java/io/mviper/mc/titlemanager/internal/reflections/NMSManager.java create mode 100644 src/main/java/io/mviper/mc/titlemanager/internal/services/TitleManagerService.java create mode 100644 src/main/java/io/mviper/mc/titlemanager/internal/services/actionbar/ActionbarService.java create mode 100644 src/main/java/io/mviper/mc/titlemanager/internal/services/animation/AnimationsService.java create mode 100644 src/main/java/io/mviper/mc/titlemanager/internal/services/placeholder/PlaceholderService.java create mode 100644 src/main/java/io/mviper/mc/titlemanager/internal/services/playerlist/PlayerListService.java create mode 100644 src/main/java/io/mviper/mc/titlemanager/internal/services/scoreboard/ScoreboardService.java create mode 100644 src/main/java/io/mviper/mc/titlemanager/internal/services/script/ScriptService.java create mode 100644 src/main/java/io/mviper/mc/titlemanager/internal/services/title/TitleService.java create mode 100644 src/main/resources/animations/left-to-right.txt create mode 100644 src/main/resources/animations/right-to-left.txt create mode 100644 src/main/resources/config.yml create mode 100644 src/main/resources/playerinfo.sql create mode 100644 src/main/resources/plugin.yml create mode 100644 src/main/resources/titlemanager_engine.js diff --git a/src/main/java/io/mviper/mc/titlemanager/TitleManagerPlugin.java b/src/main/java/io/mviper/mc/titlemanager/TitleManagerPlugin.java new file mode 100644 index 0000000..327da00 --- /dev/null +++ b/src/main/java/io/mviper/mc/titlemanager/TitleManagerPlugin.java @@ -0,0 +1,508 @@ +package io.mviper.mc.titlemanager; + +import io.mviper.mc.titlemanager.api.v2.TitleManagerAPI; +import io.mviper.mc.titlemanager.api.v2.animation.Animation; +import io.mviper.mc.titlemanager.api.v2.animation.AnimationPart; +import io.mviper.mc.titlemanager.internal.commands.TMCommand; +import io.mviper.mc.titlemanager.internal.components.DaggerTitleManagerComponent; +import io.mviper.mc.titlemanager.internal.components.TitleManagerComponent; +import io.mviper.mc.titlemanager.internal.config.ConfigMigration; +import io.mviper.mc.titlemanager.internal.config.PrettyConfig; +import io.mviper.mc.titlemanager.internal.config.TMConfigMain; +import io.mviper.mc.titlemanager.internal.model.animation.StandardAnimationFrame; +import io.mviper.mc.titlemanager.internal.placeholder.CombatLogXHook; +import io.mviper.mc.titlemanager.internal.reflections.NMSManager; +import io.mviper.mc.titlemanager.internal.services.TitleManagerService; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.plugin.java.JavaPlugin; + +import java.io.File; +import java.util.List; +import java.util.Objects; + +/** + * TitleManager - Main plugin class for Minecraft 1.21.x + * A powerful title/subtitle manager plugin + */ +public class TitleManagerPlugin extends JavaPlugin implements TitleManagerAPI { + private PrettyConfig conf = null; + private TMConfigMain tmConfig; + private TitleManagerComponent titleManagerComponent; + private TitleManagerService titleManagerService; + + @Override + public void onEnable() { + saveDefaultConfig(); + updateConfig(); + + titleManagerComponent = DaggerTitleManagerComponent.create(); + titleManagerService = titleManagerComponent.titleManagerService(); + + titleManagerService.start(); + + CombatLogXHook.infoLog(); + + debug("Registering commands"); + registerCommands(); + + debug("Registering BungeeCord messengers"); + registerBungeeCord(); + + debug("Using MC version: %s | NMS Index: %d".formatted(NMSManager.getServerVersion(), NMSManager.getVersionIndex())); + } + + @Override + public void onDisable() { + if (titleManagerService != null) { + titleManagerService.stop(); + } + } + + @Override + public FileConfiguration getConfig() { + if (conf == null) { + reloadConfig(); + } + return conf; + } + + @Override + public void saveConfig() { + try { + Objects.requireNonNull(conf).save(new File(Objects.requireNonNull(getDataFolder()), "config.yml")); + } catch (Exception e) { + getLogger().severe("Could not save config: " + e.getMessage()); + } + } + + @Override + public void reloadConfig() { + File configFile = new File(Objects.requireNonNull(getDataFolder()), "config.yml"); + conf = new PrettyConfig(configFile); + tmConfig = new TMConfigMain(conf); + } + + public void reloadPlugin() { + onDisable(); + + saveDefaultConfig(); + reloadConfig(); + + titleManagerComponent = DaggerTitleManagerComponent.create(); + titleManagerService = titleManagerComponent.titleManagerService(); + + titleManagerService.start(); + } + + private void updateConfig() { + ConfigMigration migration = new ConfigMigration(this); + migration.updateConfig(); + } + + private void registerBungeeCord() { + getServer().getMessenger().registerOutgoingPluginChannel(this, "BungeeCord"); + } + + private void registerCommands() { + if (getCommand("tm") != null) { + TMCommand tmCommand = new TMCommand(this); + getCommand("tm").setExecutor(tmCommand); + getCommand("tm").setTabCompleter(tmCommand); + } + } + + // --- TitleManagerAPI Implementation --- + + @Override + public String replaceText(Player player, String text) { + return titleManagerComponent.placeholderService().replaceText(player, text); + } + + @Override + public boolean containsPlaceholders(String text) { + return titleManagerComponent.placeholderService().containsPlaceholders(text); + } + + @Override + public boolean containsPlaceholder(String text, String placeholder) { + return titleManagerComponent.placeholderService().containsPlaceholder(text, placeholder); + } + + @Override + public boolean containsAnimations(String text) { + return titleManagerComponent.animationsService().containsAnimations(text); + } + + @Override + public boolean containsAnimation(String text, String animation) { + return titleManagerComponent.animationsService().containsAnimation(text, animation); + } + + @Override + public Object getRegisteredAnimations() { + return titleManagerComponent.animationsService().getAnimations(); + } + + @Override + public Object getRegisteredScripts() { + return titleManagerComponent.scriptService().getScripts(); + } + + @Override + public void addAnimation(String id, Animation animation) { + titleManagerComponent.animationsService().addAnimation(id, animation); + } + + @Override + public void removeAnimation(String id) { + titleManagerComponent.animationsService().removeAnimation(id); + } + + @Override + public Object toTitleAnimation(Animation animation, Player player, boolean withPlaceholders) { + return titleManagerComponent.titleService().createTitleSendableAnimation(animation, player, withPlaceholders); + } + + @Override + public Object toTitleAnimation(List> parts, Player player, boolean withPlaceholders) { + return titleManagerComponent.titleService().createTitleSendableAnimation(parts, player, withPlaceholders); + } + + @Override + public Object toSubtitleAnimation(Animation animation, Player player, boolean withPlaceholders) { + return titleManagerComponent.titleService().createSubtitleSendableAnimation(animation, player, withPlaceholders); + } + + @Override + public Object toSubtitleAnimation(List> parts, Player player, boolean withPlaceholders) { + return titleManagerComponent.titleService().createSubtitleSendableAnimation(parts, player, withPlaceholders); + } + + @Override + public Object toActionbarAnimation(Animation animation, Player player, boolean withPlaceholders) { + return titleManagerComponent.actionbarService().createActionbarSendableAnimation(animation, player, withPlaceholders); + } + + @Override + public Object toActionbarAnimation(List> parts, Player player, boolean withPlaceholders) { + return titleManagerComponent.actionbarService().createActionbarSendableAnimation(parts, player, withPlaceholders); + } + + @Override + public Object toHeaderAnimation(Animation animation, Player player, boolean withPlaceholders) { + return titleManagerComponent.playerListService().createHeaderSendableAnimation(animation, player, withPlaceholders); + } + + @Override + public Object toHeaderAnimation(List> parts, Player player, boolean withPlaceholders) { + return titleManagerComponent.playerListService().createHeaderSendableAnimation(parts, player, withPlaceholders); + } + + @Override + public Object toFooterAnimation(Animation animation, Player player, boolean withPlaceholders) { + return titleManagerComponent.playerListService().createFooterSendableAnimation(animation, player, withPlaceholders); + } + + @Override + public Object toFooterAnimation(List> parts, Player player, boolean withPlaceholders) { + return titleManagerComponent.playerListService().createFooterSendableAnimation(parts, player, withPlaceholders); + } + + @Override + public Object toScoreboardTitleAnimation(Animation animation, Player player, boolean withPlaceholders) { + return titleManagerComponent.scoreboardService().createScoreboardTitleSendableAnimation(animation, player, withPlaceholders); + } + + @Override + public Object toScoreboardTitleAnimation(List> parts, Player player, boolean withPlaceholders) { + return titleManagerComponent.scoreboardService().createScoreboardTitleSendableAnimation(parts, player, withPlaceholders); + } + + @Override + public Object toScoreboardValueAnimation(Animation animation, Player player, int index, boolean withPlaceholders) { + return titleManagerComponent.scoreboardService().createScoreboardValueSendableAnimation(animation, player, index, withPlaceholders); + } + + @Override + public Object toScoreboardValueAnimation(List> parts, Player player, int index, boolean withPlaceholders) { + return titleManagerComponent.scoreboardService().createScoreboardValueSendableAnimation(parts, player, index, withPlaceholders); + } + + @Override + public AnimationPart toAnimationPart(String text) { + return new AnimationPart<>(() -> text); + } + + @Override + public AnimationPart toAnimationPart(Animation animation) { + return new AnimationPart<>(() -> animation); + } + + @Override + public List> toAnimationParts(String text) { + return titleManagerComponent.animationsService().textToAnimationParts(text); + } + + @Override + public Object createAnimationFrame(String text, int fadeIn, int stay, int fadeOut) { + return new StandardAnimationFrame(text, fadeIn, stay, fadeOut); + } + + @Override + public Animation fromText(String... frames) { + return titleManagerComponent.animationsService().createAnimationFromTextLines(frames); + } + + @Override + public Animation fromTextFile(File file) { + return titleManagerComponent.animationsService().createAnimationFromTextFile(file); + } + + @Override + public Object fromJavaScript(String name, String input) { + return titleManagerComponent.scriptService().getScriptAnimation(name, input, true); + } + + @Override + public void sendTitle(Player player, String title) { + titleManagerComponent.titleService().sendTitle(player, title, false); + } + + @Override + public void sendTitle(Player player, String title, int fadeIn, int stay, int fadeOut) { + titleManagerComponent.titleService().sendTitle(player, title, fadeIn, stay, fadeOut, false); + } + + @Override + public void sendTitleWithPlaceholders(Player player, String title) { + titleManagerComponent.titleService().sendTitle(player, title, true); + } + + @Override + public void sendTitleWithPlaceholders(Player player, String title, int fadeIn, int stay, int fadeOut) { + titleManagerComponent.titleService().sendTitle(player, title, fadeIn, stay, fadeOut, true); + } + + @Override + public void sendProcessedTitle(Player player, String title, int fadeIn, int stay, int fadeOut) { + titleManagerComponent.titleService().sendProcessedTitle(player, title, fadeIn, stay, fadeOut); + } + + @Override + public void sendSubtitle(Player player, String subtitle) { + titleManagerComponent.titleService().sendSubtitle(player, subtitle, false); + } + + @Override + public void sendSubtitle(Player player, String subtitle, int fadeIn, int stay, int fadeOut) { + titleManagerComponent.titleService().sendSubtitle(player, subtitle, fadeIn, stay, fadeOut, false); + } + + @Override + public void sendSubtitleWithPlaceholders(Player player, String subtitle) { + titleManagerComponent.titleService().sendSubtitle(player, subtitle, true); + } + + @Override + public void sendSubtitleWithPlaceholders(Player player, String subtitle, int fadeIn, int stay, int fadeOut) { + titleManagerComponent.titleService().sendSubtitle(player, subtitle, fadeIn, stay, fadeOut, true); + } + + @Override + public void sendProcessedSubtitle(Player player, String subtitle, int fadeIn, int stay, int fadeOut) { + titleManagerComponent.titleService().sendProcessedSubtitle(player, subtitle, fadeIn, stay, fadeOut); + } + + @Override + public void sendTitles(Player player, String title, String subtitle) { + titleManagerComponent.titleService().sendTitles(player, title, subtitle, false); + } + + @Override + public void sendTitles(Player player, String title, String subtitle, int fadeIn, int stay, int fadeOut) { + titleManagerComponent.titleService().sendTitles(player, title, subtitle, fadeIn, stay, fadeOut, false); + } + + @Override + public void sendTitlesWithPlaceholders(Player player, String title, String subtitle) { + titleManagerComponent.titleService().sendTitles(player, title, subtitle, true); + } + + @Override + public void sendTitlesWithPlaceholders(Player player, String title, String subtitle, int fadeIn, int stay, int fadeOut) { + titleManagerComponent.titleService().sendTitles(player, title, subtitle, fadeIn, stay, fadeOut, true); + } + + @Override + public void sendProcessedTitles(Player player, String title, String subtitle, int fadeIn, int stay, int fadeOut) { + titleManagerComponent.titleService().sendProcessedTitle(player, title, fadeIn, stay, fadeOut); + titleManagerComponent.titleService().sendProcessedSubtitle(player, subtitle, fadeIn, stay, fadeOut); + } + + @Override + public void sendTimings(Player player, int fadeIn, int stay, int fadeOut) { + titleManagerComponent.titleService().sendTimings(player, fadeIn, stay, fadeOut); + } + + @Override + public void clearTitle(Player player) { + titleManagerComponent.titleService().clearTitle(player); + } + + @Override + public void clearSubtitle(Player player) { + titleManagerComponent.titleService().clearSubtitle(player); + } + + @Override + public void clearTitles(Player player) { + titleManagerComponent.titleService().clearTitles(player); + } + + @Override + public void sendActionbar(Player player, String text) { + titleManagerComponent.actionbarService().sendActionbar(player, text, false); + } + + @Override + public void sendActionbarWithPlaceholders(Player player, String text) { + titleManagerComponent.actionbarService().sendActionbar(player, text, true); + } + + @Override + public void sendProcessedActionbar(Player player, String text) { + titleManagerComponent.actionbarService().sendProcessedActionbar(player, text); + } + + @Override + public void clearActionbar(Player player) { + titleManagerComponent.actionbarService().clearActionbar(player); + } + + @Override + public void setHeader(Player player, String header) { + titleManagerComponent.playerListService().setHeader(player, header, false); + } + + @Override + public void setHeaderWithPlaceholders(Player player, String header) { + titleManagerComponent.playerListService().setHeader(player, header, true); + } + + @Override + public void setProcessedHeader(Player player, String header) { + titleManagerComponent.playerListService().setProcessedHeader(player, header); + } + + @Override + public String getHeader(Player player) { + return titleManagerComponent.playerListService().getHeader(player); + } + + @Override + public void setFooter(Player player, String footer) { + titleManagerComponent.playerListService().setFooter(player, footer, false); + } + + @Override + public void setFooterWithPlaceholders(Player player, String footer) { + titleManagerComponent.playerListService().setFooter(player, footer, true); + } + + @Override + public void setProcessedFooter(Player player, String footer) { + titleManagerComponent.playerListService().setProcessedFooter(player, footer); + } + + @Override + public String getFooter(Player player) { + return titleManagerComponent.playerListService().getFooter(player); + } + + @Override + public void setHeaderAndFooter(Player player, String header, String footer) { + titleManagerComponent.playerListService().setHeaderAndFooter(player, header, footer, false); + } + + @Override + public void setHeaderAndFooterWithPlaceholders(Player player, String header, String footer) { + titleManagerComponent.playerListService().setHeaderAndFooter(player, header, footer, true); + } + + @Override + public void setProcessedHeaderAndFooter(Player player, String header, String footer) { + titleManagerComponent.playerListService().setProcessedHeaderAndFooter(player, header, footer); + } + + @Override + public void giveScoreboard(Player player) { + titleManagerComponent.scoreboardService().giveScoreboard(player); + } + + @Override + public void giveDefaultScoreboard(Player player) { + titleManagerComponent.scoreboardService().giveDefaultScoreboard(player); + } + + @Override + public void removeScoreboard(Player player) { + titleManagerComponent.scoreboardService().removeScoreboard(player); + } + + @Override + public boolean hasScoreboard(Player player) { + return titleManagerComponent.scoreboardService().hasScoreboard(player); + } + + @Override + public void setScoreboardTitle(Player player, String title) { + titleManagerComponent.scoreboardService().setScoreboardTitle(player, title, false); + } + + @Override + public void setScoreboardTitleWithPlaceholders(Player player, String title) { + titleManagerComponent.scoreboardService().setScoreboardTitle(player, title, true); + } + + @Override + public void setProcessedScoreboardTitle(Player player, String title) { + titleManagerComponent.scoreboardService().setProcessedScoreboardTitle(player, title); + } + + @Override + public String getScoreboardTitle(Player player) { + return titleManagerComponent.scoreboardService().getScoreboardTitle(player); + } + + @Override + public void setScoreboardValue(Player player, int index, String value) { + titleManagerComponent.scoreboardService().setScoreboardValue(player, index, value, false); + } + + @Override + public void setScoreboardValueWithPlaceholders(Player player, int index, String value) { + titleManagerComponent.scoreboardService().setScoreboardValue(player, index, value, true); + } + + @Override + public void setProcessedScoreboardValue(Player player, int index, String value) { + titleManagerComponent.scoreboardService().setProcessedScoreboardValue(player, index, value); + } + + @Override + public String getScoreboardValue(Player player, int index) { + return titleManagerComponent.scoreboardService().getScoreboardValue(player, index); + } + + @Override + public void removeScoreboardValue(Player player, int index) { + titleManagerComponent.scoreboardService().removeScoreboardValue(player, index); + } + + // --- Utility Methods --- + + protected void debug(String message) { + getLogger().fine(message); + } +} diff --git a/src/main/java/io/mviper/mc/titlemanager/api/v2/TitleManagerAPI.java b/src/main/java/io/mviper/mc/titlemanager/api/v2/TitleManagerAPI.java new file mode 100644 index 0000000..c3ac42a --- /dev/null +++ b/src/main/java/io/mviper/mc/titlemanager/api/v2/TitleManagerAPI.java @@ -0,0 +1,140 @@ +package io.mviper.mc.titlemanager.api.v2; + +import io.mviper.mc.titlemanager.api.v2.animation.Animation; +import io.mviper.mc.titlemanager.api.v2.animation.AnimationPart; +import org.bukkit.entity.Player; + +import java.io.File; +import java.util.List; + +/** + * TitleManagerAPI - Public API for TitleManager plugin + * Provides methods for managing titles, subtitles, actionbars, player list headers/footers, and scoreboards + */ +public interface TitleManagerAPI { + + // Placeholder Methods + String replaceText(Player player, String text); + boolean containsPlaceholders(String text); + boolean containsPlaceholder(String text, String placeholder); + + // Animation Methods + boolean containsAnimations(String text); + boolean containsAnimation(String text, String animation); + Object getRegisteredAnimations(); + Object getRegisteredScripts(); + void addAnimation(String id, Animation animation); + void removeAnimation(String id); + + // Title Animation Methods + Object toTitleAnimation(Animation animation, Player player, boolean withPlaceholders); + Object toTitleAnimation(List> parts, Player player, boolean withPlaceholders); + + // Subtitle Animation Methods + Object toSubtitleAnimation(Animation animation, Player player, boolean withPlaceholders); + Object toSubtitleAnimation(List> parts, Player player, boolean withPlaceholders); + + // Actionbar Animation Methods + Object toActionbarAnimation(Animation animation, Player player, boolean withPlaceholders); + Object toActionbarAnimation(List> parts, Player player, boolean withPlaceholders); + + // Header Animation Methods + Object toHeaderAnimation(Animation animation, Player player, boolean withPlaceholders); + Object toHeaderAnimation(List> parts, Player player, boolean withPlaceholders); + + // Footer Animation Methods + Object toFooterAnimation(Animation animation, Player player, boolean withPlaceholders); + Object toFooterAnimation(List> parts, Player player, boolean withPlaceholders); + + // Scoreboard Title Animation Methods + Object toScoreboardTitleAnimation(Animation animation, Player player, boolean withPlaceholders); + Object toScoreboardTitleAnimation(List> parts, Player player, boolean withPlaceholders); + + // Scoreboard Value Animation Methods + Object toScoreboardValueAnimation(Animation animation, Player player, int index, boolean withPlaceholders); + Object toScoreboardValueAnimation(List> parts, Player player, int index, boolean withPlaceholders); + + // Animation Part Methods + AnimationPart toAnimationPart(String text); + AnimationPart toAnimationPart(Animation animation); + List> toAnimationParts(String text); + + // Animation Frame Methods + Object createAnimationFrame(String text, int fadeIn, int stay, int fadeOut); + + // Animation Creation Methods + Animation fromText(String... frames); + Animation fromTextFile(File file); + Object fromJavaScript(String name, String input); + + // Title Methods + void sendTitle(Player player, String title); + void sendTitle(Player player, String title, int fadeIn, int stay, int fadeOut); + void sendTitleWithPlaceholders(Player player, String title); + void sendTitleWithPlaceholders(Player player, String title, int fadeIn, int stay, int fadeOut); + void sendProcessedTitle(Player player, String title, int fadeIn, int stay, int fadeOut); + + // Subtitle Methods + void sendSubtitle(Player player, String subtitle); + void sendSubtitle(Player player, String subtitle, int fadeIn, int stay, int fadeOut); + void sendSubtitleWithPlaceholders(Player player, String subtitle); + void sendSubtitleWithPlaceholders(Player player, String subtitle, int fadeIn, int stay, int fadeOut); + void sendProcessedSubtitle(Player player, String subtitle, int fadeIn, int stay, int fadeOut); + + // Title & Subtitle Methods + void sendTitles(Player player, String title, String subtitle); + void sendTitles(Player player, String title, String subtitle, int fadeIn, int stay, int fadeOut); + void sendTitlesWithPlaceholders(Player player, String title, String subtitle); + void sendTitlesWithPlaceholders(Player player, String title, String subtitle, int fadeIn, int stay, int fadeOut); + void sendProcessedTitles(Player player, String title, String subtitle, int fadeIn, int stay, int fadeOut); + + // Title Timing Methods + void sendTimings(Player player, int fadeIn, int stay, int fadeOut); + + // Clear Title Methods + void clearTitle(Player player); + void clearSubtitle(Player player); + void clearTitles(Player player); + + // Actionbar Methods + void sendActionbar(Player player, String text); + void sendActionbarWithPlaceholders(Player player, String text); + void sendProcessedActionbar(Player player, String text); + void clearActionbar(Player player); + + // Header Methods + void setHeader(Player player, String header); + void setHeaderWithPlaceholders(Player player, String header); + void setProcessedHeader(Player player, String header); + String getHeader(Player player); + + // Footer Methods + void setFooter(Player player, String footer); + void setFooterWithPlaceholders(Player player, String footer); + void setProcessedFooter(Player player, String footer); + String getFooter(Player player); + + // Header & Footer Methods + void setHeaderAndFooter(Player player, String header, String footer); + void setHeaderAndFooterWithPlaceholders(Player player, String header, String footer); + void setProcessedHeaderAndFooter(Player player, String header, String footer); + + // Scoreboard Methods + void giveScoreboard(Player player); + void giveDefaultScoreboard(Player player); + void removeScoreboard(Player player); + boolean hasScoreboard(Player player); + + // Scoreboard Title Methods + void setScoreboardTitle(Player player, String title); + void setScoreboardTitleWithPlaceholders(Player player, String title); + void setProcessedScoreboardTitle(Player player, String title); + String getScoreboardTitle(Player player); + + // Scoreboard Value Methods + void setScoreboardValue(Player player, int index, String value); + void setScoreboardValueWithPlaceholders(Player player, int index, String value); + void setProcessedScoreboardValue(Player player, int index, String value); + String getScoreboardValue(Player player, int index); + void removeScoreboardValue(Player player, int index); +} diff --git a/src/main/java/io/mviper/mc/titlemanager/api/v2/animation/Animation.java b/src/main/java/io/mviper/mc/titlemanager/api/v2/animation/Animation.java new file mode 100644 index 0000000..207e613 --- /dev/null +++ b/src/main/java/io/mviper/mc/titlemanager/api/v2/animation/Animation.java @@ -0,0 +1,17 @@ +package io.mviper.mc.titlemanager.api.v2.animation; + +/** + * Animation interface for TitleManager + * Represents an animation with parts and timing + */ +public interface Animation { + /** + * Get the animation parts + */ + java.util.List getParts(); + + /** + * Get the default duration of the animation + */ + int getDuration(); +} diff --git a/src/main/java/io/mviper/mc/titlemanager/api/v2/animation/AnimationPart.java b/src/main/java/io/mviper/mc/titlemanager/api/v2/animation/AnimationPart.java new file mode 100644 index 0000000..6b9faa4 --- /dev/null +++ b/src/main/java/io/mviper/mc/titlemanager/api/v2/animation/AnimationPart.java @@ -0,0 +1,28 @@ +package io.mviper.mc.titlemanager.api.v2.animation; + +/** + * AnimationPart - Represents a part of an animation + * @param The type of content this animation part contains + */ +public class AnimationPart { + private final AnimationPartSupplier supplier; + + public AnimationPart(AnimationPartSupplier supplier) { + this.supplier = supplier; + } + + /** + * Get the content of this animation part + */ + public T get() { + return supplier.get(); + } + + /** + * Functional interface for animation part suppliers + */ + @FunctionalInterface + public interface AnimationPartSupplier { + T get(); + } +} diff --git a/src/main/java/io/mviper/mc/titlemanager/internal/commands/TMCommand.java b/src/main/java/io/mviper/mc/titlemanager/internal/commands/TMCommand.java new file mode 100644 index 0000000..b4d84bd --- /dev/null +++ b/src/main/java/io/mviper/mc/titlemanager/internal/commands/TMCommand.java @@ -0,0 +1,51 @@ +package io.mviper.mc.titlemanager.internal.commands; + +import io.mviper.mc.titlemanager.TitleManagerPlugin; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; + +import java.util.List; + +/** + * Main TitleManager command handler + */ +public class TMCommand implements CommandExecutor, TabCompleter { + private final TitleManagerPlugin plugin; + + public TMCommand(TitleManagerPlugin plugin) { + this.plugin = plugin; + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (args.length == 0) { + sender.sendMessage("§cUsage: /tm "); + return true; + } + + String subcommand = args[0].toLowerCase(); + switch (subcommand) { + case "reload": + plugin.reloadPlugin(); + sender.sendMessage("§aPlugin reloaded!"); + return true; + case "help": + sender.sendMessage("§6TitleManager v3.0.0"); + sender.sendMessage("§e/tm reload §7- Reload the plugin"); + return true; + default: + sender.sendMessage("§cUnknown subcommand: " + subcommand); + return false; + } + } + + @Override + public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { + if (args.length == 1) { + return List.of("reload", "help"); + } + return List.of(); + } +} diff --git a/src/main/java/io/mviper/mc/titlemanager/internal/components/DaggerTitleManagerComponent.java b/src/main/java/io/mviper/mc/titlemanager/internal/components/DaggerTitleManagerComponent.java new file mode 100644 index 0000000..7a18ceb --- /dev/null +++ b/src/main/java/io/mviper/mc/titlemanager/internal/components/DaggerTitleManagerComponent.java @@ -0,0 +1,85 @@ +package io.mviper.mc.titlemanager.internal.components; + +import io.mviper.mc.titlemanager.internal.services.TitleManagerService; +import io.mviper.mc.titlemanager.internal.services.placeholder.PlaceholderService; +import io.mviper.mc.titlemanager.internal.services.animation.AnimationsService; +import io.mviper.mc.titlemanager.internal.services.title.TitleService; +import io.mviper.mc.titlemanager.internal.services.actionbar.ActionbarService; +import io.mviper.mc.titlemanager.internal.services.playerlist.PlayerListService; +import io.mviper.mc.titlemanager.internal.services.scoreboard.ScoreboardService; +import io.mviper.mc.titlemanager.internal.services.script.ScriptService; + +/** + * Implementation of TitleManagerComponent + * Manually created instead of using Dagger annotation processing + */ +public class DaggerTitleManagerComponent implements TitleManagerComponent { + private static final DaggerTitleManagerComponent INSTANCE = new DaggerTitleManagerComponent(); + + private final TitleManagerService titleManagerService; + private final PlaceholderService placeholderService; + private final AnimationsService animationsService; + private final TitleService titleService; + private final ActionbarService actionbarService; + private final PlayerListService playerListService; + private final ScoreboardService scoreboardService; + private final ScriptService scriptService; + + private DaggerTitleManagerComponent() { + this.placeholderService = new PlaceholderService(); + this.animationsService = new AnimationsService(); + this.titleService = new TitleService(); + this.actionbarService = new ActionbarService(); + this.playerListService = new PlayerListService(); + this.scoreboardService = new ScoreboardService(); + this.scriptService = new ScriptService(); + this.titleManagerService = new TitleManagerService(); + } + + /** + * Creates a new component instance + */ + public static TitleManagerComponent create() { + return INSTANCE; + } + + @Override + public TitleManagerService titleManagerService() { + return titleManagerService; + } + + @Override + public PlaceholderService placeholderService() { + return placeholderService; + } + + @Override + public AnimationsService animationsService() { + return animationsService; + } + + @Override + public TitleService titleService() { + return titleService; + } + + @Override + public ActionbarService actionbarService() { + return actionbarService; + } + + @Override + public PlayerListService playerListService() { + return playerListService; + } + + @Override + public ScoreboardService scoreboardService() { + return scoreboardService; + } + + @Override + public ScriptService scriptService() { + return scriptService; + } +} diff --git a/src/main/java/io/mviper/mc/titlemanager/internal/components/TitleManagerComponent.java b/src/main/java/io/mviper/mc/titlemanager/internal/components/TitleManagerComponent.java new file mode 100644 index 0000000..dbec1cc --- /dev/null +++ b/src/main/java/io/mviper/mc/titlemanager/internal/components/TitleManagerComponent.java @@ -0,0 +1,24 @@ +package io.mviper.mc.titlemanager.internal.components; + +import io.mviper.mc.titlemanager.internal.services.TitleManagerService; +import io.mviper.mc.titlemanager.internal.services.placeholder.PlaceholderService; +import io.mviper.mc.titlemanager.internal.services.animation.AnimationsService; +import io.mviper.mc.titlemanager.internal.services.title.TitleService; +import io.mviper.mc.titlemanager.internal.services.actionbar.ActionbarService; +import io.mviper.mc.titlemanager.internal.services.playerlist.PlayerListService; +import io.mviper.mc.titlemanager.internal.services.scoreboard.ScoreboardService; +import io.mviper.mc.titlemanager.internal.services.script.ScriptService; + +/** + * TitleManager component interface for dependency injection + */ +public interface TitleManagerComponent { + TitleManagerService titleManagerService(); + PlaceholderService placeholderService(); + AnimationsService animationsService(); + TitleService titleService(); + ActionbarService actionbarService(); + PlayerListService playerListService(); + ScoreboardService scoreboardService(); + ScriptService scriptService(); +} diff --git a/src/main/java/io/mviper/mc/titlemanager/internal/config/ConfigMigration.java b/src/main/java/io/mviper/mc/titlemanager/internal/config/ConfigMigration.java new file mode 100644 index 0000000..763756f --- /dev/null +++ b/src/main/java/io/mviper/mc/titlemanager/internal/config/ConfigMigration.java @@ -0,0 +1,18 @@ +package io.mviper.mc.titlemanager.internal.config; + +import io.mviper.mc.titlemanager.TitleManagerPlugin; + +/** + * Handles config migration and updates + */ +public class ConfigMigration { + private final TitleManagerPlugin plugin; + + public ConfigMigration(TitleManagerPlugin plugin) { + this.plugin = plugin; + } + + public void updateConfig() { + // Perform config migration and updates + } +} diff --git a/src/main/java/io/mviper/mc/titlemanager/internal/config/PrettyConfig.java b/src/main/java/io/mviper/mc/titlemanager/internal/config/PrettyConfig.java new file mode 100644 index 0000000..9196c57 --- /dev/null +++ b/src/main/java/io/mviper/mc/titlemanager/internal/config/PrettyConfig.java @@ -0,0 +1,37 @@ +package io.mviper.mc.titlemanager.internal.config; + +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import java.io.File; +import java.io.IOException; + +/** + * Pretty configuration wrapper for YAML files + */ +public class PrettyConfig extends YamlConfiguration { + private final File file; + + public PrettyConfig(File file) { + this.file = file; + if (file.exists()) { + try { + this.load(file); + } catch (Exception e) { + // Initialize empty config if loading fails + } + } + } + + @Override + public void save(File file) throws IOException { + super.save(file); + } + + public void save() throws IOException { + save(this.file); + } + + public void load() throws Exception { + this.load(this.file); + } +} diff --git a/src/main/java/io/mviper/mc/titlemanager/internal/config/TMConfigMain.java b/src/main/java/io/mviper/mc/titlemanager/internal/config/TMConfigMain.java new file mode 100644 index 0000000..e7b1767 --- /dev/null +++ b/src/main/java/io/mviper/mc/titlemanager/internal/config/TMConfigMain.java @@ -0,0 +1,16 @@ +package io.mviper.mc.titlemanager.internal.config; + +/** + * Main TitleManager configuration + */ +public class TMConfigMain { + private final PrettyConfig config; + + public TMConfigMain(PrettyConfig config) { + this.config = config; + } + + public PrettyConfig getConfig() { + return config; + } +} diff --git a/src/main/java/io/mviper/mc/titlemanager/internal/model/animation/StandardAnimationFrame.java b/src/main/java/io/mviper/mc/titlemanager/internal/model/animation/StandardAnimationFrame.java new file mode 100644 index 0000000..0c7c584 --- /dev/null +++ b/src/main/java/io/mviper/mc/titlemanager/internal/model/animation/StandardAnimationFrame.java @@ -0,0 +1,38 @@ +package io.mviper.mc.titlemanager.internal.model.animation; + +/** + * Standard animation frame implementation + */ +public class StandardAnimationFrame { + private final String text; + private final int fadeIn; + private final int stay; + private final int fadeOut; + + public StandardAnimationFrame(String text, int fadeIn, int stay, int fadeOut) { + this.text = text; + this.fadeIn = fadeIn; + this.stay = stay; + this.fadeOut = fadeOut; + } + + public String getText() { + return text; + } + + public int getFadeIn() { + return fadeIn; + } + + public int getStay() { + return stay; + } + + public int getFadeOut() { + return fadeOut; + } + + public int getDuration() { + return fadeIn + stay + fadeOut; + } +} diff --git a/src/main/java/io/mviper/mc/titlemanager/internal/placeholder/CombatLogXHook.java b/src/main/java/io/mviper/mc/titlemanager/internal/placeholder/CombatLogXHook.java new file mode 100644 index 0000000..f5923b6 --- /dev/null +++ b/src/main/java/io/mviper/mc/titlemanager/internal/placeholder/CombatLogXHook.java @@ -0,0 +1,11 @@ +package io.mviper.mc.titlemanager.internal.placeholder; + +/** + * Hook replacer for CombatLogX + */ +public class CombatLogXHook { + + public static void infoLog() { + // Log info about CombatLogX hook + } +} diff --git a/src/main/java/io/mviper/mc/titlemanager/internal/reflections/NMSManager.java b/src/main/java/io/mviper/mc/titlemanager/internal/reflections/NMSManager.java new file mode 100644 index 0000000..2a32294 --- /dev/null +++ b/src/main/java/io/mviper/mc/titlemanager/internal/reflections/NMSManager.java @@ -0,0 +1,39 @@ +package io.mviper.mc.titlemanager.internal.reflections; + +/** + * NMS Manager for handling NMS (Net.Minecraft.Server) versions + */ +public class NMSManager { + private static volatile String serverVersion = ""; + private static volatile int versionIndex = -1; + + static { + detectServerVersion(); + } + + private static void detectServerVersion() { + try { + String packageName = org.bukkit.Bukkit.getServer().getClass().getPackage().getName(); + serverVersion = packageName.substring(packageName.lastIndexOf(".") + 1); + + // Parse version from string like "v1_21_R1" + if (serverVersion.startsWith("v")) { + String[] parts = serverVersion.substring(1).split("_"); + if (parts.length >= 2) { + versionIndex = Integer.parseInt(parts[0]) * 100 + Integer.parseInt(parts[1]); + } + } + } catch (Exception e) { + serverVersion = "unknown"; + versionIndex = -1; + } + } + + public static String getServerVersion() { + return serverVersion; + } + + public static int getVersionIndex() { + return versionIndex; + } +} diff --git a/src/main/java/io/mviper/mc/titlemanager/internal/services/TitleManagerService.java b/src/main/java/io/mviper/mc/titlemanager/internal/services/TitleManagerService.java new file mode 100644 index 0000000..0cd4ad9 --- /dev/null +++ b/src/main/java/io/mviper/mc/titlemanager/internal/services/TitleManagerService.java @@ -0,0 +1,22 @@ +package io.mviper.mc.titlemanager.internal.services; + +import javax.inject.Inject; + +/** + * Main TitleManager service + * Coordinates all plugin services + */ +public class TitleManagerService { + + @Inject + public TitleManagerService() { + } + + public void start() { + // Initialize all services + } + + public void stop() { + // Cleanup all services + } +} diff --git a/src/main/java/io/mviper/mc/titlemanager/internal/services/actionbar/ActionbarService.java b/src/main/java/io/mviper/mc/titlemanager/internal/services/actionbar/ActionbarService.java new file mode 100644 index 0000000..c9fc467 --- /dev/null +++ b/src/main/java/io/mviper/mc/titlemanager/internal/services/actionbar/ActionbarService.java @@ -0,0 +1,38 @@ +package io.mviper.mc.titlemanager.internal.services.actionbar; + +import io.mviper.mc.titlemanager.api.v2.animation.Animation; +import io.mviper.mc.titlemanager.api.v2.animation.AnimationPart; +import org.bukkit.entity.Player; +import javax.inject.Inject; + +import java.util.List; + +/** + * Service for handling action bar messages + */ +public class ActionbarService { + + @Inject + public ActionbarService() { + } + + public Object createActionbarSendableAnimation(Animation animation, Player player, boolean withPlaceholders) { + return null; + } + + public Object createActionbarSendableAnimation(List> parts, Player player, boolean withPlaceholders) { + return null; + } + + public void sendActionbar(Player player, String text, boolean withPlaceholders) { + // Send actionbar to player + } + + public void sendProcessedActionbar(Player player, String text) { + sendActionbar(player, text, true); + } + + public void clearActionbar(Player player) { + // Clear actionbar + } +} diff --git a/src/main/java/io/mviper/mc/titlemanager/internal/services/animation/AnimationsService.java b/src/main/java/io/mviper/mc/titlemanager/internal/services/animation/AnimationsService.java new file mode 100644 index 0000000..e35793c --- /dev/null +++ b/src/main/java/io/mviper/mc/titlemanager/internal/services/animation/AnimationsService.java @@ -0,0 +1,76 @@ +package io.mviper.mc.titlemanager.internal.services.animation; + +import io.mviper.mc.titlemanager.api.v2.animation.Animation; +import io.mviper.mc.titlemanager.api.v2.animation.AnimationPart; +import javax.inject.Inject; + +import java.io.File; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Service for handling animations + */ +public class AnimationsService { + private final Map animations = new HashMap<>(); + + @Inject + public AnimationsService() { + } + + public boolean containsAnimations(String text) { + return text.contains(""); + } + + public Map getAnimations() { + return animations; + } + + public void addAnimation(String id, Animation animation) { + animations.put(id, animation); + } + + public void removeAnimation(String id) { + animations.remove(id); + } + + public List> textToAnimationParts(String text) { + // Parse text into animation parts + return List.of(); + } + + public Animation createAnimationFromTextLines(String... frames) { + // Create animation from text lines + return new Animation() { + @Override + public java.util.List getParts() { + return java.util.List.of(); + } + + @Override + public int getDuration() { + return 100; + } + }; + } + + public Animation createAnimationFromTextFile(File file) { + // Create animation from file + return new Animation() { + @Override + public java.util.List getParts() { + return java.util.List.of(); + } + + @Override + public int getDuration() { + return 100; + } + }; + } +} diff --git a/src/main/java/io/mviper/mc/titlemanager/internal/services/placeholder/PlaceholderService.java b/src/main/java/io/mviper/mc/titlemanager/internal/services/placeholder/PlaceholderService.java new file mode 100644 index 0000000..9428772 --- /dev/null +++ b/src/main/java/io/mviper/mc/titlemanager/internal/services/placeholder/PlaceholderService.java @@ -0,0 +1,27 @@ +package io.mviper.mc.titlemanager.internal.services.placeholder; + +import org.bukkit.entity.Player; +import javax.inject.Inject; + +/** + * Service for handling placeholders + */ +public class PlaceholderService { + + @Inject + public PlaceholderService() { + } + + public String replaceText(Player player, String text) { + // Replace placeholders in text + return text; + } + + public boolean containsPlaceholders(String text) { + return text.contains("%"); + } + + public boolean containsPlaceholder(String text, String placeholder) { + return text.contains("%" + placeholder + "%"); + } +} diff --git a/src/main/java/io/mviper/mc/titlemanager/internal/services/playerlist/PlayerListService.java b/src/main/java/io/mviper/mc/titlemanager/internal/services/playerlist/PlayerListService.java new file mode 100644 index 0000000..6cc6b6a --- /dev/null +++ b/src/main/java/io/mviper/mc/titlemanager/internal/services/playerlist/PlayerListService.java @@ -0,0 +1,73 @@ +package io.mviper.mc.titlemanager.internal.services.playerlist; + +import io.mviper.mc.titlemanager.api.v2.animation.Animation; +import io.mviper.mc.titlemanager.api.v2.animation.AnimationPart; +import org.bukkit.entity.Player; +import javax.inject.Inject; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Service for handling player list headers and footers + */ +public class PlayerListService { + private final Map headers = new HashMap<>(); + private final Map footers = new HashMap<>(); + + @Inject + public PlayerListService() { + } + + public Object createHeaderSendableAnimation(Animation animation, Player player, boolean withPlaceholders) { + return null; + } + + public Object createHeaderSendableAnimation(List> parts, Player player, boolean withPlaceholders) { + return null; + } + + public Object createFooterSendableAnimation(Animation animation, Player player, boolean withPlaceholders) { + return null; + } + + public Object createFooterSendableAnimation(List> parts, Player player, boolean withPlaceholders) { + return null; + } + + public void setHeader(Player player, String header, boolean withPlaceholders) { + headers.put(player, header); + // Send header to player + } + + public void setProcessedHeader(Player player, String header) { + setHeader(player, header, true); + } + + public String getHeader(Player player) { + return headers.getOrDefault(player, ""); + } + + public void setFooter(Player player, String footer, boolean withPlaceholders) { + footers.put(player, footer); + // Send footer to player + } + + public void setProcessedFooter(Player player, String footer) { + setFooter(player, footer, true); + } + + public String getFooter(Player player) { + return footers.getOrDefault(player, ""); + } + + public void setHeaderAndFooter(Player player, String header, String footer, boolean withPlaceholders) { + setHeader(player, header, withPlaceholders); + setFooter(player, footer, withPlaceholders); + } + + public void setProcessedHeaderAndFooter(Player player, String header, String footer) { + setHeaderAndFooter(player, header, footer, true); + } +} diff --git a/src/main/java/io/mviper/mc/titlemanager/internal/services/scoreboard/ScoreboardService.java b/src/main/java/io/mviper/mc/titlemanager/internal/services/scoreboard/ScoreboardService.java new file mode 100644 index 0000000..d10fa11 --- /dev/null +++ b/src/main/java/io/mviper/mc/titlemanager/internal/services/scoreboard/ScoreboardService.java @@ -0,0 +1,85 @@ +package io.mviper.mc.titlemanager.internal.services.scoreboard; + +import io.mviper.mc.titlemanager.api.v2.animation.Animation; +import io.mviper.mc.titlemanager.api.v2.animation.AnimationPart; +import org.bukkit.entity.Player; +import org.bukkit.scoreboard.Scoreboard; +import org.bukkit.scoreboard.ScoreboardManager; +import javax.inject.Inject; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Service for handling scoreboards + */ +public class ScoreboardService { + private final Map scoreboards = new HashMap<>(); + + @Inject + public ScoreboardService() { + } + + public Object createScoreboardTitleSendableAnimation(Animation animation, Player player, boolean withPlaceholders) { + return null; + } + + public Object createScoreboardTitleSendableAnimation(List> parts, Player player, boolean withPlaceholders) { + return null; + } + + public Object createScoreboardValueSendableAnimation(Animation animation, Player player, int index, boolean withPlaceholders) { + return null; + } + + public Object createScoreboardValueSendableAnimation(List> parts, Player player, int index, boolean withPlaceholders) { + return null; + } + + public void giveScoreboard(Player player) { + // Create and give scoreboard to player + } + + public void giveDefaultScoreboard(Player player) { + // Give default scoreboard to player + } + + public void removeScoreboard(Player player) { + scoreboards.remove(player); + } + + public boolean hasScoreboard(Player player) { + return scoreboards.containsKey(player); + } + + public void setScoreboardTitle(Player player, String title, boolean withPlaceholders) { + // Set scoreboard title + } + + public void setProcessedScoreboardTitle(Player player, String title) { + setScoreboardTitle(player, title, true); + } + + public String getScoreboardTitle(Player player) { + // Get scoreboard title + return ""; + } + + public void setScoreboardValue(Player player, int index, String value, boolean withPlaceholders) { + // Set scoreboard value + } + + public void setProcessedScoreboardValue(Player player, int index, String value) { + setScoreboardValue(player, index, value, true); + } + + public String getScoreboardValue(Player player, int index) { + // Get scoreboard value + return ""; + } + + public void removeScoreboardValue(Player player, int index) { + // Remove scoreboard value + } +} diff --git a/src/main/java/io/mviper/mc/titlemanager/internal/services/script/ScriptService.java b/src/main/java/io/mviper/mc/titlemanager/internal/services/script/ScriptService.java new file mode 100644 index 0000000..872ed17 --- /dev/null +++ b/src/main/java/io/mviper/mc/titlemanager/internal/services/script/ScriptService.java @@ -0,0 +1,25 @@ +package io.mviper.mc.titlemanager.internal.services.script; + +import javax.inject.Inject; +import java.util.HashMap; +import java.util.Map; + +/** + * Service for handling JavaScript scripts + */ +public class ScriptService { + private final Map scripts = new HashMap<>(); + + @Inject + public ScriptService() { + } + + public Map getScripts() { + return scripts; + } + + public Object getScriptAnimation(String name, String input, boolean isJavaScript) { + // Parse and execute JavaScript + return null; + } +} diff --git a/src/main/java/io/mviper/mc/titlemanager/internal/services/title/TitleService.java b/src/main/java/io/mviper/mc/titlemanager/internal/services/title/TitleService.java new file mode 100644 index 0000000..7a1b06e --- /dev/null +++ b/src/main/java/io/mviper/mc/titlemanager/internal/services/title/TitleService.java @@ -0,0 +1,86 @@ +package io.mviper.mc.titlemanager.internal.services.title; + +import io.mviper.mc.titlemanager.api.v2.animation.Animation; +import io.mviper.mc.titlemanager.api.v2.animation.AnimationPart; +import org.bukkit.entity.Player; +import javax.inject.Inject; + +import java.util.List; + +/** + * Service for handling titles and subtitles + */ +public class TitleService { + + @Inject + public TitleService() { + } + + public Object createTitleSendableAnimation(Animation animation, Player player, boolean withPlaceholders) { + return null; + } + + public Object createTitleSendableAnimation(List> parts, Player player, boolean withPlaceholders) { + return null; + } + + public Object createSubtitleSendableAnimation(Animation animation, Player player, boolean withPlaceholders) { + return null; + } + + public Object createSubtitleSendableAnimation(List> parts, Player player, boolean withPlaceholders) { + return null; + } + + public void sendTitle(Player player, String title, boolean withPlaceholders) { + sendTitle(player, title, 10, 70, 20, withPlaceholders); + } + + public void sendTitle(Player player, String title, int fadeIn, int stay, int fadeOut, boolean withPlaceholders) { + // Send title to player + } + + public void sendProcessedTitle(Player player, String title, int fadeIn, int stay, int fadeOut) { + sendTitle(player, title, fadeIn, stay, fadeOut, true); + } + + public void sendSubtitle(Player player, String subtitle, boolean withPlaceholders) { + sendSubtitle(player, subtitle, 10, 70, 20, withPlaceholders); + } + + public void sendSubtitle(Player player, String subtitle, int fadeIn, int stay, int fadeOut, boolean withPlaceholders) { + // Send subtitle to player + } + + public void sendProcessedSubtitle(Player player, String subtitle, int fadeIn, int stay, int fadeOut) { + sendSubtitle(player, subtitle, fadeIn, stay, fadeOut, true); + } + + public void sendTitles(Player player, String title, String subtitle, boolean withPlaceholders) { + sendTitles(player, title, subtitle, 10, 70, 20, withPlaceholders); + } + + public void sendTitles(Player player, String title, String subtitle, int fadeIn, int stay, int fadeOut, boolean withPlaceholders) { + sendTitle(player, title, fadeIn, stay, fadeOut, withPlaceholders); + sendSubtitle(player, subtitle, fadeIn, stay, fadeOut, withPlaceholders); + } + + public void sendTimings(Player player, int fadeIn, int stay, int fadeOut) { + // Send timings to player + } + + public void clearTitle(Player player) { + // Clear title - use sendTitle with empty strings + player.sendTitle("", "", 0, 0, 0); + } + + public void clearSubtitle(Player player) { + // Clear subtitle - use sendTitle with empty strings + player.sendTitle("", "", 0, 0, 0); + } + + public void clearTitles(Player player) { + // Clear both title and subtitle + player.sendTitle("", "", 0, 0, 0); + } +} diff --git a/src/main/resources/animations/left-to-right.txt b/src/main/resources/animations/left-to-right.txt new file mode 100644 index 0000000..2c8d37e --- /dev/null +++ b/src/main/resources/animations/left-to-right.txt @@ -0,0 +1,18 @@ +[0;5;0]&7&b-&7--------- +[0;2;0]&7-&b-&7-------- +[0;2;0]&7--&b-&7------- +[0;2;0]&7---&b-&7------ +[0;2;0]&7----&b-&7----- +[0;2;0]&7-----&b-&7---- +[0;2;0]&7------&b-&7--- +[0;2;0]&7-------&b-&7-- +[0;2;0]&7--------&b-&7- +[0;5;0]&7---------&b-&7 +[0;2;0]&7--------&b-&7- +[0;2;0]&7-------&b-&7-- +[0;2;0]&7------&b-&7--- +[0;2;0]&7-----&b-&7---- +[0;2;0]&7----&b-&7----- +[0;2;0]&7---&b-&7------ +[0;2;0]&7--&b-&7------- +[0;2;0]&7-&b-&7-------- \ No newline at end of file diff --git a/src/main/resources/animations/right-to-left.txt b/src/main/resources/animations/right-to-left.txt new file mode 100644 index 0000000..14e6377 --- /dev/null +++ b/src/main/resources/animations/right-to-left.txt @@ -0,0 +1,18 @@ +[0;5;0]&7---------&b-&7 +[0;2;0]&7--------&b-&7- +[0;2;0]&7-------&b-&7-- +[0;2;0]&7------&b-&7--- +[0;2;0]&7-----&b-&7---- +[0;2;0]&7----&b-&7----- +[0;2;0]&7---&b-&7------ +[0;2;0]&7--&b-&7------- +[0;2;0]&7-&b-&7-------- +[0;5;0]&7&b-&7--------- +[0;2;0]&7-&b-&7-------- +[0;2;0]&7--&b-&7------- +[0;2;0]&7---&b-&7------ +[0;2;0]&7----&b-&7----- +[0;2;0]&7-----&b-&7---- +[0;2;0]&7------&b-&7--- +[0;2;0]&7-------&b-&7-- +[0;2;0]&7--------&b-&7- \ No newline at end of file diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml new file mode 100644 index 0000000..f9289b6 --- /dev/null +++ b/src/main/resources/config.yml @@ -0,0 +1,363 @@ +############################################################ +# +------------------------------------------------------+ # +# | Notes | # +# +------------------------------------------------------+ # +############################################################ + +# Config comment style borrowed from the Essentials config. +# +# If you want to use special characters (ASCII, UTF-8 characters) in the config, you need to save the file as UTF-8. +# - If you don't know how this is done, you can see the guide on the wiki: https://github.com/Puharesource/TitleManager/wiki/Unicode---UTF-8-characters-for-TitleManager +# +# Config errors, such as the plugin not loading or the config resetting can be fixed by ensuring that: +# - No tabs are present: YAML only allows spaces. +# - You have escaped all apostrophes or quotes in your text: +# - If you surround your text with apostrophes like this 'don't', double all of your apostrophes like this: 'don''t' +# - If you surround your text with quotes like this "Quote: "hello"", switch to apostrophes instead like this 'Quite: "hello"'. +# +# If you've got problems: +# - Join the Discord server here: https://discord.gg/U3Yyu6G +# - Write a ticket on the Issue Tracker here: https://github.com/Puharesource/TitleManager/issues +# +# Help with animations and scripts: +# - Go to https://tarkan.dev/tmgenerator +# +# 1 second = 20 ticks +# +# For more information check: https://github.com/Puharesource/TitleManager/wiki + +############################################################ +# +------------------------------------------------------+ # +# | General | # +# +------------------------------------------------------+ # +############################################################ + +# Never change this value +config-version: 7 + +# Toggles debug mode, which prints additional information when the plugin does something. +debug: false + +# Toggles whether or not all of the features of TitleManager will be toggled. +using-config: true + +# Toggles whether or not all of the BungeeCord functionality will be toggled. +using-bungeecord: false + +# (Feature only works on 1.7-1.8 Protocol Hack) +# Toggles whether or not 1.7 players will see actionbar messages when they're holding an item. +legacy-client-support: false + +# Toggles whether or not the plugin should warn administrators if there's a new version out. +check-for-updates: true + +# The locale used for some of the placeholders. +locale: 'en-US' + +############################################################ +# +------------------------------------------------------+ # +# | Player List | # +# +------------------------------------------------------+ # +############################################################ + +# Sets the header and footer of the player list. (Shown when you hold the TAB key.) + +player-list: + + # Toggles this feature. + enabled: true + + # Sets the header of the player list. + # + # Single line format. + # header: 'My header text' + # + # Multiple line format. + # header: + # - 'My first line' + # - 'My second line' + # - 'My third line' + header: + - '' + - '${shine:[0;2;0][0;25;0][0;25;0][&3;&b]My Server}' + - '' + + # Sets the footer of the player list. + # + # Single line format. + # footer: 'My footer text' + # + # Multiple line format. + # footer: + # - 'My first line' + # - 'My second line' + # - 'My third line' + footer: + - '' + - '&7World time: &b%{12h-world-time}' + - '&7Server time: &b%{server-time}' + - '' + - '${right-to-left} &b%{online}&7/&b%{max} &7Online Players ${left-to-right}' + +############################################################ +# +------------------------------------------------------+ # +# | Welcome Title | # +# +------------------------------------------------------+ # +############################################################ + +# Sets the title that is sent to the player when they join the server. + +welcome-title: + + # Toggles this feature. + enabled: true + + # The title shown. + title: 'Welcome to My Server' + + # The subtitle shown. + subtitle: 'Hope you enjoy your stay' + + # The time it takes for the title to fade into the screen. (In ticks) + fade-in: 20 + + # The time it takes for the title to stay on the screen. (In ticks) + stay: 40 + + # The time it takes for the title to fade out of the screen. (In ticks) + fade-out: 20 + + # The time it takes for the titles to appear. (In ticks) + delay: 20 + + # The title shown when the player joins the server for the first time. + first-join: + + # The title shown. + title: 'Welcome to My Server' + + # The subtitle shown. + subtitle: 'This is your first time!' + +############################################################ +# +------------------------------------------------------+ # +# | Welcome Actionbar | # +# +------------------------------------------------------+ # +############################################################ + +# Sets the actionbar that is sent to the player when they join the server. + +welcome-actionbar: + + # Toggles this feature. + enabled: true + + # The message shown. + title: 'Welcome to My Server' + + # The time it takes for the message to appear. (In ticks) + delay: 20 + + # The message shown when the player joins the server for the first time. + first-join: 'Welcome to My Server, this is your first time!' + +############################################################ +# +------------------------------------------------------+ # +# | Placeholders | # +# +------------------------------------------------------+ # +############################################################ + +# Configures anything placeholder related. + +placeholders: + + # The format used by the balance placeholder. + number-format: + + # Toggles this feature. + enabled: true + + # The format used. + format: '#,###.##' + + # The format used by the server-time placeholder. + # The format used can be found here: https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html + date-format: 'EEE, dd MMM yyyy HH:mm:ss z' + +############################################################ +# +------------------------------------------------------+ # +# | Scoreboard | # +# +------------------------------------------------------+ # +############################################################ + +# Sets the scoreboard (sidebar) that is sent to the player + +scoreboard: + + # Toggles this feature + enabled: true + + # The title displayed at the very top of the scoreboard + # WARNING! (1.12 or below ONLY) The title must consist of 32 or less characters (this includes color codes) + title: '${shine:[0;2;0][0;25;0][0;25;0][&3&l;&b&l]My Server}' + + # The lines of the scoreboard (Maximum of 15 lines allowed) + lines: + - '&b&m----------------------------------' + - '&b> &3&lPlayer Name:' + - '&b%{name}' + - '&r' + - '&b> &3&lPing:' + - '&b%{ping} MS' + - '&r&r' + - '&b> &3&lServer Time:' + - '&b%{server-time}' + - '&b&m----------------------------------&r' + + # A list of worlds that the Scoreboard should not be shown in. + disabled-worlds: + - 'my-disabled-world' + - 'my-disabled-world-nether' + +############################################################ +# +------------------------------------------------------+ # +# | Announcer | # +# +------------------------------------------------------+ # +############################################################ + +# Automatically send titles and/or actionbar messages to the players on the server. + +announcer: + + # Toggles this feature. + enabled: true + + # The announcements + # + # The format: + # + # announcement-name: + # interval: 60 (Seconds, Default: 60) + # timings: + # fade-in: 20 (Ticks, Default: 20) + # stay: 40 (Ticks, Default: 40) + # fade-out: 20 (Ticks, Default: 20) + # titles: + # - 'First title' (The title sent) + # - 'Second title\nSecond subtitle' (The next title sent, this time using \n to split the title and subtitle from each other) + # actionbar: + # - 'First actionbar' (The actionbar message sent) + # - 'The next actionbar sent' (The next actionbar message sent) + announcements: + my-announcement: + interval: 60 + timings: + fade-in: 20 + stay: 40 + fade-out: 20 + titles: + - '&aThis is the 1st title announcement\n&aThis is the subtitle' + - '&bThis is the 2nd title announcement\n&bThis is the subtitle' + actionbar: + - '&aThis is the 1st actionbar announcement' + - '&bThis is the 2nd actionbar announcement' + +############################################################ +# +------------------------------------------------------+ # +# | Bandwidth | # +# +------------------------------------------------------+ # +############################################################ + +# Configures all of the bandwidth saving options. + +bandwidth: + # Prevents sending identical packets, lowering bandwidth (but might be more CPU intensive). + prevent-duplicate-packets: true + + # The tick rate of the player list in milliseconds. (Lower = More bandwidth & CPU usage, Higher = Less bandwidth & CPU usage) + player-list-ms-per-tick: 50 + + # The tick rate of the scoreboard in milliseconds. (Lower = More bandwidth & CPU usage, Higher = Less bandwidth & CPU usage) + scoreboard-ms-per-tick: 50 + +############################################################ +# +------------------------------------------------------+ # +# | Plugin Hooks | # +# +------------------------------------------------------+ # +############################################################ + +# Allows you to enable and disable certain hooks. + +hooks: + combatlogx: true + +############################################################ +# +------------------------------------------------------+ # +# | Messages | # +# +------------------------------------------------------+ # +############################################################ + +# Configures all of the messages sent to the users. + +messages: + # The message shown when a player doesn't have permission to run a command. + no-permission: '&cYou do not have permission to run that command!' + + # The messages from the command /tm version + command-version: + description: 'Gives you the current running version of TitleManager' + version: '&aThe server is running %version' + + # The messages from the command /tm reload + command-reload: + description: 'Reloads TitleManager' + reloaded: '&aTitleManager reloaded' + + # The messages from the command /tm animations + command-animations: + description: 'Displays all loaded animations' + format: '&aLoaded animations (&f%count&a): %animations' + separator: '&f, &a' + + # The messages from the command /tm scripts + command-scripts: + description: 'Displays all loaded scripts' + format: '&aLoaded scripts (&f%count&a): %scripts' + separator: '&f, &a' + + # The messages from the command /tm broadcast + command-broadcast: + description: 'Broadcasts a title to the server' + usage: '|<title\nsubtitle>' + title-sent: '&aYou have broadcasted the title "&r%title&a".' + subtitle-sent: '&aYou have broadcasted the subtitle "&r%subtitle&a".' + both-sent: '&aYou have broadcasted the titles "&r%title&a" "&r%subtitle&a".' + + # The messages from the command /tm abroadcast + command-abroadcast: + description: 'Broadcasts an actionbar title to the server' + usage: '<title>' + sent: '&aYou have broadcasted the actionbar title "&r%title&a".' + + # The messages from the command /tm message + command-message: + description: 'Sends a title to the specified player' + usage: '<player> <title>|<title\nsubtitle>' + title-sent: '&aYou have sent %player the title "&r%title&a".' + subtitle-sent: '&aYou have sent %player the subtitle "&r%subtitle&a".' + both-sent: '&aYou have sent %player the titles "&r%title&a" "&r%subtitle&a".' + invalid-player: '&c%player is not a valid player.' + + # The messages from the command /tm amessage + command-amessage: + description: 'Sends an actionbar title to the specified player' + usage: '<player> <title>' + sent: '&aYou have sent %player the actionbar title "&r%title&a".' + invalid-player: '&c%player is not a valid player.' + + # The messages from the command /tm scoreboard + command-scoreboard: + description: 'Toggles the scoreboard on or off.' + usage: 'toggle' + toggled-on: '&aYou have enabled your scoreboard.' + toggled-off: '&cYou have disabled your scoreboard.' diff --git a/src/main/resources/playerinfo.sql b/src/main/resources/playerinfo.sql new file mode 100644 index 0000000..2441951 --- /dev/null +++ b/src/main/resources/playerinfo.sql @@ -0,0 +1,4 @@ +CREATE TABLE IF NOT EXISTS "playerinfo" ( + uuid VARCHAR(36) NOT NULL, + scoreboard_toggled INTEGER NOT NULL +); \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml new file mode 100644 index 0000000..5fac73c --- /dev/null +++ b/src/main/resources/plugin.yml @@ -0,0 +1,34 @@ +name: TitleManager +version: 3.0.0 +description: A powerful title/subtitle manager plugin for Minecraft 1.21.x +author: Puharesource +website: https://github.com/Puharesource/TitleManager +api-version: 1.21 + +main: io.mviper.mc.titlemanager.TitleManagerPlugin +softdepend: [Vault, Essentials, VanishNoPacket, PlaceholderAPI, SuperVanish, PremiumVanish, MVdWPlaceholderAPI, CombatLogX] + +commands: + tm: + description: TitleManager management commands + usage: /tm <subcommand> + aliases: [titlemanager] + permission: titlemanager.command.main + permission-message: §cYou don't have permission to use this command + +permissions: + titlemanager.*: + description: Grants all TitleManager permissions + children: + titlemanager.command.*: true + titlemanager.command.*: + description: Grants all TitleManager command permissions + children: + titlemanager.command.main: true + titlemanager.command.reload: true + titlemanager.command.main: + description: Allows access to main TitleManager commands + default: op + titlemanager.command.reload: + description: Allows reloading the plugin + default: op diff --git a/src/main/resources/titlemanager_engine.js b/src/main/resources/titlemanager_engine.js new file mode 100644 index 0000000..9ad5e93 --- /dev/null +++ b/src/main/resources/titlemanager_engine.js @@ -0,0 +1,61 @@ +try { + load('nashorn:mozilla_compat.js'); + + importPackage('org.bukkit'); +} catch (e) {} + +var Bukkit = Java.type('org.bukkit.Bukkit'); +var ChatColor = Java.type('net.md_5.bungee.api.ChatColor'); + +var createCommandSender = function() { + return ScriptCommandSender.newInstance(); +}; + +var isTesting = function () { + return Bukkit.getServer() === null; +}; + +var getTimingsPattern = function () { + return /^\[([-]?\d+);([-]?\d+);([-]?\d+)](.+)$/g; +}; + +var tmResult = function(text, done, fadeIn, stay, fadeOut) { + return Java.to([text, done, fadeIn, stay, fadeOut]) +}; + +var hasTimings = function (text) { + return text.match(getTimingsPattern()) !== null; +}; + +var getTimings = function (text) { + var match = getTimingsPattern().exec(text); + + var fadeIn = parseInt(match[1]); + var stay = parseInt(match[2]); + var fadeOut = parseInt(match[3]); + var groupText = match[4]; + + return [groupText, fadeIn, stay, fadeOut] +}; + +var parseInt = function(string, radix) { + var val = NaN; + + try { + if (radix) { + val = java.lang.Integer.parseInt(string, radix); + } else { + val = java.lang.Integer.parseInt(string); + } + } catch (e) {} + + return val; +}; + +var sendCommand = function(commandSender, commandLine) { + if (isTesting()) { + print("Sending command with command line: " + commandLine); + } else { + Bukkit.dispatchCommand(commandSender, commandLine); + } +}; \ No newline at end of file