diff --git a/.gitignore b/.gitignore index 3e42729..b9d5de3 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,6 @@ Thumbs.db # Local config local.properties + +# Temp folders +temp_*/ diff --git a/build.gradle.kts b/build.gradle.kts index 611b25a..6a5a9ce 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,9 +1,10 @@ plugins { java + checkstyle } group = "com.loki" -version = "1.5.5-1.20.1" +version = "1.5.5-1.21.8" repositories { mavenCentral() @@ -15,7 +16,7 @@ repositories { } dependencies { - compileOnly("io.papermc.paper:paper-api:1.20.1-R0.1-SNAPSHOT") + compileOnly("io.papermc.paper:paper-api:1.21.4-R0.1-SNAPSHOT") compileOnly("me.clip:placeholderapi:2.11.6") compileOnly("org.black_ixx:playerpoints:3.2.7") compileOnly("net.luckperms:api:5.4") @@ -24,7 +25,7 @@ dependencies { testImplementation("org.junit.jupiter:junit-jupiter-api:5.10.0") testImplementation("org.junit.jupiter:junit-jupiter-engine:5.10.0") testImplementation("org.mockito:mockito-core:5.11.0") - testImplementation("io.papermc.paper:paper-api:1.20.1-R0.1-SNAPSHOT") + testImplementation("io.papermc.paper:paper-api:1.21.4-R0.1-SNAPSHOT") testRuntimeOnly("org.junit.platform:junit-platform-launcher:1.10.0") } @@ -48,7 +49,21 @@ tasks.test { } tasks.jar { - archiveFileName.set("LoChat-1.5.5-1.20.1.jar") + archiveFileName.set("LoChat-1.5.5-1.21.8.jar") from(configurations.runtimeClasspath.get().map { if (it.isDirectory) it else zipTree(it) }) duplicatesStrategy = DuplicatesStrategy.EXCLUDE } + +checkstyle { + toolVersion = "10.12.5" + configFile = file("${rootDir}/config/checkstyle/checkstyle.xml") + isIgnoreFailures = true + maxWarnings = 999 +} + +tasks.withType { + reports { + xml.required.set(false) + html.required.set(true) + } +} diff --git a/config/checkstyle/README.md b/config/checkstyle/README.md new file mode 100644 index 0000000..41107fb --- /dev/null +++ b/config/checkstyle/README.md @@ -0,0 +1,83 @@ +# Checkstyle Configuration + +Автоматическая проверка качества кода во время билда. + +## Правила + +### Размеры +- **Файл**: максимум 150 строк +- **Метод**: максимум 30 строк +- **Строка**: максимум 120 символов +- **Параметры**: максимум 5 параметров + +### Сложность +- **Cyclomatic Complexity**: максимум 10 +- **Вложенность if**: максимум 3 уровня +- **Вложенность try**: максимум 2 уровня + +### Качество кода +- Нет дублирования строк (макс 2 повтора) +- Нет магических чисел (кроме -1, 0, 1, 2, 3, 4, 5, 10, 20, 100) +- Нет * импортов +- Нет неиспользуемых импортов +- Упрощение boolean выражений +- equals() и hashCode() вместе + +### Форматирование +- Отступы: 4 пробела +- Скобки обязательны для if/for/while +- Один оператор на строку +- Пробелы вокруг операторов + +## Запуск проверки + +```bash +# Проверить весь проект +./gradlew check + +# Проверить только LoChat +./gradlew checkstyleMain + +# Проверить только LoHub +./gradlew :lohub:checkstyleMain + +# Проверить только LoVelocity +./gradlew :lovelocity:checkstyleMain +``` + +## Отчеты + +После проверки отчеты доступны в: +- `build/reports/checkstyle/main.html` +- `lohub/build/reports/checkstyle/main.html` +- `lovelocity/build/reports/checkstyle/main.html` + +## Отключение проверки + +Если нужно временно отключить проверку для конкретного файла: + +```java +// CHECKSTYLE:OFF +public class MyClass { + // код без проверки +} +// CHECKSTYLE:ON +``` + +Или для конкретной строки: + +```java +private static final int MAGIC = 42; // CHECKSTYLE IGNORE MagicNumber +``` + +## Интеграция с IDE + +### IntelliJ IDEA +1. Установить плагин "CheckStyle-IDEA" +2. Settings → Tools → Checkstyle +3. Добавить конфиг: `config/checkstyle/checkstyle.xml` +4. Активировать проверку в реальном времени + +### VS Code +1. Установить расширение "Checkstyle for Java" +2. Настроить путь к конфигу в settings.json diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml new file mode 100644 index 0000000..504ab7a --- /dev/null +++ b/config/checkstyle/checkstyle.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lohub/build.gradle.kts b/lohub/build.gradle.kts index fc2cfe5..5e315f3 100644 --- a/lohub/build.gradle.kts +++ b/lohub/build.gradle.kts @@ -1,5 +1,6 @@ plugins { java + checkstyle } repositories { @@ -10,7 +11,7 @@ repositories { } dependencies { - compileOnly("io.papermc.paper:paper-api:1.20.1-R0.1-SNAPSHOT") + compileOnly("io.papermc.paper:paper-api:1.21.4-R0.1-SNAPSHOT") compileOnly("me.clip:placeholderapi:2.11.6") compileOnly("com.sk89q.worldguard:worldguard-bukkit:7.0.9") implementation("com.google.code.gson:gson:2.10.1") @@ -21,8 +22,28 @@ dependencies { testRuntimeOnly("org.junit.platform:junit-platform-launcher:1.10.0") } +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(21)) + } +} + tasks.jar { - archiveFileName.set("LoHub-1.5.5-1.20.1.jar") + archiveFileName.set("LoHub-1.5.5-1.21.8.jar") from(configurations.runtimeClasspath.get().map { if (it.isDirectory) it else zipTree(it) }) duplicatesStrategy = DuplicatesStrategy.EXCLUDE } + +checkstyle { + toolVersion = "10.12.5" + configFile = file("${rootProject.rootDir}/config/checkstyle/checkstyle.xml") + isIgnoreFailures = false + maxWarnings = 0 +} + +tasks.withType { + reports { + xml.required.set(false) + html.required.set(true) + } +} diff --git a/lohub/src/main/java/com/loki/lohub/LoHub.java b/lohub/src/main/java/com/loki/lohub/LoHub.java index 58bdacd..e5661bd 100644 --- a/lohub/src/main/java/com/loki/lohub/LoHub.java +++ b/lohub/src/main/java/com/loki/lohub/LoHub.java @@ -11,67 +11,67 @@ import com.loki.lohub.utils.PlaceholderUtil; import org.bukkit.plugin.java.JavaPlugin; public class LoHub extends JavaPlugin { - + private ConfigManager configManager; private SpawnManager spawnManager; private RegionManager regionManager; private ActionManager actionManager; private CooldownManager cooldownManager; - + @Override public void onEnable() { getLogger().info("Loading LoHub v" + getDescription().getVersion()); - + saveDefaultConfig(); - + PlaceholderUtil.init(); - + this.configManager = new ConfigManager(this); this.spawnManager = new SpawnManager(this); this.regionManager = new RegionManager(this); this.actionManager = new ActionManager(this); this.cooldownManager = new CooldownManager(); - + registerListeners(); registerCommands(); - + regionManager.createHubRegion(); - + getLogger().info("LoHub successfully loaded!"); } - + @Override public void onDisable() { getLogger().info("LoHub disabled!"); } - + private void registerListeners() { getServer().getPluginManager().registerEvents(new HubProtectionListener(this), this); getServer().getPluginManager().registerEvents(new PlayerJoinListener(this), this); } - + private void registerCommands() { getCommand("hub").setExecutor(new com.loki.lohub.commands.HubCommand(this)); getCommand("sethub").setExecutor(new com.loki.lohub.commands.SetHubCommand(this)); getCommand("lohub").setExecutor(new com.loki.lohub.commands.LoHubCommand(this)); } - + public ConfigManager getConfigManager() { return configManager; } - + public SpawnManager getSpawnManager() { return spawnManager; } - + public RegionManager getRegionManager() { return regionManager; } - + public ActionManager getActionManager() { return actionManager; } - + public CooldownManager getCooldownManager() { return cooldownManager; } diff --git a/lohub/src/main/java/com/loki/lohub/actions/Action.java b/lohub/src/main/java/com/loki/lohub/actions/Action.java index 4fb6bfb..22dfc9e 100644 --- a/lohub/src/main/java/com/loki/lohub/actions/Action.java +++ b/lohub/src/main/java/com/loki/lohub/actions/Action.java @@ -3,8 +3,8 @@ package com.loki.lohub.actions; import org.bukkit.entity.Player; public interface Action { - + void execute(Player player); - + ActionType getType(); } diff --git a/lohub/src/main/java/com/loki/lohub/actions/ActionType.java b/lohub/src/main/java/com/loki/lohub/actions/ActionType.java index dadd717..8b59644 100644 --- a/lohub/src/main/java/com/loki/lohub/actions/ActionType.java +++ b/lohub/src/main/java/com/loki/lohub/actions/ActionType.java @@ -12,7 +12,7 @@ public enum ActionType { EFFECT, CLOSE, UNKNOWN; - + public static ActionType fromString(String type) { try { return valueOf(type.toUpperCase()); diff --git a/lohub/src/main/java/com/loki/lohub/actions/impl/ActionbarAction.java b/lohub/src/main/java/com/loki/lohub/actions/impl/ActionbarAction.java index 33419d5..57b0bba 100644 --- a/lohub/src/main/java/com/loki/lohub/actions/impl/ActionbarAction.java +++ b/lohub/src/main/java/com/loki/lohub/actions/impl/ActionbarAction.java @@ -8,19 +8,19 @@ import net.kyori.adventure.text.Component; import org.bukkit.entity.Player; public class ActionbarAction implements Action { - + private final String message; - + public ActionbarAction(String message) { this.message = message; } - + @Override public void execute(Player player) { String parsed = PlaceholderUtil.parse(message, player); player.sendActionBar(Component.text(TextUtil.colorize(parsed))); } - + @Override public ActionType getType() { return ActionType.ACTIONBAR; diff --git a/lohub/src/main/java/com/loki/lohub/actions/impl/BroadcastAction.java b/lohub/src/main/java/com/loki/lohub/actions/impl/BroadcastAction.java index 8fe63bd..a051f45 100644 --- a/lohub/src/main/java/com/loki/lohub/actions/impl/BroadcastAction.java +++ b/lohub/src/main/java/com/loki/lohub/actions/impl/BroadcastAction.java @@ -8,19 +8,19 @@ import org.bukkit.Bukkit; import org.bukkit.entity.Player; public class BroadcastAction implements Action { - + private final String message; - + public BroadcastAction(String message) { this.message = message; } - + @Override public void execute(Player player) { String parsed = PlaceholderUtil.parse(message, player); Bukkit.broadcastMessage(TextUtil.colorize(parsed)); } - + @Override public ActionType getType() { return ActionType.BROADCAST; diff --git a/lohub/src/main/java/com/loki/lohub/actions/impl/CloseAction.java b/lohub/src/main/java/com/loki/lohub/actions/impl/CloseAction.java index b47c55b..1e3e77f 100644 --- a/lohub/src/main/java/com/loki/lohub/actions/impl/CloseAction.java +++ b/lohub/src/main/java/com/loki/lohub/actions/impl/CloseAction.java @@ -5,12 +5,12 @@ import com.loki.lohub.actions.ActionType; import org.bukkit.entity.Player; public class CloseAction implements Action { - + @Override public void execute(Player player) { player.closeInventory(); } - + @Override public ActionType getType() { return ActionType.CLOSE; diff --git a/lohub/src/main/java/com/loki/lohub/actions/impl/CommandAction.java b/lohub/src/main/java/com/loki/lohub/actions/impl/CommandAction.java index cfb9f0d..0c1acf2 100644 --- a/lohub/src/main/java/com/loki/lohub/actions/impl/CommandAction.java +++ b/lohub/src/main/java/com/loki/lohub/actions/impl/CommandAction.java @@ -6,19 +6,19 @@ import com.loki.lohub.utils.PlaceholderUtil; import org.bukkit.entity.Player; public class CommandAction implements Action { - + private final String command; - + public CommandAction(String command) { this.command = command; } - + @Override public void execute(Player player) { String parsed = PlaceholderUtil.parse(command, player); player.performCommand(parsed); } - + @Override public ActionType getType() { return ActionType.COMMAND; diff --git a/lohub/src/main/java/com/loki/lohub/actions/impl/ConsoleAction.java b/lohub/src/main/java/com/loki/lohub/actions/impl/ConsoleAction.java index 0049a37..663f25a 100644 --- a/lohub/src/main/java/com/loki/lohub/actions/impl/ConsoleAction.java +++ b/lohub/src/main/java/com/loki/lohub/actions/impl/ConsoleAction.java @@ -7,19 +7,19 @@ import org.bukkit.Bukkit; import org.bukkit.entity.Player; public class ConsoleAction implements Action { - + private final String command; - + public ConsoleAction(String command) { this.command = command; } - + @Override public void execute(Player player) { String parsed = PlaceholderUtil.parse(command, player); Bukkit.dispatchCommand(Bukkit.getConsoleSender(), parsed); } - + @Override public ActionType getType() { return ActionType.CONSOLE; diff --git a/lohub/src/main/java/com/loki/lohub/actions/impl/EffectAction.java b/lohub/src/main/java/com/loki/lohub/actions/impl/EffectAction.java index f4337aa..214be6e 100644 --- a/lohub/src/main/java/com/loki/lohub/actions/impl/EffectAction.java +++ b/lohub/src/main/java/com/loki/lohub/actions/impl/EffectAction.java @@ -7,36 +7,36 @@ import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; public class EffectAction implements Action { - + private final PotionEffectType effectType; private final int amplifier; private final int duration; - + public EffectAction(String effectData) { String[] parts = effectData.split(";"); - + PotionEffectType parsed; try { parsed = PotionEffectType.getByName(parts[0].toUpperCase()); } catch (Exception e) { parsed = PotionEffectType.SPEED; } - + this.effectType = parsed != null ? parsed : PotionEffectType.SPEED; this.amplifier = parts.length > 1 ? parseInt(parts[1], 0) : 0; this.duration = parts.length > 2 ? parseInt(parts[2], 999999) : 999999; } - + @Override public void execute(Player player) { player.addPotionEffect(new PotionEffect(effectType, duration * 20, amplifier, false, false)); } - + @Override public ActionType getType() { return ActionType.EFFECT; } - + private int parseInt(String value, int defaultValue) { try { return Integer.parseInt(value); diff --git a/lohub/src/main/java/com/loki/lohub/actions/impl/GamemodeAction.java b/lohub/src/main/java/com/loki/lohub/actions/impl/GamemodeAction.java index 16586ba..f200274 100644 --- a/lohub/src/main/java/com/loki/lohub/actions/impl/GamemodeAction.java +++ b/lohub/src/main/java/com/loki/lohub/actions/impl/GamemodeAction.java @@ -6,9 +6,9 @@ import org.bukkit.GameMode; import org.bukkit.entity.Player; public class GamemodeAction implements Action { - + private final GameMode gameMode; - + public GamemodeAction(String mode) { GameMode parsed; try { @@ -24,12 +24,12 @@ public class GamemodeAction implements Action { } this.gameMode = parsed; } - + @Override public void execute(Player player) { player.setGameMode(gameMode); } - + @Override public ActionType getType() { return ActionType.GAMEMODE; diff --git a/lohub/src/main/java/com/loki/lohub/actions/impl/MessageAction.java b/lohub/src/main/java/com/loki/lohub/actions/impl/MessageAction.java index 15c3dd5..93f99db 100644 --- a/lohub/src/main/java/com/loki/lohub/actions/impl/MessageAction.java +++ b/lohub/src/main/java/com/loki/lohub/actions/impl/MessageAction.java @@ -7,19 +7,19 @@ import com.loki.lohub.utils.TextUtil; import org.bukkit.entity.Player; public class MessageAction implements Action { - + private final String message; - + public MessageAction(String message) { this.message = message; } - + @Override public void execute(Player player) { String parsed = PlaceholderUtil.parse(message, player); player.sendMessage(TextUtil.colorize(parsed)); } - + @Override public ActionType getType() { return ActionType.MESSAGE; diff --git a/lohub/src/main/java/com/loki/lohub/actions/impl/SoundAction.java b/lohub/src/main/java/com/loki/lohub/actions/impl/SoundAction.java index 655c3f3..b742fef 100644 --- a/lohub/src/main/java/com/loki/lohub/actions/impl/SoundAction.java +++ b/lohub/src/main/java/com/loki/lohub/actions/impl/SoundAction.java @@ -6,36 +6,36 @@ import org.bukkit.Sound; import org.bukkit.entity.Player; public class SoundAction implements Action { - + private final Sound sound; private final float volume; private final float pitch; - + public SoundAction(String soundData) { String[] parts = soundData.split(";"); - + Sound parsedSound; try { parsedSound = Sound.valueOf(parts[0].toUpperCase()); } catch (IllegalArgumentException e) { parsedSound = Sound.ENTITY_EXPERIENCE_ORB_PICKUP; } - + this.sound = parsedSound; this.volume = parts.length > 1 ? parseFloat(parts[1], 1.0f) : 1.0f; this.pitch = parts.length > 2 ? parseFloat(parts[2], 1.0f) : 1.0f; } - + @Override public void execute(Player player) { player.playSound(player.getLocation(), sound, volume, pitch); } - + @Override public ActionType getType() { return ActionType.SOUND; } - + private float parseFloat(String value, float defaultValue) { try { return Float.parseFloat(value); diff --git a/lohub/src/main/java/com/loki/lohub/actions/impl/TitleAction.java b/lohub/src/main/java/com/loki/lohub/actions/impl/TitleAction.java index bcd51e5..c253897 100644 --- a/lohub/src/main/java/com/loki/lohub/actions/impl/TitleAction.java +++ b/lohub/src/main/java/com/loki/lohub/actions/impl/TitleAction.java @@ -11,46 +11,46 @@ import org.bukkit.entity.Player; import java.time.Duration; public class TitleAction implements Action { - + private final String title; private final String subtitle; private final int fadeIn; private final int stay; private final int fadeOut; - + public TitleAction(String titleData) { String[] parts = titleData.split(";"); - + this.title = parts.length > 0 ? parts[0] : ""; this.subtitle = parts.length > 1 ? parts[1] : ""; this.fadeIn = parts.length > 2 ? parseInt(parts[2], 10) : 10; this.stay = parts.length > 3 ? parseInt(parts[3], 40) : 40; this.fadeOut = parts.length > 4 ? parseInt(parts[4], 10) : 10; } - + @Override public void execute(Player player) { String parsedTitle = PlaceholderUtil.parse(title, player); String parsedSubtitle = PlaceholderUtil.parse(subtitle, player); - + Component titleComponent = Component.text(TextUtil.colorize(parsedTitle)); Component subtitleComponent = Component.text(TextUtil.colorize(parsedSubtitle)); - + Title.Times times = Title.Times.times( - Duration.ofMillis(fadeIn * 50L), - Duration.ofMillis(stay * 50L), - Duration.ofMillis(fadeOut * 50L) + Duration.ofMillis(fadeIn * 50L), + Duration.ofMillis(stay * 50L), + Duration.ofMillis(fadeOut * 50L) ); - + Title title = Title.title(titleComponent, subtitleComponent, times); player.showTitle(title); } - + @Override public ActionType getType() { return ActionType.TITLE; } - + private int parseInt(String value, int defaultValue) { try { return Integer.parseInt(value); diff --git a/lohub/src/main/java/com/loki/lohub/commands/HubCommand.java b/lohub/src/main/java/com/loki/lohub/commands/HubCommand.java index 705b2c6..2a0c85e 100644 --- a/lohub/src/main/java/com/loki/lohub/commands/HubCommand.java +++ b/lohub/src/main/java/com/loki/lohub/commands/HubCommand.java @@ -8,28 +8,28 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; public class HubCommand implements CommandExecutor { - + private final LoHub plugin; - + public HubCommand(LoHub plugin) { this.plugin = plugin; } - + @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { if (!(sender instanceof Player player)) { sender.sendMessage(TextUtil.colorize("&cThis command is only for players!")); return true; } - + if (plugin.getSpawnManager().getSpawn() == null) { player.sendMessage(TextUtil.colorize(plugin.getConfig().getString("messages.no-spawn"))); return true; } - + plugin.getSpawnManager().teleportToSpawn(player); player.sendMessage(TextUtil.colorize(plugin.getConfig().getString("messages.spawn-teleport"))); - + return true; } } diff --git a/lohub/src/main/java/com/loki/lohub/commands/LoHubCommand.java b/lohub/src/main/java/com/loki/lohub/commands/LoHubCommand.java index 67b2046..4e8fcc1 100644 --- a/lohub/src/main/java/com/loki/lohub/commands/LoHubCommand.java +++ b/lohub/src/main/java/com/loki/lohub/commands/LoHubCommand.java @@ -7,32 +7,32 @@ import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; public class LoHubCommand implements CommandExecutor { - + private final LoHub plugin; - + public LoHubCommand(LoHub plugin) { this.plugin = plugin; } - + @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { if (!sender.hasPermission("lohub.admin")) { sender.sendMessage(TextUtil.colorize(plugin.getConfig().getString("messages.no-permission"))); return true; } - + if (args.length == 0) { sender.sendMessage(TextUtil.colorize("&7LoHub v" + plugin.getDescription().getVersion())); sender.sendMessage(TextUtil.colorize("&7Use: &e/lohub reload")); return true; } - + if (args[0].equalsIgnoreCase("reload")) { plugin.getConfigManager().reload(); sender.sendMessage(TextUtil.colorize("&aConfiguration reloaded!")); return true; } - + return true; } } diff --git a/lohub/src/main/java/com/loki/lohub/commands/SetHubCommand.java b/lohub/src/main/java/com/loki/lohub/commands/SetHubCommand.java index ebb6f04..603dd25 100644 --- a/lohub/src/main/java/com/loki/lohub/commands/SetHubCommand.java +++ b/lohub/src/main/java/com/loki/lohub/commands/SetHubCommand.java @@ -8,35 +8,35 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; public class SetHubCommand implements CommandExecutor { - + private final LoHub plugin; - + public SetHubCommand(LoHub plugin) { this.plugin = plugin; } - + @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { if (!(sender instanceof Player player)) { sender.sendMessage(TextUtil.colorize("&cThis command is only for players!")); return true; } - + if (!player.hasPermission("lohub.admin")) { player.sendMessage(TextUtil.colorize(plugin.getConfig().getString("messages.no-permission"))); return true; } - + plugin.getSpawnManager().setSpawn(player.getLocation()); player.sendMessage(TextUtil.colorize(plugin.getConfig().getString("messages.spawn-set"))); - + plugin.getRegionManager().deleteHubRegion(); plugin.getRegionManager().createHubRegion(); - + if (plugin.getConfig().getBoolean("worldguard.auto-create-region")) { player.sendMessage(TextUtil.colorize(plugin.getConfig().getString("messages.region-created"))); } - + return true; } } diff --git a/lohub/src/main/java/com/loki/lohub/config/ConfigManager.java b/lohub/src/main/java/com/loki/lohub/config/ConfigManager.java index 0e5e231..b9a166b 100644 --- a/lohub/src/main/java/com/loki/lohub/config/ConfigManager.java +++ b/lohub/src/main/java/com/loki/lohub/config/ConfigManager.java @@ -4,52 +4,52 @@ import com.loki.lohub.LoHub; import org.bukkit.configuration.file.FileConfiguration; public class ConfigManager { - + private final LoHub plugin; private FileConfiguration config; - + public ConfigManager(LoHub plugin) { this.plugin = plugin; this.config = plugin.getConfig(); } - + public void reload() { plugin.reloadConfig(); this.config = plugin.getConfig(); } - + public FileConfiguration getConfig() { return config; } - + public boolean isProtectionEnabled() { return config.getBoolean("protection.enabled", true); } - + public boolean isBlockBreakProtected() { return config.getBoolean("protection.block-break", true); } - + public boolean isBlockPlaceProtected() { return config.getBoolean("protection.block-place", true); } - + public boolean isPvPProtected() { return config.getBoolean("protection.pvp", true); } - + public boolean isItemDropProtected() { return config.getBoolean("protection.item-drop", true); } - + public boolean isItemPickupProtected() { return config.getBoolean("protection.item-pickup", true); } - + public boolean isFoodLevelProtected() { return config.getBoolean("protection.food-level", true); } - + public boolean isMobSpawningProtected() { return config.getBoolean("protection.mob-spawning", true); } diff --git a/lohub/src/main/java/com/loki/lohub/listeners/HubProtectionListener.java b/lohub/src/main/java/com/loki/lohub/listeners/HubProtectionListener.java index 89cfc51..1048783 100644 --- a/lohub/src/main/java/com/loki/lohub/listeners/HubProtectionListener.java +++ b/lohub/src/main/java/com/loki/lohub/listeners/HubProtectionListener.java @@ -13,90 +13,120 @@ import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerPickupItemEvent; public class HubProtectionListener implements Listener { - + private final LoHub plugin; - + public HubProtectionListener(LoHub plugin) { this.plugin = plugin; } - + @EventHandler public void onPlayerJoin(PlayerJoinEvent event) { if (plugin.getConfig().getBoolean("spawn.teleport-on-join", true)) { plugin.getSpawnManager().teleportToSpawn(event.getPlayer()); } } - + @EventHandler public void onBlockBreak(BlockBreakEvent event) { - if (!plugin.getConfigManager().isProtectionEnabled()) return; - + if (!plugin.getConfigManager().isProtectionEnabled()) { + return; + } + Player player = event.getPlayer(); - if (player.hasPermission("lohub.bypass.protection")) return; - + if (player.hasPermission("lohub.bypass.protection")) { + return; + } + if (plugin.getConfigManager().isBlockBreakProtected()) { event.setCancelled(true); } } - + @EventHandler public void onBlockPlace(BlockPlaceEvent event) { - if (!plugin.getConfigManager().isProtectionEnabled()) return; - + if (!plugin.getConfigManager().isProtectionEnabled()) { + return; + } + Player player = event.getPlayer(); - if (player.hasPermission("lohub.bypass.protection")) return; - + if (player.hasPermission("lohub.bypass.protection")) { + return; + } + if (plugin.getConfigManager().isBlockPlaceProtected()) { event.setCancelled(true); } } - + @EventHandler public void onPvP(EntityDamageByEntityEvent event) { - if (!plugin.getConfigManager().isProtectionEnabled()) return; - if (!(event.getDamager() instanceof Player)) return; - if (!(event.getEntity() instanceof Player)) return; - + if (!plugin.getConfigManager().isProtectionEnabled()) { + return; + } + if (!(event.getDamager() instanceof Player)) { + return; + } + if (!(event.getEntity() instanceof Player)) { + return; + } + Player damager = (Player) event.getDamager(); - if (damager.hasPermission("lohub.bypass.protection")) return; - + if (damager.hasPermission("lohub.bypass.protection")) { + return; + } + if (plugin.getConfigManager().isPvPProtected()) { event.setCancelled(true); } } - + @EventHandler public void onItemDrop(PlayerDropItemEvent event) { - if (!plugin.getConfigManager().isProtectionEnabled()) return; - + if (!plugin.getConfigManager().isProtectionEnabled()) { + return; + } + Player player = event.getPlayer(); - if (player.hasPermission("lohub.bypass.protection")) return; - + if (player.hasPermission("lohub.bypass.protection")) { + return; + } + if (plugin.getConfigManager().isItemDropProtected()) { event.setCancelled(true); } } - + @EventHandler public void onItemPickup(PlayerPickupItemEvent event) { - if (!plugin.getConfigManager().isProtectionEnabled()) return; - + if (!plugin.getConfigManager().isProtectionEnabled()) { + return; + } + Player player = event.getPlayer(); - if (player.hasPermission("lohub.bypass.protection")) return; - + if (player.hasPermission("lohub.bypass.protection")) { + return; + } + if (plugin.getConfigManager().isItemPickupProtected()) { event.setCancelled(true); } } - + @EventHandler public void onFoodLevelChange(FoodLevelChangeEvent event) { - if (!plugin.getConfigManager().isProtectionEnabled()) return; - if (!(event.getEntity() instanceof Player)) return; - + if (!plugin.getConfigManager().isProtectionEnabled()) { + return; + } + if (!(event.getEntity() instanceof Player)) { + return; + } + Player player = (Player) event.getEntity(); - if (player.hasPermission("lohub.bypass.protection")) return; - + if (player.hasPermission("lohub.bypass.protection")) { + return; + } + if (plugin.getConfigManager().isFoodLevelProtected()) { event.setCancelled(true); } diff --git a/lohub/src/main/java/com/loki/lohub/listeners/PlayerJoinListener.java b/lohub/src/main/java/com/loki/lohub/listeners/PlayerJoinListener.java index 748c452..ff5c775 100644 --- a/lohub/src/main/java/com/loki/lohub/listeners/PlayerJoinListener.java +++ b/lohub/src/main/java/com/loki/lohub/listeners/PlayerJoinListener.java @@ -20,37 +20,61 @@ import org.bukkit.inventory.meta.FireworkMeta; import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.HashMap; public class PlayerJoinListener implements Listener { - + + private static final Map COLOR_MAP = new HashMap<>(); + + static { + COLOR_MAP.put("AQUA", Color.AQUA); + COLOR_MAP.put("BLACK", Color.BLACK); + COLOR_MAP.put("BLUE", Color.BLUE); + COLOR_MAP.put("FUCHSIA", Color.FUCHSIA); + COLOR_MAP.put("GRAY", Color.GRAY); + COLOR_MAP.put("GREEN", Color.GREEN); + COLOR_MAP.put("LIME", Color.LIME); + COLOR_MAP.put("MAROON", Color.MAROON); + COLOR_MAP.put("NAVY", Color.NAVY); + COLOR_MAP.put("OLIVE", Color.OLIVE); + COLOR_MAP.put("ORANGE", Color.ORANGE); + COLOR_MAP.put("PURPLE", Color.PURPLE); + COLOR_MAP.put("RED", Color.RED); + COLOR_MAP.put("SILVER", Color.SILVER); + COLOR_MAP.put("TEAL", Color.TEAL); + COLOR_MAP.put("WHITE", Color.WHITE); + COLOR_MAP.put("YELLOW", Color.YELLOW); + } + private final LoHub plugin; - + public PlayerJoinListener(LoHub plugin) { this.plugin = plugin; } - + @EventHandler(priority = EventPriority.HIGHEST) public void onPlayerJoin(PlayerJoinEvent event) { Player player = event.getPlayer(); - + if (isWorldDisabled(player.getWorld().getName())) { return; } - + handleJoinMessage(event, player); handleJoinSettings(player); handleJoinEvents(player); handleFirework(player); } - + @EventHandler(priority = EventPriority.HIGHEST) public void onPlayerQuit(PlayerQuitEvent event) { Player player = event.getPlayer(); - + if (isWorldDisabled(player.getWorld().getName())) { return; } - + if (plugin.getConfig().getBoolean("join_leave_messages.enabled", true)) { String quitMessage = plugin.getConfig().getString("join_leave_messages.quit_message", ""); if (quitMessage.isEmpty()) { @@ -60,15 +84,15 @@ public class PlayerJoinListener implements Listener { } } } - + @EventHandler(priority = EventPriority.HIGHEST) public void onPlayerRespawn(PlayerRespawnEvent event) { Player player = event.getPlayer(); - + if (isWorldDisabled(player.getWorld().getName())) { return; } - + if (plugin.getConfig().getBoolean("spawn.teleport-on-respawn", true)) { Location spawn = plugin.getSpawnManager().getSpawn(); if (spawn != null) { @@ -76,18 +100,18 @@ public class PlayerJoinListener implements Listener { } } } - + @EventHandler(priority = EventPriority.LOWEST) public void onPlayerDeath(PlayerDeathEvent event) { if (isWorldDisabled(event.getPlayer().getWorld().getName())) { return; } - + if (plugin.getConfig().getBoolean("world_settings.disable_death_message", true)) { event.deathMessage(null); } } - + private void handleJoinMessage(PlayerJoinEvent event, Player player) { if (plugin.getConfig().getBoolean("join_leave_messages.enabled", true)) { String joinMessage = plugin.getConfig().getString("join_leave_messages.join_message", ""); @@ -98,7 +122,7 @@ public class PlayerJoinListener implements Listener { } } } - + private void handleJoinSettings(Player player) { if (plugin.getConfig().getBoolean("join_settings.spawn_join", true)) { Location spawn = plugin.getSpawnManager().getSpawn(); @@ -106,43 +130,43 @@ public class PlayerJoinListener implements Listener { player.teleport(spawn); } } - + if (plugin.getConfig().getBoolean("join_settings.heal", true)) { player.setHealth(player.getMaxHealth()); player.setFoodLevel(20); player.setSaturation(20); } - + if (plugin.getConfig().getBoolean("join_settings.extinguish", true)) { player.setFireTicks(0); } - + if (plugin.getConfig().getBoolean("join_settings.clear_inventory", false)) { player.getInventory().clear(); } } - + private void handleJoinEvents(Player player) { List actions = plugin.getConfig().getStringList("join_events"); if (!actions.isEmpty()) { plugin.getActionManager().executeActions(player, actions, false); } } - + private void handleFirework(Player player) { if (!plugin.getConfig().getBoolean("join_settings.firework.enabled", false)) { return; } - + boolean firstJoinOnly = plugin.getConfig().getBoolean("join_settings.firework.first_join_only", true); if (firstJoinOnly && player.hasPlayedBefore()) { return; } - + Location loc = player.getLocation(); - Firework firework = (Firework) loc.getWorld().spawnEntity(loc, EntityType.FIREWORK); + Firework firework = (Firework) loc.getWorld().spawnEntity(loc, EntityType.FIREWORK_ROCKET); FireworkMeta meta = firework.getFireworkMeta(); - + String typeStr = plugin.getConfig().getString("join_settings.firework.type", "BALL_LARGE"); FireworkEffect.Type type; try { @@ -150,7 +174,7 @@ public class PlayerJoinListener implements Listener { } catch (IllegalArgumentException e) { type = FireworkEffect.Type.BALL_LARGE; } - + List colors = new ArrayList<>(); for (String colorStr : plugin.getConfig().getStringList("join_settings.firework.colors")) { Color color = parseColor(colorStr); @@ -158,51 +182,32 @@ public class PlayerJoinListener implements Listener { colors.add(color); } } - + if (colors.isEmpty()) { colors.add(Color.AQUA); } - + FireworkEffect effect = FireworkEffect.builder() - .with(type) - .withColor(colors) - .flicker(plugin.getConfig().getBoolean("join_settings.firework.flicker", true)) - .trail(plugin.getConfig().getBoolean("join_settings.firework.trail", true)) - .build(); - + .with(type) + .withColor(colors) + .flicker(plugin.getConfig().getBoolean("join_settings.firework.flicker", true)) + .trail(plugin.getConfig().getBoolean("join_settings.firework.trail", true)) + .build(); + meta.addEffect(effect); meta.setPower(plugin.getConfig().getInt("join_settings.firework.power", 1)); firework.setFireworkMeta(meta); } - + private Color parseColor(String colorStr) { - return switch (colorStr.toUpperCase()) { - case "AQUA" -> Color.AQUA; - case "BLACK" -> Color.BLACK; - case "BLUE" -> Color.BLUE; - case "FUCHSIA" -> Color.FUCHSIA; - case "GRAY" -> Color.GRAY; - case "GREEN" -> Color.GREEN; - case "LIME" -> Color.LIME; - case "MAROON" -> Color.MAROON; - case "NAVY" -> Color.NAVY; - case "OLIVE" -> Color.OLIVE; - case "ORANGE" -> Color.ORANGE; - case "PURPLE" -> Color.PURPLE; - case "RED" -> Color.RED; - case "SILVER" -> Color.SILVER; - case "TEAL" -> Color.TEAL; - case "WHITE" -> Color.WHITE; - case "YELLOW" -> Color.YELLOW; - default -> null; - }; + return COLOR_MAP.get(colorStr.toUpperCase()); } - + private boolean isWorldDisabled(String worldName) { List disabledWorlds = plugin.getConfig().getStringList("disabled-worlds.worlds"); boolean invert = plugin.getConfig().getBoolean("disabled-worlds.invert", false); boolean isInList = disabledWorlds.contains(worldName); - + return invert ? !isInList : isInList; } } diff --git a/lohub/src/main/java/com/loki/lohub/managers/ActionManager.java b/lohub/src/main/java/com/loki/lohub/managers/ActionManager.java index dd44e17..d6b3c69 100644 --- a/lohub/src/main/java/com/loki/lohub/managers/ActionManager.java +++ b/lohub/src/main/java/com/loki/lohub/managers/ActionManager.java @@ -3,7 +3,16 @@ package com.loki.lohub.managers; import com.loki.lohub.LoHub; import com.loki.lohub.actions.Action; import com.loki.lohub.actions.ActionType; -import com.loki.lohub.actions.impl.*; +import com.loki.lohub.actions.impl.ActionbarAction; +import com.loki.lohub.actions.impl.BroadcastAction; +import com.loki.lohub.actions.impl.CloseAction; +import com.loki.lohub.actions.impl.CommandAction; +import com.loki.lohub.actions.impl.ConsoleAction; +import com.loki.lohub.actions.impl.EffectAction; +import com.loki.lohub.actions.impl.GamemodeAction; +import com.loki.lohub.actions.impl.MessageAction; +import com.loki.lohub.actions.impl.SoundAction; +import com.loki.lohub.actions.impl.TitleAction; import org.bukkit.entity.Player; import java.util.ArrayList; @@ -12,43 +21,43 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; public class ActionManager { - - private final LoHub plugin; + private static final Pattern ACTION_PATTERN = Pattern.compile("\\[([A-Z]+)]\\s*(.*)"); - + private final LoHub plugin; + public ActionManager(LoHub plugin) { this.plugin = plugin; } - + public List parseActions(List actionStrings) { List actions = new ArrayList<>(); - + for (String actionString : actionStrings) { Action action = parseAction(actionString); if (action != null) { actions.add(action); } } - + return actions; } - + public Action parseAction(String actionString) { if (actionString == null || actionString.isEmpty()) { return null; } - + Matcher matcher = ACTION_PATTERN.matcher(actionString); if (!matcher.matches()) { plugin.getLogger().warning("Invalid action format: " + actionString); return null; } - + String typeStr = matcher.group(1); String data = matcher.group(2); - + ActionType type = ActionType.fromString(typeStr); - + return switch (type) { case MESSAGE -> new MessageAction(data); case BROADCAST -> new BroadcastAction(data); @@ -66,7 +75,7 @@ public class ActionManager { } }; } - + public void executeActions(Player player, List actions) { for (Action action : actions) { try { @@ -77,7 +86,7 @@ public class ActionManager { } } } - + public void executeActions(Player player, List actionStrings, boolean parse) { if (parse) { List actions = parseActions(actionStrings); diff --git a/lohub/src/main/java/com/loki/lohub/managers/CooldownManager.java b/lohub/src/main/java/com/loki/lohub/managers/CooldownManager.java index c71ab53..fd99ba3 100644 --- a/lohub/src/main/java/com/loki/lohub/managers/CooldownManager.java +++ b/lohub/src/main/java/com/loki/lohub/managers/CooldownManager.java @@ -5,55 +5,55 @@ import java.util.Map; import java.util.UUID; public class CooldownManager { - + private final Map> cooldowns = new HashMap<>(); - + public void setCooldown(String key, UUID playerId, int seconds) { cooldowns.computeIfAbsent(key, k -> new HashMap<>()) - .put(playerId, System.currentTimeMillis() + (seconds * 1000L)); + .put(playerId, System.currentTimeMillis() + (seconds * 1000L)); } - + public boolean hasCooldown(String key, UUID playerId) { Map keyCooldowns = cooldowns.get(key); if (keyCooldowns == null) { return false; } - + Long expireTime = keyCooldowns.get(playerId); if (expireTime == null) { return false; } - + if (System.currentTimeMillis() >= expireTime) { keyCooldowns.remove(playerId); return false; } - + return true; } - + public int getRemainingSeconds(String key, UUID playerId) { Map keyCooldowns = cooldowns.get(key); if (keyCooldowns == null) { return 0; } - + Long expireTime = keyCooldowns.get(playerId); if (expireTime == null) { return 0; } - + long remaining = expireTime - System.currentTimeMillis(); return remaining > 0 ? (int) (remaining / 1000) : 0; } - + public void removeCooldown(String key, UUID playerId) { Map keyCooldowns = cooldowns.get(key); if (keyCooldowns != null) { keyCooldowns.remove(playerId); } } - + public void clearAll() { cooldowns.clear(); } diff --git a/lohub/src/main/java/com/loki/lohub/managers/RegionManager.java b/lohub/src/main/java/com/loki/lohub/managers/RegionManager.java index 51b465b..62ce09b 100644 --- a/lohub/src/main/java/com/loki/lohub/managers/RegionManager.java +++ b/lohub/src/main/java/com/loki/lohub/managers/RegionManager.java @@ -4,6 +4,8 @@ import com.loki.lohub.LoHub; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldguard.WorldGuard; +import com.sk89q.worldguard.protection.flags.Flags; +import com.sk89q.worldguard.protection.flags.StateFlag; import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion; import com.sk89q.worldguard.protection.regions.ProtectedRegion; import com.sk89q.worldguard.protection.regions.RegionContainer; @@ -11,105 +13,100 @@ import org.bukkit.Location; import org.bukkit.World; public class RegionManager { - - private final LoHub plugin; + private static final String HUB_REGION_NAME = "lohub_spawn"; - + private final LoHub plugin; + public RegionManager(LoHub plugin) { this.plugin = plugin; } - + public void createHubRegion() { if (!plugin.getConfig().getBoolean("worldguard.auto-create-region", true)) { plugin.getLogger().info("WorldGuard region auto-creation is disabled"); return; } - + if (!isWorldGuardAvailable()) { plugin.getLogger().warning("WorldGuard not found! Region will not be created."); return; } - + Location spawn = plugin.getSpawnManager().getSpawn(); if (spawn == null || spawn.getWorld() == null) { plugin.getLogger().warning("Spawn not set! Use /sethub"); return; } - + World world = spawn.getWorld(); int radius = plugin.getConfig().getInt("worldguard.region-radius", 100); - + try { RegionContainer container = WorldGuard.getInstance().getPlatform().getRegionContainer(); com.sk89q.worldguard.protection.managers.RegionManager wgRegionManager = container.get(BukkitAdapter.adapt(world)); - + if (wgRegionManager == null) { plugin.getLogger().warning("Failed to get RegionManager for world " + world.getName()); return; } - + ProtectedRegion existingRegion = wgRegionManager.getRegion(HUB_REGION_NAME); if (existingRegion != null) { plugin.getLogger().info("Region '" + HUB_REGION_NAME + "' already exists"); return; } - + BlockVector3 min = BlockVector3.at( - spawn.getBlockX() - radius, - world.getMinHeight(), - spawn.getBlockZ() - radius + spawn.getBlockX() - radius, + world.getMinHeight(), + spawn.getBlockZ() - radius ); - + BlockVector3 max = BlockVector3.at( - spawn.getBlockX() + radius, - world.getMaxHeight(), - spawn.getBlockZ() + radius + spawn.getBlockX() + radius, + world.getMaxHeight(), + spawn.getBlockZ() + radius ); - + ProtectedCuboidRegion region = new ProtectedCuboidRegion(HUB_REGION_NAME, min, max); - - region.setFlag(com.sk89q.worldguard.protection.flags.Flags.PVP, - com.sk89q.worldguard.protection.flags.StateFlag.State.DENY); - region.setFlag(com.sk89q.worldguard.protection.flags.Flags.BLOCK_BREAK, - com.sk89q.worldguard.protection.flags.StateFlag.State.DENY); - region.setFlag(com.sk89q.worldguard.protection.flags.Flags.BLOCK_PLACE, - com.sk89q.worldguard.protection.flags.StateFlag.State.DENY); - region.setFlag(com.sk89q.worldguard.protection.flags.Flags.DAMAGE_ANIMALS, - com.sk89q.worldguard.protection.flags.StateFlag.State.DENY); - region.setFlag(com.sk89q.worldguard.protection.flags.Flags.MOB_SPAWNING, - com.sk89q.worldguard.protection.flags.StateFlag.State.DENY); - region.setFlag(com.sk89q.worldguard.protection.flags.Flags.LEAF_DECAY, - com.sk89q.worldguard.protection.flags.StateFlag.State.DENY); - region.setFlag(com.sk89q.worldguard.protection.flags.Flags.ITEM_DROP, - com.sk89q.worldguard.protection.flags.StateFlag.State.DENY); - region.setFlag(com.sk89q.worldguard.protection.flags.Flags.ITEM_PICKUP, - com.sk89q.worldguard.protection.flags.StateFlag.State.DENY); - + setRegionFlags(region); + wgRegionManager.addRegion(region); - + plugin.getLogger().info("Region '" + HUB_REGION_NAME + "' created around spawn (radius: " + radius + " blocks)"); plugin.getLogger().info("Coordinates: " + min + " -> " + max); - + } catch (Exception e) { plugin.getLogger().severe("Error creating WorldGuard region: " + e.getMessage()); e.printStackTrace(); } } - + + private void setRegionFlags(ProtectedCuboidRegion region) { + region.setFlag(Flags.PVP, StateFlag.State.DENY); + region.setFlag(Flags.BLOCK_BREAK, StateFlag.State.DENY); + region.setFlag(Flags.BLOCK_PLACE, StateFlag.State.DENY); + region.setFlag(Flags.DAMAGE_ANIMALS, StateFlag.State.DENY); + region.setFlag(Flags.MOB_SPAWNING, StateFlag.State.DENY); + region.setFlag(Flags.LEAF_DECAY, StateFlag.State.DENY); + region.setFlag(Flags.ITEM_DROP, StateFlag.State.DENY); + region.setFlag(Flags.ITEM_PICKUP, StateFlag.State.DENY); + } + public void deleteHubRegion() { if (!isWorldGuardAvailable()) { return; } - + Location spawn = plugin.getSpawnManager().getSpawn(); if (spawn == null || spawn.getWorld() == null) { return; } - + try { RegionContainer container = WorldGuard.getInstance().getPlatform().getRegionContainer(); com.sk89q.worldguard.protection.managers.RegionManager wgRegionManager = container.get(BukkitAdapter.adapt(spawn.getWorld())); - + if (wgRegionManager != null) { wgRegionManager.removeRegion(HUB_REGION_NAME); plugin.getLogger().info("Region '" + HUB_REGION_NAME + "' deleted"); @@ -118,7 +115,7 @@ public class RegionManager { plugin.getLogger().severe("Error deleting region: " + e.getMessage()); } } - + private boolean isWorldGuardAvailable() { try { Class.forName("com.sk89q.worldguard.WorldGuard"); diff --git a/lohub/src/main/java/com/loki/lohub/managers/SpawnManager.java b/lohub/src/main/java/com/loki/lohub/managers/SpawnManager.java index bea7974..3effc29 100644 --- a/lohub/src/main/java/com/loki/lohub/managers/SpawnManager.java +++ b/lohub/src/main/java/com/loki/lohub/managers/SpawnManager.java @@ -12,18 +12,18 @@ import java.io.File; import java.io.IOException; public class SpawnManager { - + private final LoHub plugin; private final File spawnFile; private FileConfiguration spawnConfig; private Location spawnLocation; - + public SpawnManager(LoHub plugin) { this.plugin = plugin; this.spawnFile = new File(plugin.getDataFolder(), "spawn.yml"); loadSpawn(); } - + private void loadSpawn() { if (!spawnFile.exists()) { try { @@ -32,9 +32,9 @@ public class SpawnManager { plugin.getLogger().severe("Failed to create spawn.yml: " + e.getMessage()); } } - + spawnConfig = YamlConfiguration.loadConfiguration(spawnFile); - + if (spawnConfig.contains("spawn")) { String worldName = spawnConfig.getString("spawn.world"); double x = spawnConfig.getDouble("spawn.x"); @@ -42,7 +42,7 @@ public class SpawnManager { double z = spawnConfig.getDouble("spawn.z"); float yaw = (float) spawnConfig.getDouble("spawn.yaw"); float pitch = (float) spawnConfig.getDouble("spawn.pitch"); - + World world = Bukkit.getWorld(worldName); if (world != null) { spawnLocation = new Location(world, x, y, z, yaw, pitch); @@ -52,35 +52,35 @@ public class SpawnManager { } } } - + + public Location getSpawn() { + return spawnLocation; + } + public void setSpawn(Location location) { this.spawnLocation = location; - + spawnConfig.set("spawn.world", location.getWorld().getName()); spawnConfig.set("spawn.x", location.getX()); spawnConfig.set("spawn.y", location.getY()); spawnConfig.set("spawn.z", location.getZ()); spawnConfig.set("spawn.yaw", location.getYaw()); spawnConfig.set("spawn.pitch", location.getPitch()); - + try { spawnConfig.save(spawnFile); - plugin.getLogger().info("Spawn set: " + location.getWorld().getName() + - " (" + location.getBlockX() + ", " + location.getBlockY() + ", " + location.getBlockZ() + ")"); + plugin.getLogger().info("Spawn set: " + location.getWorld().getName() + + " (" + location.getBlockX() + ", " + location.getBlockY() + ", " + location.getBlockZ() + ")"); } catch (IOException e) { plugin.getLogger().severe("Failed to save spawn.yml: " + e.getMessage()); } } - - public Location getSpawn() { - return spawnLocation; - } - + public void teleportToSpawn(Player player) { if (spawnLocation == null) { return; } - + player.teleport(spawnLocation); } } diff --git a/lohub/src/main/java/com/loki/lohub/utils/ItemBuilder.java b/lohub/src/main/java/com/loki/lohub/utils/ItemBuilder.java index 5972bb1..01763f8 100644 --- a/lohub/src/main/java/com/loki/lohub/utils/ItemBuilder.java +++ b/lohub/src/main/java/com/loki/lohub/utils/ItemBuilder.java @@ -9,83 +9,83 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.SkullMeta; -import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; public class ItemBuilder { - + private final ItemStack itemStack; - + public ItemBuilder(Material material) { this.itemStack = new ItemStack(material); } - + public ItemBuilder(ItemStack itemStack) { this.itemStack = itemStack.clone(); } - + public static ItemBuilder fromConfig(ConfigurationSection section) { return fromConfig(section, null); } - + public static ItemBuilder fromConfig(ConfigurationSection section, Player player) { String materialName = section.getString("material", "STONE").toUpperCase(); Material material; - + try { material = Material.valueOf(materialName); } catch (IllegalArgumentException e) { material = Material.STONE; } - + ItemBuilder builder = new ItemBuilder(material); - + if (section.contains("amount")) { builder.amount(section.getInt("amount", 1)); } - + if (section.contains("display_name")) { String name = section.getString("display_name"); builder.name(player != null ? PlaceholderUtil.parse(name, player) : name); } - + if (section.contains("lore")) { List lore = section.getStringList("lore"); - builder.lore(player != null ? - lore.stream().map(line -> PlaceholderUtil.parse(line, player)).collect(Collectors.toList()) : - lore); + builder.lore(player != null ? + lore.stream().map(line -> PlaceholderUtil.parse(line, player)).collect(Collectors.toList()) : + lore); } - + if (section.contains("glow") && section.getBoolean("glow")) { builder.glow(); } - + if (section.contains("custom_model_data")) { builder.customModelData(section.getInt("custom_model_data")); } - + if (section.contains("item_flags")) { section.getStringList("item_flags").forEach(flagName -> { try { builder.flag(ItemFlag.valueOf(flagName.toUpperCase())); - } catch (IllegalArgumentException ignored) {} + } catch (IllegalArgumentException ignored) { + } }); } - + if (material == Material.PLAYER_HEAD && section.contains("skull_owner")) { String owner = section.getString("skull_owner"); builder.skullOwner(player != null ? owner.replace("%player%", player.getName()) : owner); } - + return builder; } - + public ItemBuilder amount(int amount) { itemStack.setAmount(Math.max(1, amount)); return this; } - + public ItemBuilder name(String name) { ItemMeta meta = itemStack.getItemMeta(); if (meta != null) { @@ -94,23 +94,23 @@ public class ItemBuilder { } return this; } - + public ItemBuilder lore(List lore) { ItemMeta meta = itemStack.getItemMeta(); if (meta != null) { List coloredLore = lore.stream() - .map(TextUtil::colorize) - .collect(Collectors.toList()); + .map(TextUtil::colorize) + .collect(Collectors.toList()); meta.setLore(coloredLore); itemStack.setItemMeta(meta); } return this; } - + public ItemBuilder lore(String... lines) { return lore(List.of(lines)); } - + public ItemBuilder flag(ItemFlag... flags) { ItemMeta meta = itemStack.getItemMeta(); if (meta != null) { @@ -119,17 +119,17 @@ public class ItemBuilder { } return this; } - + public ItemBuilder glow() { ItemMeta meta = itemStack.getItemMeta(); if (meta != null) { - meta.addEnchant(Enchantment.LUCK, 1, true); + meta.addEnchant(Enchantment.UNBREAKING, 1, true); meta.addItemFlags(ItemFlag.HIDE_ENCHANTS); itemStack.setItemMeta(meta); } return this; } - + public ItemBuilder customModelData(int data) { ItemMeta meta = itemStack.getItemMeta(); if (meta != null) { @@ -138,7 +138,7 @@ public class ItemBuilder { } return this; } - + public ItemBuilder skullOwner(String owner) { if (itemStack.getType() == Material.PLAYER_HEAD) { SkullMeta meta = (SkullMeta) itemStack.getItemMeta(); @@ -149,7 +149,7 @@ public class ItemBuilder { } return this; } - + public ItemStack build() { return itemStack; } diff --git a/lohub/src/main/java/com/loki/lohub/utils/PlaceholderUtil.java b/lohub/src/main/java/com/loki/lohub/utils/PlaceholderUtil.java index 2e3f9f1..191fce2 100644 --- a/lohub/src/main/java/com/loki/lohub/utils/PlaceholderUtil.java +++ b/lohub/src/main/java/com/loki/lohub/utils/PlaceholderUtil.java @@ -6,49 +6,53 @@ import org.bukkit.Location; import org.bukkit.entity.Player; public class PlaceholderUtil { - + private static boolean placeholderAPIEnabled = false; - + + private PlaceholderUtil() { + // Utility class - prevent instantiation + } + public static void init() { placeholderAPIEnabled = Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI"); } - + public static String parse(String text, Player player) { if (text == null) { return ""; } - + text = parseInternalPlaceholders(text, player); - + if (placeholderAPIEnabled && player != null) { text = PlaceholderAPI.setPlaceholders(player, text); } - + return text; } - + private static String parseInternalPlaceholders(String text, Player player) { if (player != null) { text = text.replace("%player%", player.getName()); text = text.replace("%player_displayname%", player.getDisplayName()); - + if (text.contains("%location%")) { Location loc = player.getLocation(); - text = text.replace("%location%", - loc.getBlockX() + ", " + loc.getBlockY() + ", " + loc.getBlockZ()); + text = text.replace("%location%", + loc.getBlockX() + ", " + loc.getBlockY() + ", " + loc.getBlockZ()); } - + if (text.contains("%world%")) { text = text.replace("%world%", player.getWorld().getName()); } } - + text = text.replace("%online%", String.valueOf(Bukkit.getOnlinePlayers().size())); text = text.replace("%online_max%", String.valueOf(Bukkit.getMaxPlayers())); - + return text; } - + public static boolean isPlaceholderAPIEnabled() { return placeholderAPIEnabled; } diff --git a/lohub/src/main/java/com/loki/lohub/utils/TextUtil.java b/lohub/src/main/java/com/loki/lohub/utils/TextUtil.java index 0ab841f..542ecc9 100644 --- a/lohub/src/main/java/com/loki/lohub/utils/TextUtil.java +++ b/lohub/src/main/java/com/loki/lohub/utils/TextUtil.java @@ -8,49 +8,53 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; public class TextUtil { - + private static final Pattern HEX_PATTERN = Pattern.compile("&#([A-Fa-f0-9]{6})"); - + + private TextUtil() { + // Utility class - prevent instantiation + } + public static String colorize(String text) { if (text == null || text.isEmpty()) { return text; } - + text = translateHexCodes(text); text = ChatColor.translateAlternateColorCodes('&', text); - + return text; } - + public static List colorize(List lines) { return lines.stream() - .map(TextUtil::colorize) - .collect(Collectors.toList()); + .map(TextUtil::colorize) + .collect(Collectors.toList()); } - + private static String translateHexCodes(String text) { Matcher matcher = HEX_PATTERN.matcher(text); StringBuffer buffer = new StringBuffer(); - + while (matcher.find()) { String hexCode = matcher.group(1); String replacement = ChatColor.of("#" + hexCode).toString(); matcher.appendReplacement(buffer, replacement); } - + matcher.appendTail(buffer); return buffer.toString(); } - + public static String strip(String text) { return ChatColor.stripColor(text); } - + public static String joinFrom(int startIndex, String[] args) { if (args == null || startIndex >= args.length) { return ""; } - + StringBuilder builder = new StringBuilder(); for (int i = startIndex; i < args.length; i++) { builder.append(args[i]); @@ -58,15 +62,15 @@ public class TextUtil { builder.append(" "); } } - + return builder.toString(); } - + public static String listToString(List list) { if (list == null || list.isEmpty()) { return ""; } - + return String.join("\n", list); } } diff --git a/lohub/src/main/resources/plugin.yml b/lohub/src/main/resources/plugin.yml index 4628887..7d2717a 100644 --- a/lohub/src/main/resources/plugin.yml +++ b/lohub/src/main/resources/plugin.yml @@ -15,13 +15,13 @@ commands: description: Teleport to spawn usage: /hub permission: lohub.hub - aliases: [spawn, хаб, спавн] + aliases: [ spawn, хаб, спавн ] sethub: description: Set hub spawn location usage: /sethub permission: lohub.admin - aliases: [setspawn, установитьспавн] + aliases: [ setspawn, установитьспавн ] lohub: description: LoHub admin command diff --git a/lovelocity/build.gradle.kts b/lovelocity/build.gradle.kts index 5640933..923dbb6 100644 --- a/lovelocity/build.gradle.kts +++ b/lovelocity/build.gradle.kts @@ -1,5 +1,6 @@ plugins { java + checkstyle } repositories { @@ -12,7 +13,7 @@ dependencies { compileOnly("com.velocitypowered:velocity-api:3.3.0-SNAPSHOT") annotationProcessor("com.velocitypowered:velocity-api:3.3.0-SNAPSHOT") implementation("com.google.code.gson:gson:2.10.1") - + testImplementation("org.junit.jupiter:junit-jupiter-api:5.10.0") testImplementation("org.junit.jupiter:junit-jupiter-engine:5.10.0") testRuntimeOnly("org.junit.platform:junit-platform-launcher:1.10.0") @@ -23,3 +24,17 @@ tasks.jar { from(configurations.runtimeClasspath.get().map { if (it.isDirectory) it else zipTree(it) }) duplicatesStrategy = DuplicatesStrategy.EXCLUDE } + +checkstyle { + toolVersion = "10.12.5" + configFile = file("${rootProject.rootDir}/config/checkstyle/checkstyle.xml") + isIgnoreFailures = false + maxWarnings = 0 +} + +tasks.withType { + reports { + xml.required.set(false) + html.required.set(true) + } +} diff --git a/lovelocity/src/main/java/com/loki/lovelocity/LoVelocity.java b/lovelocity/src/main/java/com/loki/lovelocity/LoVelocity.java index 8cd814b..6667201 100644 --- a/lovelocity/src/main/java/com/loki/lovelocity/LoVelocity.java +++ b/lovelocity/src/main/java/com/loki/lovelocity/LoVelocity.java @@ -13,52 +13,52 @@ import org.slf4j.Logger; import java.nio.file.Path; @Plugin( - id = "lovelocity", - name = "LoVelocity", - version = "1.5.5", - description = "Velocity integration for LoNetwork", - authors = {"loki"} + id = "lovelocity", + name = "LoVelocity", + version = "1.5.5", + description = "Velocity integration for LoNetwork", + authors = {"loki"} ) public class LoVelocity { - + private final ProxyServer server; private final Logger logger; private final Path dataDirectory; - + @Inject public LoVelocity(ProxyServer server, Logger logger, @DataDirectory Path dataDirectory) { this.server = server; this.logger = logger; this.dataDirectory = dataDirectory; } - + @Subscribe public void onProxyInitialization(ProxyInitializeEvent event) { logger.info("LoVelocity loaded!"); logger.info("Version: 1.5.5"); - + registerCommands(); } - + private void registerCommands() { CommandMeta hubMeta = server.getCommandManager().metaBuilder("hub") - .aliases("lobby") - .plugin(this) - .build(); - + .aliases("lobby") + .plugin(this) + .build(); + server.getCommandManager().register(hubMeta, new HubCommand(this)); - + logger.info("Commands registered: /hub, /lobby"); } - + public ProxyServer getServer() { return server; } - + public Logger getLogger() { return logger; } - + public Path getDataDirectory() { return dataDirectory; } diff --git a/lovelocity/src/main/java/com/loki/lovelocity/commands/HubCommand.java b/lovelocity/src/main/java/com/loki/lovelocity/commands/HubCommand.java index 6233c7f..762eaef 100644 --- a/lovelocity/src/main/java/com/loki/lovelocity/commands/HubCommand.java +++ b/lovelocity/src/main/java/com/loki/lovelocity/commands/HubCommand.java @@ -12,66 +12,66 @@ import java.util.Optional; import java.util.concurrent.CompletableFuture; public class HubCommand implements SimpleCommand { - + private final LoVelocity plugin; private final List hubServers = List.of("hub", "lobby"); - + public HubCommand(LoVelocity plugin) { this.plugin = plugin; } - + @Override public void execute(Invocation invocation) { if (!(invocation.source() instanceof Player player)) { invocation.source().sendMessage(Component.text("This command is only for players!", NamedTextColor.RED)); return; } - + Optional currentServer = player.getCurrentServer().map(s -> s.getServer()); - + if (currentServer.isEmpty()) { player.sendMessage(Component.text("Failed to determine current server!", NamedTextColor.RED)); return; } - + String currentServerName = currentServer.get().getServerInfo().getName().toLowerCase(); - + if (isHubServer(currentServerName)) { player.sendMessage(Component.text("You are already on the hub!", NamedTextColor.YELLOW)); return; } - + Optional hubServer = findHubServer(); - + if (hubServer.isEmpty()) { player.sendMessage(Component.text("Hub server not found!", NamedTextColor.RED)); - plugin.getLogger().warn("Hub server not found! Available servers: " + - plugin.getServer().getAllServers().stream() - .map(s -> s.getServerInfo().getName()) - .toList()); + plugin.getLogger().warn("Hub server not found! Available servers: " + + plugin.getServer().getAllServers().stream() + .map(s -> s.getServerInfo().getName()) + .toList()); return; } - + player.sendMessage(Component.text("Teleporting to hub...", NamedTextColor.GREEN)); - + player.createConnectionRequest(hubServer.get()).fireAndForget(); } - + private boolean isHubServer(String serverName) { return hubServers.stream().anyMatch(hub -> serverName.contains(hub)); } - + private Optional findHubServer() { return plugin.getServer().getAllServers().stream() - .filter(server -> isHubServer(server.getServerInfo().getName().toLowerCase())) - .findFirst(); + .filter(server -> isHubServer(server.getServerInfo().getName().toLowerCase())) + .findFirst(); } - + @Override public CompletableFuture> suggestAsync(Invocation invocation) { return CompletableFuture.completedFuture(List.of()); } - + @Override public boolean hasPermission(Invocation invocation) { return invocation.source().hasPermission("lovelocity.hub"); diff --git a/src/main/java/com/loki/lochat/LoChat.java b/src/main/java/com/loki/lochat/LoChat.java index 3d9ead2..fe40073 100644 --- a/src/main/java/com/loki/lochat/LoChat.java +++ b/src/main/java/com/loki/lochat/LoChat.java @@ -31,71 +31,76 @@ public final class LoChat extends JavaPlugin { private AutoMessageManager autoMessageManager; private CustomCommandManager customCommandManager; + // Геттеры + public static LoChat getInstance() { + return instance; + } + @Override public void onEnable() { instance = this; getLogger().info("Загрузка LoChat v" + getPluginMeta().getVersion() + " для Paper/Folia " + Bukkit.getMinecraftVersion() + "..."); - + // Конфиги configManager = new ConfigManager(this); messageConfig = new MessageConfig(this); - + // Service Registry (SOLID DI) - с зависимостями - serviceRegistry = new ServiceRegistry(this, configManager, messageConfig); + serviceRegistry = ServiceRegistry.createWithDeps(this, configManager, messageConfig); getLogger().info("ServiceRegistry инициализирован (SOLID DI)"); - + // Менеджеры - customCommandManager = new CustomCommandManager(this); + customCommandManager = CustomCommandManager.create(this); autoMessageManager = new AutoMessageManager(this); - + // Интеграции initIntegrations(); - + // Команды и слушатели registerCommands(); registerListeners(); - + // Автосообщения autoMessageManager.start(); - + getLogger().info("LoChat успешно запущен!"); } @Override public void onDisable() { if (autoMessageManager != null) autoMessageManager.stop(); - + // Сохранение данных через сервисы IgnoreService ignoreService = serviceRegistry.get(IgnoreService.class); if (ignoreService != null) ignoreService.save(); - + MuteService muteService = serviceRegistry.get(MuteService.class); if (muteService != null) muteService.save(); - + NickService nickService = serviceRegistry.get(NickService.class); if (nickService != null) nickService.save(); - + if (gradientModule != null) gradientModule.shutdown(); getLogger().info("LoChat отключен!"); } - + private void initIntegrations() { // Gradient модуль gradientModule = new GradientModule(this); if (gradientModule.init()) { getLogger().info("Gradient модуль (LoPreff) загружен!"); } - + // LibertyBans new LibertyBansHook(this); - + // PlaceholderAPI if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) { new PlaceholderAPIHook(this).register(); getLogger().info("PlaceholderAPI подключен!"); } } - + private void registerCommands() { getCommand("g").setExecutor(new GlobalChatCommand(this)); getCommand("l").setExecutor(new LocalChatCommand(this)); @@ -106,44 +111,44 @@ public final class LoChat extends JavaPlugin { getCommand("announce").setExecutor(new AnnounceCommand(this)); getCommand("chatspy").setExecutor(new ChatSpyCommand(this)); getCommand("clearchat").setExecutor(new ClearChatCommand(this)); - + NickCommand nickCmd = new NickCommand(this); getCommand("nick").setExecutor(nickCmd); getCommand("nick").setTabCompleter(nickCmd); - + LoChatCommand loChatCmd = new LoChatCommand(this); getCommand("lochat").setExecutor(loChatCmd); getCommand("lochat").setTabCompleter(loChatCmd); - + MuteCommand muteCmd = new MuteCommand(this); getCommand("lmute").setExecutor(muteCmd); getCommand("lmute").setTabCompleter(muteCmd); - + UnmuteCommand unmuteCmd = new UnmuteCommand(this); getCommand("lunmute").setExecutor(unmuteCmd); getCommand("lunmute").setTabCompleter(unmuteCmd); - + getCommand("lmutelist").setExecutor(new MuteListCommand(this)); - + MuteHistoryCommand historyCmd = new MuteHistoryCommand(this); getCommand("lmutehistory").setExecutor(historyCmd); getCommand("lmutehistory").setTabCompleter(historyCmd); - + MuteBlameCommand blameCmd = new MuteBlameCommand(this); getCommand("lmuteblame").setExecutor(blameCmd); getCommand("lmuteblame").setTabCompleter(blameCmd); - + ClearChatConfigCommand clearCfgCmd = new ClearChatConfigCommand(this); getCommand("clearchatconfig").setExecutor(clearCfgCmd); getCommand("clearchatconfig").setTabCompleter(clearCfgCmd); } - + private void registerListeners() { getServer().getPluginManager().registerEvents(new ChatEventListener(this, serviceRegistry), this); getServer().getPluginManager().registerEvents(new PlayerEventListener(serviceRegistry), this); getLogger().info("Слушатели зарегистрированы (новая архитектура)"); } - + public void reload() { configManager.reload(); messageConfig.reload(); @@ -152,11 +157,23 @@ public final class LoChat extends JavaPlugin { if (customCommandManager != null) customCommandManager.reload(); } - // Геттеры - public static LoChat getInstance() { return instance; } - public ServiceRegistry getServiceRegistry() { return serviceRegistry; } - public ConfigManager getConfigManager() { return configManager; } - public MessageConfig getMessageConfig() { return messageConfig; } - public GradientModule getGradientModule() { return gradientModule; } - public CustomCommandManager getCustomCommandManager() { return customCommandManager; } + public ServiceRegistry getServiceRegistry() { + return serviceRegistry; + } + + public ConfigManager getConfigManager() { + return configManager; + } + + public MessageConfig getMessageConfig() { + return messageConfig; + } + + public GradientModule getGradientModule() { + return gradientModule; + } + + public CustomCommandManager getCustomCommandManager() { + return customCommandManager; + } } diff --git a/src/main/java/com/loki/lochat/api/ChatService.java b/src/main/java/com/loki/lochat/api/ChatService.java index 6847f4c..232b0c4 100644 --- a/src/main/java/com/loki/lochat/api/ChatService.java +++ b/src/main/java/com/loki/lochat/api/ChatService.java @@ -7,7 +7,10 @@ import org.bukkit.entity.Player; */ public interface ChatService { void sendGlobalMessage(Player sender, Object message); + void sendLocalMessage(Player sender, Object message); + boolean toggleGlobalChat(java.util.UUID player); + boolean isGlobalChatDisabled(java.util.UUID player); } diff --git a/src/main/java/com/loki/lochat/api/CooldownService.java b/src/main/java/com/loki/lochat/api/CooldownService.java index 181d831..1f11b33 100644 --- a/src/main/java/com/loki/lochat/api/CooldownService.java +++ b/src/main/java/com/loki/lochat/api/CooldownService.java @@ -7,7 +7,10 @@ import java.util.UUID; */ public interface CooldownService { boolean isOnCooldown(UUID player, String type, int cooldownSeconds); + int getRemainingCooldown(UUID player, String type, int cooldownSeconds); + void setCooldown(UUID player, String type); + void removeCooldown(UUID player); } diff --git a/src/main/java/com/loki/lochat/api/MessageFilter.java b/src/main/java/com/loki/lochat/api/MessageFilter.java index 6fafa2b..725f3ad 100644 --- a/src/main/java/com/loki/lochat/api/MessageFilter.java +++ b/src/main/java/com/loki/lochat/api/MessageFilter.java @@ -8,6 +8,7 @@ import org.bukkit.entity.Player; public interface MessageFilter { /** * Применить фильтр к сообщению + * * @return отфильтрованное сообщение или null если заблокировано */ Object apply(Player player, Object message, String plainMessage); diff --git a/src/main/java/com/loki/lochat/api/MuteService.java b/src/main/java/com/loki/lochat/api/MuteService.java index 9e594d4..0758051 100644 --- a/src/main/java/com/loki/lochat/api/MuteService.java +++ b/src/main/java/com/loki/lochat/api/MuteService.java @@ -7,9 +7,14 @@ import java.util.UUID; */ public interface MuteService { void mute(UUID uuid, String playerName, long duration, String reason, String mutedBy); + boolean unmute(UUID uuid, String unmutedBy); + boolean isMuted(UUID uuid); + long getRemainingTime(UUID uuid); + String formatTime(long millis); + long parseTime(String timeStr); } diff --git a/src/main/java/com/loki/lochat/api/filter/MessageFilter.java b/src/main/java/com/loki/lochat/api/filter/MessageFilter.java index f2d5d59..93f0ddb 100644 --- a/src/main/java/com/loki/lochat/api/filter/MessageFilter.java +++ b/src/main/java/com/loki/lochat/api/filter/MessageFilter.java @@ -9,6 +9,7 @@ import org.bukkit.entity.Player; public interface MessageFilter { /** * Применить фильтр к сообщению + * * @return true если сообщение прошло фильтр, false если заблокировано */ boolean apply(Player player, ChatMessage message); diff --git a/src/main/java/com/loki/lochat/api/service/ChatService.java b/src/main/java/com/loki/lochat/api/service/ChatService.java index 5f6ca7d..721535c 100644 --- a/src/main/java/com/loki/lochat/api/service/ChatService.java +++ b/src/main/java/com/loki/lochat/api/service/ChatService.java @@ -9,7 +9,10 @@ import java.util.UUID; */ public interface ChatService { void sendGlobalMessage(Player sender, Object message); + void sendLocalMessage(Player sender, Object message); + boolean toggleGlobalChat(UUID player); + boolean isGlobalChatDisabled(UUID player); } diff --git a/src/main/java/com/loki/lochat/api/service/CooldownService.java b/src/main/java/com/loki/lochat/api/service/CooldownService.java index f41bc07..651861d 100644 --- a/src/main/java/com/loki/lochat/api/service/CooldownService.java +++ b/src/main/java/com/loki/lochat/api/service/CooldownService.java @@ -7,7 +7,10 @@ import java.util.UUID; */ public interface CooldownService { boolean isOnCooldown(UUID player, String type, int cooldownSeconds); + int getRemainingCooldown(UUID player, String type, int cooldownSeconds); + void setCooldown(UUID player, String type); + void removeCooldown(UUID player); } diff --git a/src/main/java/com/loki/lochat/api/service/IgnoreService.java b/src/main/java/com/loki/lochat/api/service/IgnoreService.java index 5fcc777..56a073e 100644 --- a/src/main/java/com/loki/lochat/api/service/IgnoreService.java +++ b/src/main/java/com/loki/lochat/api/service/IgnoreService.java @@ -11,39 +11,41 @@ public interface IgnoreService { * Проверяет, игнорирует ли игрок другого */ boolean isIgnoring(UUID player, UUID target); - + /** * Добавляет игрока в список игнорируемых + * * @return true если успешно добавлен */ boolean addIgnore(UUID player, UUID target); - + /** * Удаляет игрока из списка игнорируемых + * * @return true если успешно удалён */ boolean removeIgnore(UUID player, UUID target); - + /** * Получает список всех игнорируемых игроков */ Set getIgnoredPlayers(UUID player); - + /** * Получает количество игнорируемых игроков */ int getIgnoredCount(UUID player); - + /** * Очищает список игнорируемых для игрока */ void clearIgnores(UUID player); - + /** * Сохраняет данные на диск */ void save(); - + /** * Загружает данные с диска */ diff --git a/src/main/java/com/loki/lochat/api/service/MentionService.java b/src/main/java/com/loki/lochat/api/service/MentionService.java index f3783a0..f8cac9c 100644 --- a/src/main/java/com/loki/lochat/api/service/MentionService.java +++ b/src/main/java/com/loki/lochat/api/service/MentionService.java @@ -10,26 +10,27 @@ import java.util.Set; public interface MentionService { /** * Обрабатывает упоминания в сообщении + * * @return сообщение с подсвеченными никами */ String processMentions(String message, Set mentionedPlayers); - + /** * Создаёт персонализированное сообщение для игрока * Если его ник упомянут — выделяет его особым образом */ String getPersonalizedMessage(String message, Player viewer); - + /** * Проверяет, упомянут ли игрок в сообщении (по нику без @) */ boolean isPlayerMentioned(String message, Player player); - + /** * Уведомляет упомянутых игроков звуком */ void notifyMentioned(Set players); - + /** * Уведомляет игрока если его ник упомянут (без @) */ diff --git a/src/main/java/com/loki/lochat/api/service/MessageService.java b/src/main/java/com/loki/lochat/api/service/MessageService.java index c803f91..6dcda75 100644 --- a/src/main/java/com/loki/lochat/api/service/MessageService.java +++ b/src/main/java/com/loki/lochat/api/service/MessageService.java @@ -8,6 +8,7 @@ import org.bukkit.entity.Player; public interface MessageService { /** * Обработать входящее сообщение чата + * * @return true если сообщение обработано успешно */ boolean processMessage(Player player, String message); diff --git a/src/main/java/com/loki/lochat/api/service/MuteService.java b/src/main/java/com/loki/lochat/api/service/MuteService.java index fc8a395..02f09b4 100644 --- a/src/main/java/com/loki/lochat/api/service/MuteService.java +++ b/src/main/java/com/loki/lochat/api/service/MuteService.java @@ -13,30 +13,38 @@ import java.util.UUID; public interface MuteService { // Основные операции void mute(UUID uuid, String playerName, long duration, String reason, String mutedBy); + boolean unmute(UUID uuid, String unmutedBy); + boolean isMuted(UUID uuid); + MuteData getMuteData(UUID uuid); + long getRemainingTime(UUID uuid); - + // Утилиты времени String formatTime(long millis); + long parseTime(String timeStr); - + // Права доступа long getMaxDuration(Player player); + boolean canMuteForDuration(Player player, long duration); - + // История List getPlayerHistory(UUID uuid); + List getMutesByOperator(String operatorName); + UUID getUUIDByName(String name); - + // Список активных мутов Map getActiveMutes(); - + // Форматирование сообщений String formatMessage(String message, String player, String operator, String duration, String reason); - + // Сохранение void save(); } diff --git a/src/main/java/com/loki/lochat/api/service/NickService.java b/src/main/java/com/loki/lochat/api/service/NickService.java index f7600ab..b4e5e6b 100644 --- a/src/main/java/com/loki/lochat/api/service/NickService.java +++ b/src/main/java/com/loki/lochat/api/service/NickService.java @@ -9,48 +9,54 @@ import java.util.UUID; * Сервис для управления кастомными никами */ public interface NickService { - + /** * Устанавливает кастомный ник игроку - * @param player UUID игрока + * + * @param player UUID игрока * @param nickname Новый ник (с поддержкой цветов и русских символов) * @return true если успешно, false если ник занят или невалиден */ boolean setNickname(UUID player, String nickname); - + /** * Сбрасывает кастомный ник игрока + * * @param player UUID игрока */ void resetNickname(UUID player); - + /** * Получает кастомный ник игрока + * * @param player UUID игрока * @return Optional с ником или empty если нет кастомного ника */ Optional getNickname(UUID player); - + /** * Проверяет занят ли ник + * * @param nickname Ник для проверки * @return true если ник уже используется */ boolean isNicknameTaken(String nickname); - + /** * Валидирует ник (длина, символы) + * * @param nickname Ник для проверки * @return true если ник валиден */ boolean isValidNickname(String nickname); - + /** * Обновляет displayName и tabName игрока + * * @param player Игрок */ void updatePlayerDisplay(Player player); - + /** * Сохраняет данные */ diff --git a/src/main/java/com/loki/lochat/api/service/PMService.java b/src/main/java/com/loki/lochat/api/service/PMService.java index 805e5f5..2ed3421 100644 --- a/src/main/java/com/loki/lochat/api/service/PMService.java +++ b/src/main/java/com/loki/lochat/api/service/PMService.java @@ -11,17 +11,17 @@ public interface PMService { * Устанавливает последнего собеседника для игрока */ void setLastConversation(UUID player, UUID target); - + /** * Получает последнего собеседника игрока */ Optional getLastConversation(UUID player); - + /** * Удаляет информацию о последнем разговоре */ void removeConversation(UUID player); - + /** * Проверяет, есть ли у игрока активный разговор */ diff --git a/src/main/java/com/loki/lochat/api/service/PlayerDataService.java b/src/main/java/com/loki/lochat/api/service/PlayerDataService.java index 5d7e11a..d8b0d50 100644 --- a/src/main/java/com/loki/lochat/api/service/PlayerDataService.java +++ b/src/main/java/com/loki/lochat/api/service/PlayerDataService.java @@ -7,5 +7,6 @@ import java.util.UUID; */ public interface PlayerDataService { void clearPlayerData(UUID player); + void saveAll(); } diff --git a/src/main/java/com/loki/lochat/api/service/SpyService.java b/src/main/java/com/loki/lochat/api/service/SpyService.java index ef63907..78d0d8a 100644 --- a/src/main/java/com/loki/lochat/api/service/SpyService.java +++ b/src/main/java/com/loki/lochat/api/service/SpyService.java @@ -9,25 +9,26 @@ import org.bukkit.entity.Player; public interface SpyService { /** * Переключает режим шпиона для игрока + * * @return true если шпион включен, false если выключен */ boolean toggleSpy(java.util.UUID player); - + /** * Проверяет, находится ли игрок в режиме шпиона */ boolean isSpying(java.util.UUID player); - + /** * Отправляет сообщение всем шпионам (для обычного чата) */ void sendToSpies(Player sender, Component message, boolean isGlobal); - + /** * Отправляет информацию о личном сообщении шпионам */ void broadcastPM(Player sender, Player receiver, String message); - + /** * Удаляет игрока из списка шпионов */ diff --git a/src/main/java/com/loki/lochat/commands/AnnounceCommand.java b/src/main/java/com/loki/lochat/commands/AnnounceCommand.java index a993d21..c79e5e6 100644 --- a/src/main/java/com/loki/lochat/commands/AnnounceCommand.java +++ b/src/main/java/com/loki/lochat/commands/AnnounceCommand.java @@ -42,20 +42,20 @@ public class AnnounceCommand implements CommandExecutor { // Отправка в чат for (Player player : Bukkit.getOnlinePlayers()) { player.sendMessage(formatted); - + // ActionBar (если включен) if (plugin.getConfigManager().isAnnouncementActionBarEnabled()) { player.sendActionBar(formatted); } - + // Title (если включен) if (plugin.getConfigManager().isAnnouncementTitleEnabled()) { Title title = Title.title( ChatFormatter.parse(plugin.getConfigManager().getAnnouncementTitleHeader()), ChatFormatter.parse(message), Title.Times.times( - Duration.ofMillis(500), - Duration.ofSeconds(plugin.getConfigManager().getAnnouncementTitleDuration()), + Duration.ofMillis(500), + Duration.ofSeconds(plugin.getConfigManager().getAnnouncementTitleDuration()), Duration.ofMillis(500) ) ); diff --git a/src/main/java/com/loki/lochat/commands/ClearChatCommand.java b/src/main/java/com/loki/lochat/commands/ClearChatCommand.java index cb216db..535615f 100644 --- a/src/main/java/com/loki/lochat/commands/ClearChatCommand.java +++ b/src/main/java/com/loki/lochat/commands/ClearChatCommand.java @@ -24,7 +24,7 @@ public class ClearChatCommand implements CommandExecutor { for (int i = 0; i < com.loki.lochat.utils.Constants.CLEAR_CHAT_LINES; i++) { player.sendMessage(""); } - + // Уведомление (если включено) if (plugin.getConfigManager().isClearChatMessageEnabled()) { String message = plugin.getConfigManager().getClearChatMessage(); diff --git a/src/main/java/com/loki/lochat/commands/ClearChatConfigCommand.java b/src/main/java/com/loki/lochat/commands/ClearChatConfigCommand.java index cc74de9..080ab57 100644 --- a/src/main/java/com/loki/lochat/commands/ClearChatConfigCommand.java +++ b/src/main/java/com/loki/lochat/commands/ClearChatConfigCommand.java @@ -56,7 +56,7 @@ public class ClearChatConfigCommand implements CommandExecutor, TabCompleter { sender.sendMessage(ChatFormatter.parse("&cУкажите текст сообщения!")); return true; } - + String message = String.join(" ", Arrays.copyOfRange(args, 1, args.length)); plugin.getConfigManager().setClearChatMessage(message); sender.sendMessage(ChatFormatter.parse("&aСообщение установлено: &f" + message)); @@ -64,7 +64,7 @@ public class ClearChatConfigCommand implements CommandExecutor, TabCompleter { case "status" -> { boolean enabled = plugin.getConfigManager().isClearChatMessageEnabled(); String message = plugin.getConfigManager().getClearChatMessage(); - + sender.sendMessage(ChatFormatter.parse("&6Статус сообщения очистки чата:")); sender.sendMessage(ChatFormatter.parse("&eВключено: " + (enabled ? "&aДа" : "&cНет"))); sender.sendMessage(ChatFormatter.parse("&eСообщение: &f" + message)); diff --git a/src/main/java/com/loki/lochat/commands/CustomCommand.java b/src/main/java/com/loki/lochat/commands/CustomCommand.java index cb8ebfe..c211407 100644 --- a/src/main/java/com/loki/lochat/commands/CustomCommand.java +++ b/src/main/java/com/loki/lochat/commands/CustomCommand.java @@ -9,17 +9,13 @@ import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; -public class CustomCommand extends Command { +public final class CustomCommand extends Command { private final CustomCommandManager manager; public CustomCommand(String name, CustomCommandManager manager) { super(name); this.manager = manager; - init(name); - } - - private void init(String name) { this.setDescription("Кастомная команда LoChat"); this.setUsage("/" + name); } diff --git a/src/main/java/com/loki/lochat/commands/GlobalChatCommand.java b/src/main/java/com/loki/lochat/commands/GlobalChatCommand.java index 422521f..ef2ba66 100644 --- a/src/main/java/com/loki/lochat/commands/GlobalChatCommand.java +++ b/src/main/java/com/loki/lochat/commands/GlobalChatCommand.java @@ -18,9 +18,9 @@ import org.jetbrains.annotations.NotNull; */ public class GlobalChatCommand implements CommandExecutor { + private static final MiniMessage MM = MiniMessage.miniMessage(); private final LoChat plugin; private final ChatService chatService; - private static final MiniMessage MM = MiniMessage.miniMessage(); public GlobalChatCommand(LoChat plugin) { this.plugin = plugin; @@ -53,10 +53,10 @@ public class GlobalChatCommand implements CommandExecutor { } String message = String.join(" ", args); - + // Конвертируем String в Component для новой сигнатуры ChatService Component messageComponent = MM.deserialize(message); - + chatService.sendGlobalMessage(player, messageComponent); return true; } diff --git a/src/main/java/com/loki/lochat/commands/LoChatCommand.java b/src/main/java/com/loki/lochat/commands/LoChatCommand.java index e7adaeb..3fee605 100644 --- a/src/main/java/com/loki/lochat/commands/LoChatCommand.java +++ b/src/main/java/com/loki/lochat/commands/LoChatCommand.java @@ -14,8 +14,8 @@ import java.util.List; public class LoChatCommand implements CommandExecutor, TabCompleter { - private final LoChat plugin; private static final MiniMessage MM = MiniMessage.miniMessage(); + private final LoChat plugin; public LoChatCommand(LoChat plugin) { this.plugin = plugin; @@ -51,14 +51,15 @@ public class LoChatCommand implements CommandExecutor, TabCompleter { var commands = plugin.getCustomCommandManager().getCommands(); sender.sendMessage(MM.deserialize("&#FFD700Кастомные команды (" + commands.size() + "):")); for (var cmd : commands.values()) { - sender.sendMessage(MM.deserialize("&e/" + cmd.name + " 󅒐(" + cmd.type + ")")); - if (!cmd.aliases.isEmpty()) { - sender.sendMessage(MM.deserialize("󅒐 Алиасы: " + String.join(", ", cmd.aliases))); + sender.sendMessage(MM.deserialize("&e/" + cmd.name() + " 󅒐(" + cmd.type() + ")")); + if (!cmd.aliases().isEmpty()) { + sender.sendMessage(MM.deserialize("󅒐 Алиасы: " + String.join(", ", cmd.aliases()))); } } } } - default -> sender.sendMessage(MM.deserialize("&#FF0000Неизвестная команда. Используйте /lochat для помощи.")); + default -> + sender.sendMessage(MM.deserialize("&#FF0000Неизвестная команда. Используйте /lochat для помощи.")); } return true; @@ -66,7 +67,7 @@ public class LoChatCommand implements CommandExecutor, TabCompleter { @Override public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, - @NotNull String alias, @NotNull String[] args) { + @NotNull String alias, @NotNull String[] args) { if (!sender.hasPermission("lochat.admin")) { return new ArrayList<>(); } @@ -74,7 +75,7 @@ public class LoChatCommand implements CommandExecutor, TabCompleter { if (args.length == 1) { List completions = new ArrayList<>(); String input = args[0].toLowerCase(); - + for (String cmd : List.of("reload", "commands")) { if (cmd.startsWith(input)) { completions.add(cmd); @@ -82,11 +83,11 @@ public class LoChatCommand implements CommandExecutor, TabCompleter { } return completions; } - + if (args.length == 2 && args[0].equalsIgnoreCase("commands")) { List completions = new ArrayList<>(); String input = args[1].toLowerCase(); - + if ("reload".startsWith(input)) { completions.add("reload"); } diff --git a/src/main/java/com/loki/lochat/commands/LocalChatCommand.java b/src/main/java/com/loki/lochat/commands/LocalChatCommand.java index a636221..edfe8df 100644 --- a/src/main/java/com/loki/lochat/commands/LocalChatCommand.java +++ b/src/main/java/com/loki/lochat/commands/LocalChatCommand.java @@ -17,9 +17,9 @@ import org.jetbrains.annotations.NotNull; */ public class LocalChatCommand implements CommandExecutor { + private static final MiniMessage MM = MiniMessage.miniMessage(); private final LoChat plugin; private final ChatService chatService; - private static final MiniMessage MM = MiniMessage.miniMessage(); public LocalChatCommand(LoChat plugin) { this.plugin = plugin; @@ -39,10 +39,10 @@ public class LocalChatCommand implements CommandExecutor { } String message = String.join(" ", args); - + // Конвертируем String в Component для новой сигнатуры ChatService Component messageComponent = MM.deserialize(message); - + chatService.sendLocalMessage(player, messageComponent); return true; } diff --git a/src/main/java/com/loki/lochat/commands/MsgCommand.java b/src/main/java/com/loki/lochat/commands/MsgCommand.java index 83fc56b..bb62802 100644 --- a/src/main/java/com/loki/lochat/commands/MsgCommand.java +++ b/src/main/java/com/loki/lochat/commands/MsgCommand.java @@ -5,6 +5,7 @@ import com.loki.lochat.api.service.IgnoreService; import com.loki.lochat.api.service.PMService; import com.loki.lochat.api.service.SpyService; import com.loki.lochat.utils.ChatFormatter; +import com.loki.lochat.utils.PlayerUtil; import org.bukkit.Bukkit; import org.bukkit.Sound; import org.bukkit.command.Command; @@ -89,10 +90,10 @@ public class MsgCommand implements CommandExecutor { // Звук для получателя if (plugin.getConfigManager().isPmSoundEnabled()) { - try { - Sound sound = Sound.valueOf(plugin.getConfigManager().getPmSoundType()); + Sound sound = PlayerUtil.parseSound(plugin.getConfigManager().getPmSoundType(), null); + if (sound != null) { target.playSound(target.getLocation(), sound, 1.0f, 1.0f); - } catch (IllegalArgumentException ignored) {} + } } // Шпион diff --git a/src/main/java/com/loki/lochat/commands/MuteBlameCommand.java b/src/main/java/com/loki/lochat/commands/MuteBlameCommand.java index 50766ef..6fb6ec9 100644 --- a/src/main/java/com/loki/lochat/commands/MuteBlameCommand.java +++ b/src/main/java/com/loki/lochat/commands/MuteBlameCommand.java @@ -101,7 +101,7 @@ public class MuteBlameCommand implements CommandExecutor, TabCompleter { @Override public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, - @NotNull String alias, @NotNull String[] args) { + @NotNull String alias, @NotNull String[] args) { List completions = new ArrayList<>(); if (args.length == 1) { diff --git a/src/main/java/com/loki/lochat/commands/MuteCommand.java b/src/main/java/com/loki/lochat/commands/MuteCommand.java index 606d915..6d91581 100644 --- a/src/main/java/com/loki/lochat/commands/MuteCommand.java +++ b/src/main/java/com/loki/lochat/commands/MuteCommand.java @@ -73,7 +73,7 @@ public class MuteCommand implements CommandExecutor, TabCompleter { // Получаем настройки из конфига String defaultReason = plugin.getConfigManager().getString("mute.default-reason", "Нету."); String defaultDuration = plugin.getConfigManager().getString("mute.default-duration", "7d"); - + String reason = reasonBuilder.length() > 0 ? reasonBuilder.toString() : defaultReason; // Определяем длительность @@ -136,7 +136,7 @@ public class MuteCommand implements CommandExecutor, TabCompleter { // Уведомляем замученного (если онлайн) if (target != null) { String msgKey = duration == 0 ? "mute.messages.you-muted-permanent" : "mute.messages.you-muted"; - String msg = plugin.getConfigManager().getString(msgKey, + String msg = plugin.getConfigManager().getString(msgKey, duration == 0 ? "§cВы замучены навсегда! Причина: %reason%" : "§cВы замучены на %duration%! Причина: %reason%"); msg = muteService.formatMessage(msg, finalTargetName, operatorName, timeDisplay, reason); target.sendMessage(ChatFormatter.parse(msg)); @@ -147,7 +147,7 @@ public class MuteCommand implements CommandExecutor, TabCompleter { String silentMsg = plugin.getConfigManager().getString("mute.messages.silent-muted", "§8[Тихо] §c%player% §7замучен на §c%duration% §7(%operator%). Причина: %reason%"); silentMsg = muteService.formatMessage(silentMsg, finalTargetName, operatorName, timeDisplay, reason); - + for (Player p : Bukkit.getOnlinePlayers()) { if (p.hasPermission("lochat.mute.see-silent")) { p.sendMessage(ChatFormatter.parse(silentMsg)); @@ -170,7 +170,7 @@ public class MuteCommand implements CommandExecutor, TabCompleter { @Override public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, - @NotNull String alias, @NotNull String[] args) { + @NotNull String alias, @NotNull String[] args) { List completions = new ArrayList<>(); if (args.length == 1) { diff --git a/src/main/java/com/loki/lochat/commands/MuteHistoryCommand.java b/src/main/java/com/loki/lochat/commands/MuteHistoryCommand.java index 43544ab..6b51579 100644 --- a/src/main/java/com/loki/lochat/commands/MuteHistoryCommand.java +++ b/src/main/java/com/loki/lochat/commands/MuteHistoryCommand.java @@ -72,7 +72,7 @@ public class MuteHistoryCommand implements CommandExecutor, TabCompleter { // Выводим от новых к старым for (int i = history.size() - 1; i >= 0; i--) { MuteData.MuteHistoryEntry entry = history.get(i); - + // Статус String status; if (entry.unmuted) { @@ -99,13 +99,13 @@ public class MuteHistoryCommand implements CommandExecutor, TabCompleter { sender.sendMessage(" §7Длительность: §f" + durationStr); sender.sendMessage(" §7Причина: §f" + (entry.reason != null ? entry.reason : "Не указана")); sender.sendMessage(" §7Выдал: §f" + entry.mutedBy); - + if (entry.unmuted && entry.unmutedBy != null) { sender.sendMessage(" §7Размутил: §f" + entry.unmutedBy + " §7(" + dateFormat.format(new Date(entry.unmutedAt)) + ")"); } index++; - + // Ограничиваем вывод if (index > 10) { sender.sendMessage("§7... и ещё " + (history.size() - 10) + " записей"); @@ -118,7 +118,7 @@ public class MuteHistoryCommand implements CommandExecutor, TabCompleter { @Override public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, - @NotNull String alias, @NotNull String[] args) { + @NotNull String alias, @NotNull String[] args) { List completions = new ArrayList<>(); if (args.length == 1) { diff --git a/src/main/java/com/loki/lochat/commands/MuteListCommand.java b/src/main/java/com/loki/lochat/commands/MuteListCommand.java index 760d68d..b56db27 100644 --- a/src/main/java/com/loki/lochat/commands/MuteListCommand.java +++ b/src/main/java/com/loki/lochat/commands/MuteListCommand.java @@ -45,19 +45,19 @@ public class MuteListCommand implements CommandExecutor { } sender.sendMessage("§6§l=== Активные муты (" + activeMutes.size() + ") ==="); - + int index = 1; for (Map.Entry entry : activeMutes.entrySet()) { UUID uuid = entry.getKey(); MuteData data = entry.getValue(); - + // Получаем имя игрока String playerName = data.getPlayerName(); if (playerName == null) { OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(uuid); playerName = offlinePlayer.getName() != null ? offlinePlayer.getName() : uuid.toString().substring(0, 8); } - + // Форматируем время String timeStr; if (data.isPermanent()) { @@ -66,11 +66,11 @@ public class MuteListCommand implements CommandExecutor { long remaining = data.getEndTime() - System.currentTimeMillis(); timeStr = "§e" + muteService.formatTime(remaining); } - + sender.sendMessage("§7" + index + ". §f" + playerName + " §7- " + timeStr); sender.sendMessage(" §7Причина: §f" + (data.getReason() != null ? data.getReason() : "Не указана")); sender.sendMessage(" §7Выдал: §f" + data.getMutedBy() + " §7(" + dateFormat.format(new Date(data.getMutedAt())) + ")"); - + index++; } diff --git a/src/main/java/com/loki/lochat/commands/NickCommand.java b/src/main/java/com/loki/lochat/commands/NickCommand.java index 020e68f..34100c7 100644 --- a/src/main/java/com/loki/lochat/commands/NickCommand.java +++ b/src/main/java/com/loki/lochat/commands/NickCommand.java @@ -17,39 +17,39 @@ import java.util.List; public class NickCommand implements CommandExecutor, TabCompleter { private final LoChat plugin; private final NickService nickService; - + public NickCommand(LoChat plugin) { this.plugin = plugin; this.nickService = plugin.getServiceRegistry().get(NickService.class); } - + @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { if (!(sender instanceof Player player)) { sender.sendMessage(Component.text("Эта команда только для игроков!", NamedTextColor.RED)); return true; } - + if (!player.hasPermission("lochat.nick")) { player.sendMessage(Component.text("У вас нет прав на использование этой команды!", NamedTextColor.RED)); return true; } - + if (args.length == 0) { return showCurrentNick(player); } - + if (args[0].equalsIgnoreCase("reset")) { return resetNick(player); } - + String nickname = String.join(" ", args); return setNick(player, nickname); } - + private boolean showCurrentNick(Player player) { var currentNick = nickService.getNickname(player.getUniqueId()); - + if (currentNick.isPresent()) { Component nickComponent = ChatFormatter.parse(currentNick.get()); player.sendMessage(Component.text("Ваш текущий ник: ", NamedTextColor.GRAY) @@ -63,23 +63,23 @@ public class NickCommand implements CommandExecutor, TabCompleter { .append(Component.text("/nick <ник>", NamedTextColor.YELLOW)) .append(Component.text(" для установки", NamedTextColor.GRAY))); } - + return true; } - + private boolean resetNick(Player player) { var currentNick = nickService.getNickname(player.getUniqueId()); - + if (currentNick.isEmpty()) { player.sendMessage(Component.text("У вас нет кастомного ника!", NamedTextColor.RED)); return true; } - + nickService.resetNickname(player.getUniqueId()); player.sendMessage(Component.text("Ваш ник сброшен!", NamedTextColor.GREEN)); return true; } - + private boolean setNick(Player player, String nickname) { if (!nickService.isValidNickname(nickname)) { player.sendMessage(Component.text("Невалидный ник!", NamedTextColor.RED)); @@ -89,7 +89,7 @@ public class NickCommand implements CommandExecutor, TabCompleter { player.sendMessage(Component.text("• Поддержка цветов: &#FF0000текст, текст", NamedTextColor.GRAY)); return true; } - + if (nickService.isNicknameTaken(nickname)) { var currentNick = nickService.getNickname(player.getUniqueId()); if (currentNick.isEmpty() || !currentNick.get().equals(nickname)) { @@ -97,9 +97,9 @@ public class NickCommand implements CommandExecutor, TabCompleter { return true; } } - + boolean success = nickService.setNickname(player.getUniqueId(), nickname); - + if (success) { Component nickComponent = ChatFormatter.parse(nickname); player.sendMessage(Component.text("Ваш ник изменён на: ", NamedTextColor.GREEN) @@ -107,33 +107,33 @@ public class NickCommand implements CommandExecutor, TabCompleter { } else { player.sendMessage(Component.text("Не удалось установить ник!", NamedTextColor.RED)); } - + return true; } - + @Override public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { List completions = new ArrayList<>(); - + if (args.length == 1) { String input = args[0].toLowerCase(); - + if ("reset".startsWith(input)) { completions.add("reset"); } - + if (sender instanceof Player player) { var currentNick = nickService.getNickname(player.getUniqueId()); if (currentNick.isPresent()) { completions.add(currentNick.get()); } } - + completions.add("&#FF0000Красный"); completions.add("�FF00Зелёный"); completions.add("Русский_Ник"); } - + return completions; } } diff --git a/src/main/java/com/loki/lochat/commands/PlayerInfoCommand.java b/src/main/java/com/loki/lochat/commands/PlayerInfoCommand.java index 05ecde4..5a14a3d 100644 --- a/src/main/java/com/loki/lochat/commands/PlayerInfoCommand.java +++ b/src/main/java/com/loki/lochat/commands/PlayerInfoCommand.java @@ -41,7 +41,7 @@ public class PlayerInfoCommand implements CommandExecutor { sender.sendMessage(ChatFormatter.parse("§eУровень: §f" + target.getLevel())); sender.sendMessage(ChatFormatter.parse("§eЗдоровье: §f" + Math.round(target.getHealth()) + "/20")); sender.sendMessage(ChatFormatter.parse("§eМир: §f" + target.getWorld().getName())); - + // Если есть градиентный модуль, показываем градиентное имя if (plugin.getGradientModule() != null) { String gradientName = plugin.getGradientModule().getFormattedName(target); diff --git a/src/main/java/com/loki/lochat/commands/ReplyCommand.java b/src/main/java/com/loki/lochat/commands/ReplyCommand.java index b398865..3295907 100644 --- a/src/main/java/com/loki/lochat/commands/ReplyCommand.java +++ b/src/main/java/com/loki/lochat/commands/ReplyCommand.java @@ -5,6 +5,7 @@ import com.loki.lochat.api.service.IgnoreService; import com.loki.lochat.api.service.PMService; import com.loki.lochat.api.service.SpyService; import com.loki.lochat.utils.ChatFormatter; +import com.loki.lochat.utils.PlayerUtil; import org.bukkit.Bukkit; import org.bukkit.Sound; import org.bukkit.command.Command; @@ -88,10 +89,10 @@ public class ReplyCommand implements CommandExecutor { // Звук для получателя if (plugin.getConfigManager().isPmSoundEnabled()) { - try { - Sound sound = Sound.valueOf(plugin.getConfigManager().getPmSoundType()); + Sound sound = PlayerUtil.parseSound(plugin.getConfigManager().getPmSoundType(), null); + if (sound != null) { target.playSound(target.getLocation(), sound, 1.0f, 1.0f); - } catch (IllegalArgumentException ignored) {} + } } // Шпион diff --git a/src/main/java/com/loki/lochat/commands/UnmuteCommand.java b/src/main/java/com/loki/lochat/commands/UnmuteCommand.java index 251d443..2b19b91 100644 --- a/src/main/java/com/loki/lochat/commands/UnmuteCommand.java +++ b/src/main/java/com/loki/lochat/commands/UnmuteCommand.java @@ -107,7 +107,7 @@ public class UnmuteCommand implements CommandExecutor, TabCompleter { @Override public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, - @NotNull String alias, @NotNull String[] args) { + @NotNull String alias, @NotNull String[] args) { List completions = new ArrayList<>(); if (args.length == 1) { diff --git a/src/main/java/com/loki/lochat/config/ConfigManager.java b/src/main/java/com/loki/lochat/config/ConfigManager.java index ec15c29..1ca6b7d 100644 --- a/src/main/java/com/loki/lochat/config/ConfigManager.java +++ b/src/main/java/com/loki/lochat/config/ConfigManager.java @@ -15,7 +15,7 @@ public class ConfigManager { this.plugin = plugin; plugin.saveDefaultConfig(); this.config = plugin.getConfig(); - + // Проверяем версию конфига и обновляем при необходимости updateConfig(); } @@ -23,17 +23,17 @@ public class ConfigManager { private void updateConfig() { int currentVersion = config.getInt("config-version", 1); int requiredVersion = 2; // Текущая версия конфига - + if (currentVersion < requiredVersion) { plugin.getLogger().info("Обновление конфига с версии " + currentVersion + " до " + requiredVersion); - + // Добавляем новые настройки если их нет addMissingConfigOptions(); - + // Обновляем версию config.set("config-version", requiredVersion); plugin.saveConfig(); - + plugin.getLogger().info("Конфиг успешно обновлен!"); } } @@ -46,12 +46,12 @@ public class ConfigManager { config.set("announcements.show-actionbar", true); config.set("announcements.title-duration", 3); } - + // Можно добавить другие недостающие настройки if (!config.contains("chat.pm.enabled")) { config.set("chat.pm.enabled", true); } - + if (!config.contains("mentions.enabled")) { config.set("mentions.enabled", true); config.set("mentions.sound", true); @@ -59,18 +59,18 @@ public class ConfigManager { config.set("mentions.highlight", "&#FFFF00@{player}"); config.set("mentions.self-highlight", "&#FFD700{player}"); } - + if (!config.contains("automessages.enabled")) { config.set("automessages.enabled", true); config.set("automessages.interval", 300); config.set("automessages.random", false); } - + if (!config.contains("clearchat.message.enabled")) { config.set("clearchat.message.enabled", true); config.set("clearchat.message.text", "CADFЧат очищен администратором {player}"); } - + if (!config.contains("lopreff.enabled")) { config.set("lopreff.enabled", true); config.set("lopreff.use-gradient-name", true); @@ -197,21 +197,21 @@ public class ConfigManager { public String getSelfMentionHighlight() { return ChatFormatter.convertAllColors(config.getString("mentions.self-highlight", "&#FFD700{player}")); } - + // Clear chat public boolean isClearChatMessageEnabled() { return config.getBoolean("clearchat.message.enabled", true); } - + public void setClearChatMessageEnabled(boolean enabled) { config.set("clearchat.message.enabled", enabled); plugin.saveConfig(); } - + public String getClearChatMessage() { return config.getString("clearchat.message.text", "CADFЧат очищен администратором {player}"); } - + public void setClearChatMessage(String message) { config.set("clearchat.message.text", message); plugin.saveConfig(); diff --git a/src/main/java/com/loki/lochat/core/filter/AdvancedMessageFilter.java b/src/main/java/com/loki/lochat/core/filter/AdvancedMessageFilter.java index 5f45aae..8e2e48c 100644 --- a/src/main/java/com/loki/lochat/core/filter/AdvancedMessageFilter.java +++ b/src/main/java/com/loki/lochat/core/filter/AdvancedMessageFilter.java @@ -8,127 +8,127 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; public class AdvancedMessageFilter { - + private static final Pattern URL_PATTERN = Pattern.compile( - "(https?://)?([\\w-]+\\.)+[\\w-]+(/[\\w-./?%&=]*)?", - Pattern.CASE_INSENSITIVE + "(https?://)?([\\w-]+\\.)+[\\w-]+(/[\\w-./?%&=]*)?", + Pattern.CASE_INSENSITIVE ); - + private static final Pattern IP_PATTERN = Pattern.compile( - "\\b(?:\\d{1,3}\\.){3}\\d{1,3}\\b" + "\\b(?:\\d{1,3}\\.){3}\\d{1,3}\\b" ); - + private static final Pattern REPEAT_PATTERN = Pattern.compile( - "(.)\\1{3,}" + "(.)\\1{3,}" ); - + private final FileConfiguration config; private final List whitelistedDomains; private final List blacklistedDomains; - + public AdvancedMessageFilter(FileConfiguration config) { this.config = config; this.whitelistedDomains = config.getStringList("filters.url.whitelist"); this.blacklistedDomains = config.getStringList("filters.url.blacklist"); } - + public FilterResult filterMessage(Player player, String message) { if (config.getBoolean("filters.url.enabled", true)) { FilterResult urlResult = filterUrls(player, message); - if (!urlResult.isAllowed()) { + if (!urlResult.allowed()) { return urlResult; } - message = urlResult.getFilteredMessage(); + message = urlResult.filteredMessage(); } - + if (config.getBoolean("filters.ip.enabled", true)) { FilterResult ipResult = filterIPs(player, message); - if (!ipResult.isAllowed()) { + if (!ipResult.allowed()) { return ipResult; } - message = ipResult.getFilteredMessage(); + message = ipResult.filteredMessage(); } - + if (config.getBoolean("filters.repeat.enabled", true)) { message = filterRepeatingChars(message); } - + return new FilterResult(true, message, null); } - + private FilterResult filterUrls(Player player, String message) { if (player.hasPermission("lochat.bypass.urlfilter")) { return new FilterResult(true, message, null); } - + Matcher matcher = URL_PATTERN.matcher(message); - + while (matcher.find()) { String url = matcher.group(); String domain = extractDomain(url); - + if (!whitelistedDomains.isEmpty()) { boolean isWhitelisted = whitelistedDomains.stream() - .anyMatch(d -> domain.toLowerCase().contains(d.toLowerCase())); - + .anyMatch(d -> domain.toLowerCase().contains(d.toLowerCase())); + if (!isWhitelisted) { - return new FilterResult(false, message, - config.getString("filters.url.blocked-message", "&#FF6B6BСсылки запрещены!")); + return new FilterResult(false, message, + config.getString("filters.url.blocked-message", "&#FF6B6BСсылки запрещены!")); } } - + if (!blacklistedDomains.isEmpty()) { boolean isBlacklisted = blacklistedDomains.stream() - .anyMatch(d -> domain.toLowerCase().contains(d.toLowerCase())); - + .anyMatch(d -> domain.toLowerCase().contains(d.toLowerCase())); + if (isBlacklisted) { return new FilterResult(false, message, - config.getString("filters.url.blocked-message", "&#FF6B6BЭта ссылка запрещена!")); + config.getString("filters.url.blocked-message", "&#FF6B6BЭта ссылка запрещена!")); } } } - + return new FilterResult(true, message, null); } - + private FilterResult filterIPs(Player player, String message) { if (player.hasPermission("lochat.bypass.ipfilter")) { return new FilterResult(true, message, null); } - + Matcher matcher = IP_PATTERN.matcher(message); - + if (matcher.find()) { String replacement = config.getString("filters.ip.replacement", "[IP скрыт]"); String filtered = matcher.replaceAll(replacement); - + if (config.getBoolean("filters.ip.block", false)) { return new FilterResult(false, message, - config.getString("filters.ip.blocked-message", "&#FF6B6BIP адреса запрещены!")); + config.getString("filters.ip.blocked-message", "&#FF6B6BIP адреса запрещены!")); } - + return new FilterResult(true, filtered, null); } - + return new FilterResult(true, message, null); } - + private String filterRepeatingChars(String message) { int maxRepeats = config.getInt("filters.repeat.max-repeats", 3); - + Matcher matcher = REPEAT_PATTERN.matcher(message); StringBuffer result = new StringBuffer(); - + while (matcher.find()) { String repeated = matcher.group(1); String replacement = repeated.repeat(Math.min(maxRepeats, matcher.group().length())); matcher.appendReplacement(result, Matcher.quoteReplacement(replacement)); } matcher.appendTail(result); - + return result.toString(); } - + private String extractDomain(String url) { url = url.replaceFirst("^https?://", ""); int slashIndex = url.indexOf('/'); @@ -137,28 +137,7 @@ public class AdvancedMessageFilter { } return url; } - - public static class FilterResult { - private final boolean allowed; - private final String filteredMessage; - private final String blockReason; - - public FilterResult(boolean allowed, String filteredMessage, String blockReason) { - this.allowed = allowed; - this.filteredMessage = filteredMessage; - this.blockReason = blockReason; - } - - public boolean isAllowed() { - return allowed; - } - - public String getFilteredMessage() { - return filteredMessage; - } - - public String getBlockReason() { - return blockReason; - } + + public record FilterResult(boolean allowed, String filteredMessage, String blockReason) { } } diff --git a/src/main/java/com/loki/lochat/core/filter/CooldownFilter.java b/src/main/java/com/loki/lochat/core/filter/CooldownFilter.java index 2c2cf81..97d6b49 100644 --- a/src/main/java/com/loki/lochat/core/filter/CooldownFilter.java +++ b/src/main/java/com/loki/lochat/core/filter/CooldownFilter.java @@ -13,30 +13,30 @@ import org.bukkit.plugin.java.JavaPlugin; public class CooldownFilter implements MessageFilter { private final CooldownService cooldownService; private final FileConfiguration config; - + public CooldownFilter(CooldownService cooldownService, JavaPlugin plugin) { this.cooldownService = cooldownService; this.config = plugin.getConfig(); } - + @Override public boolean apply(Player player, ChatMessage message) { if (player.hasPermission("chat.bypass.cooldown")) { return true; } - + String chatType = message.getChatType(); int cooldown = config.getInt("chat." + chatType + ".cooldown", 0); - + if (cooldown > 0) { if (cooldownService.isOnCooldown(player.getUniqueId(), chatType, cooldown)) { int remaining = cooldownService.getRemainingCooldown( - player.getUniqueId(), chatType, cooldown); + player.getUniqueId(), chatType, cooldown); player.sendMessage("§cПодождите " + remaining + " сек."); return false; } } - + cooldownService.setCooldown(player.getUniqueId(), chatType); return true; } diff --git a/src/main/java/com/loki/lochat/core/filter/MuteFilter.java b/src/main/java/com/loki/lochat/core/filter/MuteFilter.java index f9fcd45..ab872b0 100644 --- a/src/main/java/com/loki/lochat/core/filter/MuteFilter.java +++ b/src/main/java/com/loki/lochat/core/filter/MuteFilter.java @@ -10,11 +10,11 @@ import org.bukkit.entity.Player; */ public class MuteFilter implements MessageFilter { private final MuteService muteService; - + public MuteFilter(MuteService muteService) { this.muteService = muteService; } - + @Override public boolean apply(Player player, ChatMessage message) { if (muteService.isMuted(player.getUniqueId())) { @@ -23,7 +23,7 @@ public class MuteFilter implements MessageFilter { } return true; } - + private void sendMuteNotification(Player player) { long remaining = muteService.getRemainingTime(player.getUniqueId()); String timeStr = muteService.formatTime(remaining); diff --git a/src/main/java/com/loki/lochat/core/registry/ServiceRegistry.java b/src/main/java/com/loki/lochat/core/registry/ServiceRegistry.java index 5df639a..55a4e61 100644 --- a/src/main/java/com/loki/lochat/core/registry/ServiceRegistry.java +++ b/src/main/java/com/loki/lochat/core/registry/ServiceRegistry.java @@ -12,25 +12,23 @@ import java.util.Map; public class ServiceRegistry { private final Map, Object> services = new HashMap<>(); private final JavaPlugin plugin; - - public ServiceRegistry(JavaPlugin plugin) { + + private ServiceRegistry(JavaPlugin plugin) { this.plugin = plugin; - init(); } - - public ServiceRegistry(JavaPlugin plugin, ConfigManager configManager, MessageConfig messageConfig) { - this.plugin = plugin; - initWithDeps(configManager, messageConfig); + + public static ServiceRegistry create(JavaPlugin plugin) { + ServiceRegistry registry = new ServiceRegistry(plugin); + registry.registerServices(); + return registry; } - - private void init() { - registerServices(); + + public static ServiceRegistry createWithDeps(JavaPlugin plugin, ConfigManager configManager, MessageConfig messageConfig) { + ServiceRegistry registry = new ServiceRegistry(plugin); + registry.registerServicesWithDeps(configManager, messageConfig); + return registry; } - - private void initWithDeps(ConfigManager configManager, MessageConfig messageConfig) { - registerServicesWithDeps(configManager, messageConfig); - } - + private void registerServices() { register(ChatService.class, new ChatServiceImpl(plugin, this)); register(MuteService.class, new MuteServiceImpl(plugin)); @@ -38,25 +36,25 @@ public class ServiceRegistry { register(MessageService.class, new MessageServiceImpl(plugin, this)); register(PlayerDataService.class, new PlayerDataServiceImpl(plugin)); } - + private void registerServicesWithDeps(ConfigManager configManager, MessageConfig messageConfig) { register(ChatService.class, new ChatServiceImpl(plugin, this)); register(MuteService.class, new MuteServiceImpl(plugin)); register(CooldownService.class, new CooldownServiceImpl()); register(MessageService.class, new MessageServiceImpl(plugin, this)); register(PlayerDataService.class, new PlayerDataServiceImpl(plugin)); - + register(PMService.class, new PMServiceImpl()); register(IgnoreService.class, new IgnoreServiceImpl(plugin)); register(SpyService.class, new SpyServiceImpl(plugin, messageConfig)); register(MentionService.class, new MentionServiceImpl(configManager)); register(NickService.class, new NickServiceImpl(plugin)); } - + public void register(Class serviceClass, T implementation) { services.put(serviceClass, implementation); } - + @SuppressWarnings("unchecked") public T get(Class serviceClass) { Object service = services.get(serviceClass); @@ -65,7 +63,7 @@ public class ServiceRegistry { } return (T) service; } - + public void shutdown() { services.clear(); } diff --git a/src/main/java/com/loki/lochat/core/service/ChatServiceImpl.java b/src/main/java/com/loki/lochat/core/service/ChatServiceImpl.java index 38cc094..243d4e9 100644 --- a/src/main/java/com/loki/lochat/core/service/ChatServiceImpl.java +++ b/src/main/java/com/loki/lochat/core/service/ChatServiceImpl.java @@ -19,61 +19,61 @@ import java.util.concurrent.ConcurrentHashMap; public class ChatServiceImpl implements ChatService { private final JavaPlugin plugin; private final Set globalChatDisabled = ConcurrentHashMap.newKeySet(); - + public ChatServiceImpl(JavaPlugin plugin, ServiceRegistry registry) { this.plugin = plugin; } - + @Override public void sendGlobalMessage(Player sender, Object message) { - String format = plugin.getConfig().getString("chat.global.format", - "{prefix} {player}: {message}"); + String format = plugin.getConfig().getString("chat.global.format", + "{prefix} {player}: {message}"); String prefix = plugin.getConfig().getString("chat.global.prefix", "[G]"); - - Component messageComponent = (message instanceof Component) - ? (Component) message - : ChatFormatter.parse(message.toString()); - + + Component messageComponent = (message instanceof Component) + ? (Component) message + : ChatFormatter.parse(message.toString()); + // Используем displayName игрока (с градиентом если есть) Component playerName = sender.displayName(); - + String formatted = format.replace("{prefix}", prefix); - + Component finalComponent = ChatFormatter.parse(formatted) - .replaceText(builder -> builder.matchLiteral("{player}").replacement(playerName)) - .replaceText(builder -> builder.matchLiteral("{message}").replacement(messageComponent)); - + .replaceText(builder -> builder.matchLiteral("{player}").replacement(playerName)) + .replaceText(builder -> builder.matchLiteral("{message}").replacement(messageComponent)); + for (Player player : Bukkit.getOnlinePlayers()) { if (!isGlobalChatDisabled(player.getUniqueId())) { player.sendMessage(finalComponent); } } } - + @Override public void sendLocalMessage(Player sender, Object message) { int radius = plugin.getConfig().getInt("chat.local.radius", 100); - String format = plugin.getConfig().getString("chat.local.format", - "{player}: {message}"); - - Component messageComponent = (message instanceof Component) - ? (Component) message - : ChatFormatter.parse(message.toString()); - + String format = plugin.getConfig().getString("chat.local.format", + "{player}: {message}"); + + Component messageComponent = (message instanceof Component) + ? (Component) message + : ChatFormatter.parse(message.toString()); + // Используем displayName игрока (с градиентом если есть) Component playerName = sender.displayName(); - + Component finalComponent = ChatFormatter.parse(format) - .replaceText(builder -> builder.matchLiteral("{player}").replacement(playerName)) - .replaceText(builder -> builder.matchLiteral("{message}").replacement(messageComponent)); - + .replaceText(builder -> builder.matchLiteral("{player}").replacement(playerName)) + .replaceText(builder -> builder.matchLiteral("{message}").replacement(messageComponent)); + for (Player player : Bukkit.getOnlinePlayers()) { if (DistanceUtil.isInRange(sender, player, radius)) { player.sendMessage(finalComponent); } } } - + @Override public boolean toggleGlobalChat(UUID player) { if (globalChatDisabled.contains(player)) { @@ -84,7 +84,7 @@ public class ChatServiceImpl implements ChatService { return false; } } - + @Override public boolean isGlobalChatDisabled(UUID player) { return globalChatDisabled.contains(player); diff --git a/src/main/java/com/loki/lochat/core/service/CooldownServiceImpl.java b/src/main/java/com/loki/lochat/core/service/CooldownServiceImpl.java index c6ac6d0..b2afcd3 100644 --- a/src/main/java/com/loki/lochat/core/service/CooldownServiceImpl.java +++ b/src/main/java/com/loki/lochat/core/service/CooldownServiceImpl.java @@ -12,40 +12,40 @@ import java.util.concurrent.ConcurrentHashMap; public class CooldownServiceImpl implements CooldownService { private final Map globalCooldowns = new ConcurrentHashMap<>(); private final Map localCooldowns = new ConcurrentHashMap<>(); - + @Override public boolean isOnCooldown(UUID player, String type, int cooldownSeconds) { Map cooldowns = getCooldownMap(type); Long lastTime = cooldowns.get(player); - + if (lastTime == null) return false; - + long elapsed = (System.currentTimeMillis() - lastTime) / 1000; return elapsed < cooldownSeconds; } - + @Override public int getRemainingCooldown(UUID player, String type, int cooldownSeconds) { Map cooldowns = getCooldownMap(type); Long lastTime = cooldowns.get(player); - + if (lastTime == null) return 0; - + long elapsed = (System.currentTimeMillis() - lastTime) / 1000; return Math.max(0, cooldownSeconds - (int) elapsed); } - + @Override public void setCooldown(UUID player, String type) { getCooldownMap(type).put(player, System.currentTimeMillis()); } - + @Override public void removeCooldown(UUID player) { globalCooldowns.remove(player); localCooldowns.remove(player); } - + private Map getCooldownMap(String type) { return type.equals("global") ? globalCooldowns : localCooldowns; } diff --git a/src/main/java/com/loki/lochat/core/service/IgnoreServiceImpl.java b/src/main/java/com/loki/lochat/core/service/IgnoreServiceImpl.java index baeab3d..606c87a 100644 --- a/src/main/java/com/loki/lochat/core/service/IgnoreServiceImpl.java +++ b/src/main/java/com/loki/lochat/core/service/IgnoreServiceImpl.java @@ -2,6 +2,7 @@ package com.loki.lochat.core.service; import com.loki.lochat.api.service.IgnoreService; import com.loki.lochat.gradient.util.FoliaUtil; +import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.plugin.java.JavaPlugin; import java.io.File; @@ -9,8 +10,6 @@ import java.io.IOException; import java.util.*; import java.util.concurrent.ConcurrentHashMap; -import org.bukkit.configuration.file.YamlConfiguration; - /** * Реализация сервиса игнорирования */ @@ -39,13 +38,15 @@ public class IgnoreServiceImpl implements IgnoreService { for (String ignoredStr : ignoredList) { try { ignored.add(UUID.fromString(ignoredStr)); - } catch (Exception ignored2) {} + } catch (Exception ignored2) { + } } if (!ignored.isEmpty()) { ignoreMap.put(uuid, ignored); } - } catch (Exception ignored) {} + } catch (Exception ignored) { + } } } diff --git a/src/main/java/com/loki/lochat/core/service/MentionServiceImpl.java b/src/main/java/com/loki/lochat/core/service/MentionServiceImpl.java index 5da0d1d..9d01443 100644 --- a/src/main/java/com/loki/lochat/core/service/MentionServiceImpl.java +++ b/src/main/java/com/loki/lochat/core/service/MentionServiceImpl.java @@ -2,6 +2,7 @@ package com.loki.lochat.core.service; import com.loki.lochat.api.service.MentionService; import com.loki.lochat.config.ConfigManager; +import com.loki.lochat.utils.PlayerUtil; import org.bukkit.Bukkit; import org.bukkit.Sound; import org.bukkit.entity.Player; @@ -17,9 +18,8 @@ import java.util.regex.Pattern; * Реализация сервиса упоминаний */ public class MentionServiceImpl implements MentionService { - private final ConfigManager configManager; private static final Pattern MENTION_PATTERN = Pattern.compile("@(\\w+)"); - + private final ConfigManager configManager; // Хранит для какого игрока какие части сообщения выделить private final Map> highlightedNicks = new HashMap<>(); @@ -46,7 +46,7 @@ public class MentionServiceImpl implements MentionService { mentionedPlayers.add(mentioned); String replacement = highlight.replace("{player}", mentioned.getName()); matcher.appendReplacement(result, replacement); - + // Запоминаем что этот игрок упомянут highlightedNicks.computeIfAbsent(mentioned, k -> new HashSet<>()).add(mentioned.getName()); } @@ -64,23 +64,23 @@ public class MentionServiceImpl implements MentionService { String viewerName = viewer.getName(); String result = message; - + // Проверяем упоминание через @ник String highlight = configManager.getMentionHighlight(); String highlightedName = highlight.replace("{player}", viewerName); - + // Если в сообщении есть выделенный ник этого игрока — добавляем дополнительное выделение if (result.contains(highlightedName)) { // Уже выделено через processMentions, добавляем эффект String extraHighlight = "" + highlightedName + ""; result = result.replace(highlightedName, extraHighlight); } - + // Также проверяем просто ник в сообщении (без @) // Регистронезависимый поиск Pattern nickPattern = Pattern.compile("(?i)\\b" + Pattern.quote(viewerName) + "\\b"); Matcher nickMatcher = nickPattern.matcher(result); - + if (nickMatcher.find()) { // Ник найден в сообщении — выделяем для этого игрока String selfHighlight = configManager.getSelfMentionHighlight(); @@ -104,12 +104,7 @@ public class MentionServiceImpl implements MentionService { } String soundName = configManager.getMentionSoundType(); - Sound sound; - try { - sound = Sound.valueOf(soundName); - } catch (IllegalArgumentException e) { - sound = Sound.BLOCK_NOTE_BLOCK_PLING; - } + Sound sound = PlayerUtil.parseSound(soundName, Sound.BLOCK_NOTE_BLOCK_PLING); for (Player player : players) { player.playSound(player.getLocation(), sound, 1.0f, 1.0f); @@ -120,13 +115,13 @@ public class MentionServiceImpl implements MentionService { public void notifyIfMentioned(String message, Player viewer, Player sender) { if (viewer.equals(sender)) return; if (!configManager.isMentionSoundEnabled()) return; - + if (isPlayerMentioned(message, viewer)) { String soundName = configManager.getMentionSoundType(); - try { - Sound sound = Sound.valueOf(soundName); + Sound sound = PlayerUtil.parseSound(soundName, null); + if (sound != null) { viewer.playSound(viewer.getLocation(), sound, 1.0f, 1.0f); - } catch (IllegalArgumentException ignored) {} + } } } } diff --git a/src/main/java/com/loki/lochat/core/service/MessageServiceImpl.java b/src/main/java/com/loki/lochat/core/service/MessageServiceImpl.java index c9ad6c5..e231884 100644 --- a/src/main/java/com/loki/lochat/core/service/MessageServiceImpl.java +++ b/src/main/java/com/loki/lochat/core/service/MessageServiceImpl.java @@ -1,13 +1,14 @@ package com.loki.lochat.core.service; import com.loki.lochat.api.filter.MessageFilter; -import com.loki.lochat.api.service.*; +import com.loki.lochat.api.service.ChatService; +import com.loki.lochat.api.service.CooldownService; +import com.loki.lochat.api.service.MessageService; +import com.loki.lochat.api.service.MuteService; import com.loki.lochat.core.filter.CooldownFilter; import com.loki.lochat.core.filter.MuteFilter; import com.loki.lochat.core.registry.ServiceRegistry; import com.loki.lochat.data.model.ChatMessage; -import com.loki.lochat.utils.ChatFormatter; -import net.kyori.adventure.text.Component; import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; @@ -21,29 +22,29 @@ public class MessageServiceImpl implements MessageService { private final JavaPlugin plugin; private final List filters; private final ChatService chatService; - + public MessageServiceImpl(JavaPlugin plugin, ServiceRegistry registry) { this.plugin = plugin; this.chatService = registry.get(ChatService.class); this.filters = new ArrayList<>(); - + // Регистрируем фильтры в порядке применения filters.add(new MuteFilter(registry.get(MuteService.class))); filters.add(new CooldownFilter(registry.get(CooldownService.class), plugin)); } - + @Override public boolean processMessage(Player player, String rawMessage) { // Создаем объект сообщения ChatMessage message = ChatMessage.create(player, rawMessage); - + // Применяем фильтры (мут, кулдаун) for (MessageFilter filter : filters) { if (!filter.apply(player, message)) { return false; // Сообщение заблокировано } } - + // Возвращаем true - сообщение разрешено // Рендерер сам отправит его return true; diff --git a/src/main/java/com/loki/lochat/core/service/MuteServiceImpl.java b/src/main/java/com/loki/lochat/core/service/MuteServiceImpl.java index 3fc4629..4422fb8 100644 --- a/src/main/java/com/loki/lochat/core/service/MuteServiceImpl.java +++ b/src/main/java/com/loki/lochat/core/service/MuteServiceImpl.java @@ -24,7 +24,7 @@ public class MuteServiceImpl implements MuteService { private final File dataFile; private final File historyFile; private final Gson gson = new GsonBuilder().setPrettyPrinting().create(); - + public MuteServiceImpl(JavaPlugin plugin) { this.plugin = plugin; this.dataFile = new File(plugin.getDataFolder(), "mutes.json"); @@ -32,19 +32,19 @@ public class MuteServiceImpl implements MuteService { load(); loadHistory(); } - + @Override public void mute(UUID uuid, String playerName, long duration, String reason, String mutedBy) { long endTime = duration > 0 ? System.currentTimeMillis() + duration : 0; MuteData data = new MuteData(uuid, playerName, endTime, reason, mutedBy); mutes.put(uuid, data); - + // Добавляем в историю addToHistory(uuid, playerName, duration, reason, mutedBy); - + saveAsync(); } - + @Override public boolean unmute(UUID uuid, String unmutedBy) { MuteData removed = mutes.remove(uuid); @@ -55,12 +55,12 @@ public class MuteServiceImpl implements MuteService { } return false; } - + @Override public boolean isMuted(UUID uuid) { MuteData data = mutes.get(uuid); if (data == null) return false; - + if (data.getEndTime() > 0 && System.currentTimeMillis() > data.getEndTime()) { mutes.remove(uuid); saveAsync(); @@ -68,13 +68,13 @@ public class MuteServiceImpl implements MuteService { } return true; } - + @Override public MuteData getMuteData(UUID uuid) { if (!isMuted(uuid)) return null; return mutes.get(uuid); } - + @Override public long getRemainingTime(UUID uuid) { MuteData data = mutes.get(uuid); @@ -82,16 +82,16 @@ public class MuteServiceImpl implements MuteService { if (data.getEndTime() == 0) return -1; // Перманентный return Math.max(0, data.getEndTime() - System.currentTimeMillis()); } - + @Override public String formatTime(long millis) { if (millis <= 0) return "0с"; - + long seconds = millis / 1000; long minutes = seconds / 60; long hours = minutes / 60; long days = hours / 24; - + if (days > 0) { return days + "д " + (hours % 24) + "ч"; } else if (hours > 0) { @@ -102,14 +102,14 @@ public class MuteServiceImpl implements MuteService { return seconds + "с"; } } - + @Override public long parseTime(String timeStr) { if (timeStr == null || timeStr.isEmpty()) return 0; - + timeStr = timeStr.toLowerCase(); long multiplier = 1000; // базово в миллисекундах - + try { if (timeStr.endsWith("d")) { return Long.parseLong(timeStr.replace("d", "")) * 24 * 60 * 60 * multiplier; @@ -126,45 +126,45 @@ public class MuteServiceImpl implements MuteService { return -1; } } - + @Override public long getMaxDuration(Player player) { if (player.hasPermission("lochat.mute.dur.perm")) { return 0; // Перманентный } - + String[] durations = {"30d", "14d", "7d", "3d", "1d", "12h", "6h", "1h", "30m", "10m"}; for (String dur : durations) { if (player.hasPermission("lochat.mute.dur." + dur)) { return parseTime(dur); } } - + return -1; // Нет прав } - + @Override public boolean canMuteForDuration(Player player, long duration) { if (player.hasPermission("lochat.mute.dur.perm")) { return true; } - + if (duration == 0) { return false; } - + long maxDuration = getMaxDuration(player); if (maxDuration == -1) return false; if (maxDuration == 0) return true; - + return duration <= maxDuration; } - + @Override public List getPlayerHistory(UUID uuid) { return history.getOrDefault(uuid, new ArrayList<>()); } - + @Override public List getMutesByOperator(String operatorName) { List result = new ArrayList<>(); @@ -178,7 +178,7 @@ public class MuteServiceImpl implements MuteService { result.sort((a, b) -> Long.compare(b.mutedAt, a.mutedAt)); return result; } - + @Override public UUID getUUIDByName(String name) { for (Map.Entry> entry : history.entrySet()) { @@ -190,7 +190,7 @@ public class MuteServiceImpl implements MuteService { } return null; } - + @Override public Map getActiveMutes() { mutes.entrySet().removeIf(entry -> { @@ -199,7 +199,7 @@ public class MuteServiceImpl implements MuteService { }); return new HashMap<>(mutes); } - + @Override public String formatMessage(String message, String player, String operator, String duration, String reason) { return message @@ -208,17 +208,17 @@ public class MuteServiceImpl implements MuteService { .replace("%duration%", duration != null ? duration : "") .replace("%reason%", reason != null ? reason : ""); } - + @Override public void save() { try { if (!dataFile.getParentFile().exists()) { dataFile.getParentFile().mkdirs(); } - + Map toSave = new ConcurrentHashMap<>(); mutes.forEach((uuid, data) -> toSave.put(uuid.toString(), data)); - + try (Writer writer = new FileWriter(dataFile)) { gson.toJson(toSave, writer); } @@ -226,52 +226,56 @@ public class MuteServiceImpl implements MuteService { plugin.getLogger().warning("Ошибка сохранения мутов: " + e.getMessage()); } } - + private void load() { if (!dataFile.exists()) return; - + try (Reader reader = new FileReader(dataFile)) { - Type type = new TypeToken>(){}.getType(); + Type type = new TypeToken>() { + }.getType(); Map loaded = gson.fromJson(reader, type); if (loaded != null) { loaded.forEach((key, value) -> { try { mutes.put(UUID.fromString(key), value); - } catch (IllegalArgumentException ignored) {} + } catch (IllegalArgumentException ignored) { + } }); } } catch (IOException e) { plugin.getLogger().warning("Ошибка загрузки мутов: " + e.getMessage()); } } - + private void loadHistory() { if (!historyFile.exists()) return; - + try (Reader reader = new FileReader(historyFile)) { - Type type = new TypeToken>>(){}.getType(); + Type type = new TypeToken>>() { + }.getType(); Map> loaded = gson.fromJson(reader, type); if (loaded != null) { loaded.forEach((key, value) -> { try { history.put(UUID.fromString(key), new ArrayList<>(value)); - } catch (IllegalArgumentException ignored) {} + } catch (IllegalArgumentException ignored) { + } }); } } catch (IOException e) { plugin.getLogger().warning("Ошибка загрузки истории мутов: " + e.getMessage()); } } - + private void saveHistory() { try { if (!historyFile.getParentFile().exists()) { historyFile.getParentFile().mkdirs(); } - + Map> toSave = new ConcurrentHashMap<>(); history.forEach((uuid, data) -> toSave.put(uuid.toString(), data)); - + try (Writer writer = new FileWriter(historyFile)) { gson.toJson(toSave, writer); } @@ -279,7 +283,7 @@ public class MuteServiceImpl implements MuteService { plugin.getLogger().warning("Ошибка сохранения истории мутов: " + e.getMessage()); } } - + private void addToHistory(UUID uuid, String playerName, long duration, String reason, String mutedBy) { List playerHistory = history.computeIfAbsent(uuid, k -> new ArrayList<>()); playerHistory.add(new MuteData.MuteHistoryEntry( @@ -294,7 +298,7 @@ public class MuteServiceImpl implements MuteService { )); saveHistoryAsync(); } - + private void updateHistoryUnmute(UUID uuid, String unmutedBy) { List playerHistory = history.get(uuid); if (playerHistory != null && !playerHistory.isEmpty()) { @@ -310,11 +314,11 @@ public class MuteServiceImpl implements MuteService { } saveHistoryAsync(); } - + private void saveHistoryAsync() { FoliaUtil.runAsync(plugin, this::saveHistory); } - + private void saveAsync() { FoliaUtil.runAsync(plugin, () -> { save(); diff --git a/src/main/java/com/loki/lochat/core/service/NickServiceImpl.java b/src/main/java/com/loki/lochat/core/service/NickServiceImpl.java index cd110ec..adcc964 100644 --- a/src/main/java/com/loki/lochat/core/service/NickServiceImpl.java +++ b/src/main/java/com/loki/lochat/core/service/NickServiceImpl.java @@ -12,28 +12,29 @@ import org.bukkit.plugin.java.JavaPlugin; import java.io.File; import java.io.IOException; -import java.util.*; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; /** * Реализация сервиса кастомных ников */ public class NickServiceImpl implements NickService { + // Настройки + private static final int MIN_LENGTH = 3; + private static final int MAX_LENGTH = 16; private final JavaPlugin plugin; private final Map nicknames = new ConcurrentHashMap<>(); private final File dataFile; private FileConfiguration data; - - // Настройки - private static final int MIN_LENGTH = 3; - private static final int MAX_LENGTH = 16; - + public NickServiceImpl(JavaPlugin plugin) { this.plugin = plugin; this.dataFile = new File(plugin.getDataFolder(), "nicknames.yml"); load(); } - + private void load() { if (!dataFile.exists()) { try { @@ -43,9 +44,9 @@ public class NickServiceImpl implements NickService { plugin.getLogger().warning("Не удалось создать nicknames.yml: " + e.getMessage()); } } - + data = YamlConfiguration.loadConfiguration(dataFile); - + // Загружаем ники if (data.contains("nicknames")) { for (String key : data.getConfigurationSection("nicknames").getKeys(false)) { @@ -54,10 +55,10 @@ public class NickServiceImpl implements NickService { nicknames.put(uuid, nickname); } } - + plugin.getLogger().info("Загружено " + nicknames.size() + " кастомных ников"); } - + @Override public void save() { // Сохраняем ники @@ -65,21 +66,21 @@ public class NickServiceImpl implements NickService { for (Map.Entry entry : nicknames.entrySet()) { data.set("nicknames." + entry.getKey().toString(), entry.getValue()); } - + try { data.save(dataFile); } catch (IOException e) { plugin.getLogger().warning("Не удалось сохранить nicknames.yml: " + e.getMessage()); } } - + @Override public boolean setNickname(UUID player, String nickname) { // Валидация if (!isValidNickname(nickname)) { return false; } - + // Проверка уникальности if (isNicknameTaken(nickname)) { // Проверяем не свой ли это ник @@ -88,23 +89,23 @@ public class NickServiceImpl implements NickService { return false; } } - + // Устанавливаем ник nicknames.put(player, nickname); - + // Обновляем display Player onlinePlayer = Bukkit.getPlayer(player); if (onlinePlayer != null) { updatePlayerDisplay(onlinePlayer); } - + return true; } - + @Override public void resetNickname(UUID player) { nicknames.remove(player); - + // Сбрасываем display Player onlinePlayer = Bukkit.getPlayer(player); if (onlinePlayer != null) { @@ -112,59 +113,55 @@ public class NickServiceImpl implements NickService { onlinePlayer.playerListName(Component.text(onlinePlayer.getName())); } } - + @Override public Optional getNickname(UUID player) { return Optional.ofNullable(nicknames.get(player)); } - + @Override public boolean isNicknameTaken(String nickname) { String cleanNick = stripColors(nickname).toLowerCase(); - + // Проверяем существующие ники for (String existingNick : nicknames.values()) { if (stripColors(existingNick).equalsIgnoreCase(cleanNick)) { return true; } } - + // Проверяем реальные ники онлайн игроков for (Player player : Bukkit.getOnlinePlayers()) { if (player.getName().equalsIgnoreCase(cleanNick)) { return true; } } - + return false; } - + @Override public boolean isValidNickname(String nickname) { if (nickname == null || nickname.isEmpty()) { return false; } - + // Убираем цвета для проверки длины String cleanNick = stripColors(nickname); - + // Проверка длины if (cleanNick.length() < MIN_LENGTH || cleanNick.length() > MAX_LENGTH) { return false; } - + // Проверка символов (разрешены буквы, цифры, _, русские буквы) - if (!cleanNick.matches("[a-zA-Zа-яА-Я0-9_]+")) { - return false; - } - - return true; + return cleanNick.matches("[a-zA-Zа-яА-Я0-9_]+"); } - + @Override public void updatePlayerDisplay(Player player) { Optional nickname = getNickname(player.getUniqueId()); - + if (nickname.isPresent()) { // Парсим ник с цветами Component nickComponent = ChatFormatter.parse(nickname.get()); @@ -176,7 +173,7 @@ public class NickServiceImpl implements NickService { player.playerListName(Component.text(player.getName())); } } - + /** * Убирает цвета из строки */ diff --git a/src/main/java/com/loki/lochat/core/service/PlayerDataServiceImpl.java b/src/main/java/com/loki/lochat/core/service/PlayerDataServiceImpl.java index 62dc941..0b0037f 100644 --- a/src/main/java/com/loki/lochat/core/service/PlayerDataServiceImpl.java +++ b/src/main/java/com/loki/lochat/core/service/PlayerDataServiceImpl.java @@ -11,16 +11,16 @@ import java.util.UUID; */ public class PlayerDataServiceImpl implements PlayerDataService { private final CooldownService cooldownService; - + public PlayerDataServiceImpl(JavaPlugin plugin) { this.cooldownService = new CooldownServiceImpl(); } - + @Override public void clearPlayerData(UUID player) { cooldownService.removeCooldown(player); } - + @Override public void saveAll() { // Сохранение всех данных при выключении diff --git a/src/main/java/com/loki/lochat/core/service/SpyServiceImpl.java b/src/main/java/com/loki/lochat/core/service/SpyServiceImpl.java index 45a1934..4d90cb7 100644 --- a/src/main/java/com/loki/lochat/core/service/SpyServiceImpl.java +++ b/src/main/java/com/loki/lochat/core/service/SpyServiceImpl.java @@ -60,10 +60,10 @@ public class SpyServiceImpl implements SpyService { @Override public void sendToSpies(Player sender, Component message, boolean isGlobal) { if (spyEnabled.isEmpty()) return; - + String chatType = isGlobal ? "Global" : "Local"; String plainMessage = PlainTextComponentSerializer.plainText().serialize(message); - String format = messageConfig.get("spy.chat-format", + String format = messageConfig.get("spy.chat-format", "§7[SPY] §e{type} §7{sender}: §f{message}"); for (UUID spyUuid : spyEnabled) { diff --git a/src/main/java/com/loki/lochat/data/model/ChatMessage.java b/src/main/java/com/loki/lochat/data/model/ChatMessage.java index f44a1ac..53259fd 100644 --- a/src/main/java/com/loki/lochat/data/model/ChatMessage.java +++ b/src/main/java/com/loki/lochat/data/model/ChatMessage.java @@ -7,33 +7,50 @@ import org.bukkit.entity.Player; */ public class ChatMessage { private final Player sender; - private String content; private final boolean isGlobal; private final long timestamp; - + private String content; + private ChatMessage(Player sender, String content, boolean isGlobal) { this.sender = sender; this.content = content; this.isGlobal = isGlobal; this.timestamp = System.currentTimeMillis(); } - + public static ChatMessage create(Player sender, String rawMessage) { // Определяем тип чата - boolean isGlobal = rawMessage.startsWith("!") && - sender.hasPermission("chat.global.use"); - - String content = isGlobal ? - rawMessage.substring(1).trim() : - rawMessage.trim(); - + boolean isGlobal = rawMessage.startsWith("!") && + sender.hasPermission("chat.global.use"); + + String content = isGlobal ? + rawMessage.substring(1).trim() : + rawMessage.trim(); + return new ChatMessage(sender, content, isGlobal); } - - public Player getSender() { return sender; } - public String getContent() { return content; } - public void setContent(String content) { this.content = content; } - public boolean isGlobal() { return isGlobal; } - public long getTimestamp() { return timestamp; } - public String getChatType() { return isGlobal ? "global" : "local"; } + + public Player getSender() { + return sender; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public boolean isGlobal() { + return isGlobal; + } + + public long getTimestamp() { + return timestamp; + } + + public String getChatType() { + return isGlobal ? "global" : "local"; + } } diff --git a/src/main/java/com/loki/lochat/data/model/MuteData.java b/src/main/java/com/loki/lochat/data/model/MuteData.java index 8180757..88ffb36 100644 --- a/src/main/java/com/loki/lochat/data/model/MuteData.java +++ b/src/main/java/com/loki/lochat/data/model/MuteData.java @@ -6,15 +6,16 @@ import java.util.UUID; * Модель данных мута (Value Object) */ public class MuteData { - private UUID uuid; - private String playerName; public long endTime; // 0 = перманентный (public for JSON serialization) public String reason; public String mutedBy; public long mutedAt; - - public MuteData() {} // For JSON deserialization - + private UUID uuid; + private String playerName; + + public MuteData() { + } // For JSON deserialization + public MuteData(UUID uuid, String playerName, long endTime, String reason, String mutedBy) { this.uuid = uuid; this.playerName = playerName; @@ -23,7 +24,7 @@ public class MuteData { this.mutedBy = mutedBy; this.mutedAt = System.currentTimeMillis(); } - + public MuteData(long endTime, String reason, String mutedBy, long mutedAt, String playerName) { this.endTime = endTime; this.reason = reason; @@ -31,15 +32,35 @@ public class MuteData { this.mutedAt = mutedAt; this.playerName = playerName; } - - public UUID getUuid() { return uuid; } - public String getPlayerName() { return playerName; } - public long getEndTime() { return endTime; } - public String getReason() { return reason; } - public String getMutedBy() { return mutedBy; } - public long getMutedAt() { return mutedAt; } - public boolean isPermanent() { return endTime == 0; } - + + public UUID getUuid() { + return uuid; + } + + public String getPlayerName() { + return playerName; + } + + public long getEndTime() { + return endTime; + } + + public String getReason() { + return reason; + } + + public String getMutedBy() { + return mutedBy; + } + + public long getMutedAt() { + return mutedAt; + } + + public boolean isPermanent() { + return endTime == 0; + } + /** * Запись истории мута */ @@ -52,12 +73,13 @@ public class MuteData { public boolean unmuted; public String unmutedBy; public long unmutedAt; - - public MuteHistoryEntry() {} // For JSON deserialization - - public MuteHistoryEntry(String playerName, long duration, String reason, - String mutedBy, long mutedAt, boolean unmuted, - String unmutedBy, long unmutedAt) { + + public MuteHistoryEntry() { + } // For JSON deserialization + + public MuteHistoryEntry(String playerName, long duration, String reason, + String mutedBy, long mutedAt, boolean unmuted, + String unmutedBy, long unmutedAt) { this.playerName = playerName; this.duration = duration; this.reason = reason; diff --git a/src/main/java/com/loki/lochat/gradient/GradientModule.java b/src/main/java/com/loki/lochat/gradient/GradientModule.java index c6edb58..b7dfe18 100644 --- a/src/main/java/com/loki/lochat/gradient/GradientModule.java +++ b/src/main/java/com/loki/lochat/gradient/GradientModule.java @@ -37,18 +37,19 @@ public class GradientModule { /** * Инициализация модуля + * * @return true если модуль успешно инициализирован */ public boolean init() { // Загружаем конфиги config = new GradientConfig(plugin); messages = new GradientMessages(plugin); - + if (!config.isEnabled()) { plugin.getLogger().info("Gradient модуль отключен в конфиге."); return false; } - + // Проверяем PlayerPoints (опционально теперь) if (Bukkit.getPluginManager().isPluginEnabled("PlayerPoints")) { playerPointsAPI = PlayerPoints.getInstance().getAPI(); @@ -56,10 +57,10 @@ public class GradientModule { } else { plugin.getLogger().warning("Gradient: PlayerPoints не найден. Покупки будут бесплатными."); } - + // Инициализация хранилища dataManager = new GradientDataManager(plugin, config); - + // Подключение LuckPerms (опционально) try { if (Bukkit.getPluginManager().isPluginEnabled("LuckPerms")) { @@ -71,15 +72,15 @@ public class GradientModule { } catch (NoClassDefFoundError e) { plugin.getLogger().info("Gradient: LuckPerms не найден. Префиксы LuckPerms будут недоступны."); } - - + + // Регистрация команд registerCommands(); - + // Регистрация слушателей Bukkit.getPluginManager().registerEvents(new GradientPlayerListener(this), plugin); Bukkit.getPluginManager().registerEvents(new GradientGUIListener(this), plugin); - + enabled = true; plugin.getLogger().info("Gradient модуль успешно загружен!"); return true; @@ -91,13 +92,13 @@ public class GradientModule { plugin.getCommand("color").setExecutor(colorCommand); plugin.getCommand("color").setTabCompleter(colorCommand); } - + GradientPrefixCommand prefixCommand = new GradientPrefixCommand(this); if (plugin.getCommand("prefix") != null) { plugin.getCommand("prefix").setExecutor(prefixCommand); plugin.getCommand("prefix").setTabCompleter(prefixCommand); } - + GradientAdminCommand adminCommand = new GradientAdminCommand(this); if (plugin.getCommand("aprefix") != null) { plugin.getCommand("aprefix").setExecutor(adminCommand); @@ -141,22 +142,23 @@ public class GradientModule { /** * Получает отформатированное имя игрока с градиентом и LuckPerms префиксом + * * @param useTabFormat true для §x§... формата (TAB), false для &#RRGGBB */ private String getFormattedName(Player player, boolean useTabFormat) { if (!enabled) return player.getName(); - + GradientPlayerData data = dataManager.getPlayerData(player.getUniqueId()); - + // Собираем полную строку: префикс + ник StringBuilder fullText = new StringBuilder(); - + // LuckPerms префикс String lpPrefix = null; if (luckPermsHook.isEnabled()) { lpPrefix = luckPermsHook.getActivePrefix(player); } - + // Определяем какой префикс использовать if (data.hasPrefix() && data.isPrefixEnabled()) { // Кастомный префикс @@ -167,21 +169,21 @@ public class GradientModule { fullText.append(stripColors(lpPrefix)); } else { // LP префикс со своими цветами, ник отдельно - String nick = data.hasColors() && data.isColorEnabled() - ? applyGradientWithFormat(player.getName(), data.getColors(), useTabFormat) - : player.getName(); + String nick = data.hasColors() && data.isColorEnabled() + ? applyGradientWithFormat(player.getName(), data.getColors(), useTabFormat) + : player.getName(); return lpPrefix + nick; } } - + // Добавляем ник fullText.append(player.getName()); - + // Применяем единый градиент на всю строку if (data.hasColors() && data.isColorEnabled()) { return applyGradientWithFormat(fullText.toString(), data.getColors(), useTabFormat); } - + return fullText.toString(); } @@ -211,12 +213,12 @@ public class GradientModule { */ public String getGradientNick(Player player) { if (!enabled) return player.getName(); - + GradientPlayerData data = dataManager.getPlayerData(player.getUniqueId()); if (!data.hasColors() || !data.isColorEnabled()) { return player.getName(); } - + return GradientUtil.applyGradient(player.getName(), data.getColors(), config.isUseLegacyRgbFormat()); } @@ -226,9 +228,9 @@ public class GradientModule { */ public String getPrefix(Player player) { if (!enabled) return ""; - + GradientPlayerData data = dataManager.getPlayerData(player.getUniqueId()); - + // Кастомный префикс if (data.hasPrefix() && data.isPrefixEnabled()) { String prefix = config.getPrefixFormat().replace("{prefix}", data.getPrefix()); @@ -237,7 +239,7 @@ public class GradientModule { } return prefix; } - + // LuckPerms префикс if (luckPermsHook.isEnabled()) { String lpPrefix = luckPermsHook.getActivePrefix(player); @@ -249,7 +251,7 @@ public class GradientModule { return lpPrefix; } } - + return ""; } @@ -263,12 +265,35 @@ public class GradientModule { } // Геттеры - public JavaPlugin getPlugin() { return plugin; } - public GradientConfig getConfig() { return config; } - public GradientMessages getMessages() { return messages; } - public GradientDataManager getDataManager() { return dataManager; } - public GradientLuckPermsHook getLuckPermsHook() { return luckPermsHook; } - public PlayerPointsAPI getPlayerPointsAPI() { return playerPointsAPI; } - public boolean hasPlayerPoints() { return playerPointsAPI != null; } - public boolean isEnabled() { return enabled; } + public JavaPlugin getPlugin() { + return plugin; + } + + public GradientConfig getConfig() { + return config; + } + + public GradientMessages getMessages() { + return messages; + } + + public GradientDataManager getDataManager() { + return dataManager; + } + + public GradientLuckPermsHook getLuckPermsHook() { + return luckPermsHook; + } + + public PlayerPointsAPI getPlayerPointsAPI() { + return playerPointsAPI; + } + + public boolean hasPlayerPoints() { + return playerPointsAPI != null; + } + + public boolean isEnabled() { + return enabled; + } } diff --git a/src/main/java/com/loki/lochat/gradient/commands/GradientAdminCommand.java b/src/main/java/com/loki/lochat/gradient/commands/GradientAdminCommand.java index 525a85f..ad488cf 100644 --- a/src/main/java/com/loki/lochat/gradient/commands/GradientAdminCommand.java +++ b/src/main/java/com/loki/lochat/gradient/commands/GradientAdminCommand.java @@ -26,10 +26,10 @@ import java.util.List; */ public class GradientAdminCommand implements CommandExecutor, TabCompleter { - private final GradientModule module; private static final List PRESET_COLORS = Arrays.asList( "#FF0000", "#FF7F00", "#FFFF00", "#00FF00", "#0000FF", "#4B0082", "#9400D3" ); + private final GradientModule module; public GradientAdminCommand(GradientModule module) { this.module = module; @@ -153,11 +153,11 @@ public class GradientAdminCommand implements CommandExecutor, TabCompleter { Player onlineTarget = target.getPlayer(); if (onlineTarget != null) { - FoliaUtil.runEntityTask(module.getPlugin(), onlineTarget, + FoliaUtil.runEntityTask(module.getPlugin(), onlineTarget, () -> DisplayNameUtil.updateDisplayName(module, onlineTarget, data)); } - FoliaUtil.runAsync(module.getPlugin(), + FoliaUtil.runAsync(module.getPlugin(), () -> module.getDataManager().savePlayerData(target.getUniqueId())); sender.sendMessage("§aЦвет для игрока §f" + args[1] + " §aустановлен: §f" + String.join(" ", colors)); @@ -194,11 +194,11 @@ public class GradientAdminCommand implements CommandExecutor, TabCompleter { Player onlineTarget = target.getPlayer(); if (onlineTarget != null) { - FoliaUtil.runEntityTask(module.getPlugin(), onlineTarget, + FoliaUtil.runEntityTask(module.getPlugin(), onlineTarget, () -> DisplayNameUtil.updateDisplayName(module, onlineTarget, data)); } - FoliaUtil.runAsync(module.getPlugin(), + FoliaUtil.runAsync(module.getPlugin(), () -> module.getDataManager().savePlayerData(target.getUniqueId())); sender.sendMessage("§aПрефикс для игрока §f" + args[1] + " §aустановлен: §f" + prefix); @@ -209,7 +209,7 @@ public class GradientAdminCommand implements CommandExecutor, TabCompleter { sender.sendMessage("§cИспользование: /aprefix " + (enable ? "coloron" : "coloroff") + " <игрок>"); return; } - + OfflinePlayer target = Bukkit.getOfflinePlayer(args[1]); if (!target.hasPlayedBefore() && !target.isOnline()) { msg.send(sender, "player-not-found"); @@ -221,11 +221,11 @@ public class GradientAdminCommand implements CommandExecutor, TabCompleter { Player onlineTarget = target.getPlayer(); if (onlineTarget != null) { - FoliaUtil.runEntityTask(module.getPlugin(), onlineTarget, + FoliaUtil.runEntityTask(module.getPlugin(), onlineTarget, () -> DisplayNameUtil.updateDisplayName(module, onlineTarget, data)); } - FoliaUtil.runAsync(module.getPlugin(), + FoliaUtil.runAsync(module.getPlugin(), () -> module.getDataManager().savePlayerData(target.getUniqueId())); sender.sendMessage("§aЦвет для игрока §f" + args[1] + (enable ? " §aвключён" : " §cвыключен")); @@ -236,7 +236,7 @@ public class GradientAdminCommand implements CommandExecutor, TabCompleter { sender.sendMessage("§cИспользование: /aprefix " + (enable ? "prefixon" : "prefixoff") + " <игрок>"); return; } - + OfflinePlayer target = Bukkit.getOfflinePlayer(args[1]); if (!target.hasPlayedBefore() && !target.isOnline()) { msg.send(sender, "player-not-found"); @@ -256,11 +256,11 @@ public class GradientAdminCommand implements CommandExecutor, TabCompleter { Player onlineTarget = target.getPlayer(); if (onlineTarget != null) { - FoliaUtil.runEntityTask(module.getPlugin(), onlineTarget, + FoliaUtil.runEntityTask(module.getPlugin(), onlineTarget, () -> DisplayNameUtil.updateDisplayName(module, onlineTarget, data)); } - FoliaUtil.runAsync(module.getPlugin(), + FoliaUtil.runAsync(module.getPlugin(), () -> module.getDataManager().savePlayerData(target.getUniqueId())); sender.sendMessage("§aПрефикс для игрока §f" + args[1] + (enable ? " §aвключён" : " §cвыключен")); @@ -271,7 +271,7 @@ public class GradientAdminCommand implements CommandExecutor, TabCompleter { sender.sendMessage("§cИспользование: /aprefix resetcolor <игрок>"); return; } - + OfflinePlayer target = Bukkit.getOfflinePlayer(args[1]); if (!target.hasPlayedBefore() && !target.isOnline()) { msg.send(sender, "player-not-found"); @@ -284,11 +284,11 @@ public class GradientAdminCommand implements CommandExecutor, TabCompleter { Player onlineTarget = target.getPlayer(); if (onlineTarget != null) { - FoliaUtil.runEntityTask(module.getPlugin(), onlineTarget, + FoliaUtil.runEntityTask(module.getPlugin(), onlineTarget, () -> DisplayNameUtil.updateDisplayName(module, onlineTarget, data)); } - FoliaUtil.runAsync(module.getPlugin(), + FoliaUtil.runAsync(module.getPlugin(), () -> module.getDataManager().savePlayerData(target.getUniqueId())); sender.sendMessage("§aЦвет для игрока §f" + args[1] + " §aсброшен"); @@ -299,7 +299,7 @@ public class GradientAdminCommand implements CommandExecutor, TabCompleter { sender.sendMessage("§cИспользование: /aprefix resetprefix <игрок>"); return; } - + OfflinePlayer target = Bukkit.getOfflinePlayer(args[1]); if (!target.hasPlayedBefore() && !target.isOnline()) { msg.send(sender, "player-not-found"); @@ -316,11 +316,11 @@ public class GradientAdminCommand implements CommandExecutor, TabCompleter { Player onlineTarget = target.getPlayer(); if (onlineTarget != null) { - FoliaUtil.runEntityTask(module.getPlugin(), onlineTarget, + FoliaUtil.runEntityTask(module.getPlugin(), onlineTarget, () -> DisplayNameUtil.updateDisplayName(module, onlineTarget, data)); } - FoliaUtil.runAsync(module.getPlugin(), + FoliaUtil.runAsync(module.getPlugin(), () -> module.getDataManager().savePlayerData(target.getUniqueId())); sender.sendMessage("§aПрефикс для игрока §f" + args[1] + " §aсброшен"); @@ -330,7 +330,7 @@ public class GradientAdminCommand implements CommandExecutor, TabCompleter { int count = 0; for (Player player : Bukkit.getOnlinePlayers()) { GradientPlayerData data = module.getDataManager().getPlayerData(player.getUniqueId()); - FoliaUtil.runEntityTask(module.getPlugin(), player, + FoliaUtil.runEntityTask(module.getPlugin(), player, () -> DisplayNameUtil.updateDisplayName(module, player, data)); count++; } @@ -340,19 +340,19 @@ public class GradientAdminCommand implements CommandExecutor, TabCompleter { @Override public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, - @NotNull String alias, @NotNull String[] args) { + @NotNull String alias, @NotNull String[] args) { if (!sender.hasPermission("gradient.admin")) return new ArrayList<>(); if (args.length == 1) { - return Arrays.asList("reload", "info", "setcolor", "setprefix", "coloron", "coloroff", - "prefixon", "prefixoff", "resetcolor", "resetprefix", "updateall").stream() + return Arrays.asList("reload", "info", "setcolor", "setprefix", "coloron", "coloroff", + "prefixon", "prefixoff", "resetcolor", "resetprefix", "updateall").stream() .filter(s -> s.startsWith(args[0].toLowerCase())) .toList(); } if (args.length == 2) { String sub = args[0].toLowerCase(); - if (Arrays.asList("info", "setcolor", "setprefix", "coloron", "coloroff", + if (Arrays.asList("info", "setcolor", "setprefix", "coloron", "coloroff", "prefixon", "prefixoff", "resetcolor", "resetprefix").contains(sub)) { return Bukkit.getOnlinePlayers().stream() .map(Player::getName) diff --git a/src/main/java/com/loki/lochat/gradient/commands/GradientColorCommand.java b/src/main/java/com/loki/lochat/gradient/commands/GradientColorCommand.java index 864e713..f9bda89 100644 --- a/src/main/java/com/loki/lochat/gradient/commands/GradientColorCommand.java +++ b/src/main/java/com/loki/lochat/gradient/commands/GradientColorCommand.java @@ -26,14 +26,13 @@ import java.util.function.BiFunction; */ public class GradientColorCommand implements CommandExecutor, TabCompleter { - private final GradientModule module; - private final Map> subCommands = new HashMap<>(); - private static final List PRESET_COLORS = List.of( "#FF0000", "#FF7F00", "#FFFF00", "#00FF00", "#0000FF", "#4B0082", "#9400D3", "#FF69B4", "#00FFFF", "#FFD700", "#FFFFFF", "#000000" ); private static final Set SUB_COMMANDS = Set.of("on", "off", "reset", "copy"); + private final GradientModule module; + private final Map> subCommands = new HashMap<>(); public GradientColorCommand(GradientModule module) { this.module = module; @@ -77,12 +76,12 @@ public class GradientColorCommand implements CommandExecutor, TabCompleter { private boolean handleOn(Player player, String[] args) { GradientPlayerData data = module.getDataManager().getPlayerData(player.getUniqueId()); GradientMessages msg = module.getMessages(); - + if (!data.hasColors()) { msg.send(player, "color-no-colors"); return true; } - + data.setColorEnabled(true); saveAndUpdate(player, data); msg.send(player, "color-enabled"); @@ -100,12 +99,12 @@ public class GradientColorCommand implements CommandExecutor, TabCompleter { private boolean handleReset(Player player, String[] args) { GradientPlayerData data = module.getDataManager().getPlayerData(player.getUniqueId()); GradientMessages msg = module.getMessages(); - + if (!data.hasColors()) { msg.send(player, "color-no-colors"); return true; } - + data.setColors(new ArrayList<>()); data.setColorEnabled(false); saveAndUpdate(player, data); @@ -116,18 +115,18 @@ public class GradientColorCommand implements CommandExecutor, TabCompleter { private boolean handleCopy(Player player, String[] args) { GradientMessages msg = module.getMessages(); GradientConfig cfg = module.getConfig(); - + if (args.length < 2) { msg.send(player, "color-copy-usage"); return true; } - + Player target = Bukkit.getPlayer(args[1]); if (target == null) { msg.send(player, "player-not-found"); return true; } - + GradientPlayerData targetData = module.getDataManager().getPlayerData(target.getUniqueId()); if (!targetData.hasColors()) { msg.send(player, "color-copy-no-colors", "player", target.getName()); @@ -135,8 +134,8 @@ public class GradientColorCommand implements CommandExecutor, TabCompleter { } GradientPlayerData data = module.getDataManager().getPlayerData(player.getUniqueId()); - - if (!player.hasPermission("gradient.bypass.cooldown") && + + if (!player.hasPermission("gradient.bypass.cooldown") && !checkCooldown(player, cfg.getColorCooldown(), data.getLastColorChange())) { return true; } @@ -148,7 +147,7 @@ public class GradientColorCommand implements CommandExecutor, TabCompleter { return true; } - GradientConfirmGUI gui = new GradientConfirmGUI(module, player, + GradientConfirmGUI gui = new GradientConfirmGUI(module, player, GradientConfirmGUI.ConfirmType.COLOR, colors, data.getPrefix(), price); FoliaUtil.runEntityTask(module.getPlugin(), player, gui::open); return true; @@ -170,7 +169,7 @@ public class GradientColorCommand implements CommandExecutor, TabCompleter { GradientPlayerData data = module.getDataManager().getPlayerData(player.getUniqueId()); - if (!player.hasPermission("gradient.bypass.cooldown") && + if (!player.hasPermission("gradient.bypass.cooldown") && !checkCooldown(player, cfg.getColorCooldown(), data.getLastColorChange())) { return true; } @@ -191,7 +190,7 @@ public class GradientColorCommand implements CommandExecutor, TabCompleter { return true; } - GradientConfirmGUI gui = new GradientConfirmGUI(module, player, + GradientConfirmGUI gui = new GradientConfirmGUI(module, player, GradientConfirmGUI.ConfirmType.COLOR, colors, data.getPrefix(), price); FoliaUtil.runEntityTask(module.getPlugin(), player, gui::open); return true; @@ -222,35 +221,35 @@ public class GradientColorCommand implements CommandExecutor, TabCompleter { } private void saveAndUpdate(Player player, GradientPlayerData data) { - FoliaUtil.runEntityTask(module.getPlugin(), player, + FoliaUtil.runEntityTask(module.getPlugin(), player, () -> DisplayNameUtil.updateDisplayName(module, player, data)); - FoliaUtil.runAsync(module.getPlugin(), + FoliaUtil.runAsync(module.getPlugin(), () -> module.getDataManager().savePlayerData(player.getUniqueId())); } @Override public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, - @NotNull String alias, @NotNull String[] args) { + @NotNull String alias, @NotNull String[] args) { if (args.length == 1) { String input = args[0].toLowerCase(); List completions = new ArrayList<>(SUB_COMMANDS); completions.addAll(PRESET_COLORS); return completions.stream().filter(s -> s.toLowerCase().startsWith(input)).toList(); } - + String firstArg = args[0].toLowerCase(); - + if (args.length == 2 && firstArg.equals("copy")) { return Bukkit.getOnlinePlayers().stream().map(Player::getName) .filter(s -> s.toLowerCase().startsWith(args[1].toLowerCase())).toList(); } - + if (!SUB_COMMANDS.contains(firstArg) && args.length <= module.getConfig().getMaxColors()) { return PRESET_COLORS.stream() .filter(s -> s.toLowerCase().startsWith(args[args.length - 1].toLowerCase())) .toList(); } - + return List.of(); } } diff --git a/src/main/java/com/loki/lochat/gradient/commands/GradientPrefixCommand.java b/src/main/java/com/loki/lochat/gradient/commands/GradientPrefixCommand.java index 2beee6f..66a5bdb 100644 --- a/src/main/java/com/loki/lochat/gradient/commands/GradientPrefixCommand.java +++ b/src/main/java/com/loki/lochat/gradient/commands/GradientPrefixCommand.java @@ -28,13 +28,12 @@ import java.util.regex.Pattern; */ public class GradientPrefixCommand implements CommandExecutor, TabCompleter { - private final GradientModule module; - private final Map> subCommands = new HashMap<>(); - private static final Pattern COLOR_CODE_PATTERN = Pattern.compile( "(?i)(&[0-9a-fk-or]|§[0-9a-fk-or]|#[0-9a-f]{6}|&#[0-9a-f]{6}|<#[0-9a-f]{6}>)"); private static final Pattern ALLOWED_PREFIX_PATTERN = Pattern.compile("^[a-zA-Zа-яА-ЯёЁ0-9 _\\-]+$"); private static final Set SUB_COMMANDS = Set.of("on", "off", "reset"); + private final GradientModule module; + private final Map> subCommands = new HashMap<>(); public GradientPrefixCommand(GradientModule module) { this.module = module; @@ -77,12 +76,12 @@ public class GradientPrefixCommand implements CommandExecutor, TabCompleter { private boolean handleOn(Player player, String[] args) { GradientPlayerData data = module.getDataManager().getPlayerData(player.getUniqueId()); GradientMessages msg = module.getMessages(); - + if (!data.hasPrefix()) { msg.send(player, "prefix-no-prefix"); return true; } - + data.setPrefixEnabled(true); if (module.getLuckPermsHook() != null) { module.getLuckPermsHook().setPrefix(player, DisplayNameUtil.buildColoredPrefix(module, data)); @@ -106,12 +105,12 @@ public class GradientPrefixCommand implements CommandExecutor, TabCompleter { private boolean handleReset(Player player, String[] args) { GradientPlayerData data = module.getDataManager().getPlayerData(player.getUniqueId()); GradientMessages msg = module.getMessages(); - + if (!data.hasPrefix()) { msg.send(player, "prefix-no-prefix"); return true; } - + data.setPrefix(null); data.setPrefixEnabled(false); if (module.getLuckPermsHook() != null) { @@ -154,7 +153,7 @@ public class GradientPrefixCommand implements CommandExecutor, TabCompleter { GradientPlayerData data = module.getDataManager().getPlayerData(player.getUniqueId()); - if (!player.hasPermission("gradient.bypass.cooldown") && + if (!player.hasPermission("gradient.bypass.cooldown") && !checkCooldown(player, cfg.getPrefixCooldown(), data.getLastPrefixChange())) { return true; } @@ -165,9 +164,9 @@ public class GradientPrefixCommand implements CommandExecutor, TabCompleter { return true; } - GradientConfirmGUI gui = new GradientConfirmGUI(module, player, - GradientConfirmGUI.ConfirmType.PREFIX, - data.hasColors() && data.isColorEnabled() ? data.getColors() : null, + GradientConfirmGUI gui = new GradientConfirmGUI(module, player, + GradientConfirmGUI.ConfirmType.PREFIX, + data.hasColors() && data.isColorEnabled() ? data.getColors() : null, prefix, price); FoliaUtil.runEntityTask(module.getPlugin(), player, gui::open); return true; @@ -203,15 +202,15 @@ public class GradientPrefixCommand implements CommandExecutor, TabCompleter { } private void saveAndUpdate(Player player, GradientPlayerData data) { - FoliaUtil.runEntityTask(module.getPlugin(), player, + FoliaUtil.runEntityTask(module.getPlugin(), player, () -> DisplayNameUtil.updateDisplayName(module, player, data)); - FoliaUtil.runAsync(module.getPlugin(), + FoliaUtil.runAsync(module.getPlugin(), () -> module.getDataManager().savePlayerData(player.getUniqueId())); } @Override public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, - @NotNull String alias, @NotNull String[] args) { + @NotNull String alias, @NotNull String[] args) { if (args.length == 1) { return SUB_COMMANDS.stream() .filter(s -> s.startsWith(args[0].toLowerCase())) diff --git a/src/main/java/com/loki/lochat/gradient/config/GradientConfig.java b/src/main/java/com/loki/lochat/gradient/config/GradientConfig.java index 71fe716..f9bc218 100644 --- a/src/main/java/com/loki/lochat/gradient/config/GradientConfig.java +++ b/src/main/java/com/loki/lochat/gradient/config/GradientConfig.java @@ -33,7 +33,7 @@ public class GradientConfig { plugin.saveResource("gradient-config.yml", false); } config = YamlConfiguration.loadConfiguration(configFile); - + // Загружаем дефолты InputStream defStream = plugin.getResource("gradient-config.yml"); if (defStream != null) { @@ -56,23 +56,70 @@ public class GradientConfig { } } - public boolean isEnabled() { return config.getBoolean("enabled", true); } - public int getMaxColors() { return config.getInt("max-colors", 7); } - public int getMinColors() { return config.getInt("min-colors", 1); } - public int getPricePerColor() { return config.getInt("price-per-color", 50); } - public int getPrefixPrice() { return config.getInt("prefix-price", 500); } - public boolean isPrefixOneTimePurchase() { return config.getBoolean("prefix-one-time-purchase", true); } - public int getColorCooldown() { return config.getInt("color-cooldown", 60); } - public int getPrefixCooldown() { return config.getInt("prefix-cooldown", 300); } - public int getMaxPrefixLength() { return config.getInt("max-prefix-length", 7); } - public String getPrefixFormat() { return config.getString("prefix-format", "[{prefix}] "); } - public boolean isGradientOnPrefix() { return config.getBoolean("gradient-on-prefix", true); } - public boolean isGradientOnLuckPermsPrefix() { return config.getBoolean("gradient-on-luckperms-prefix", true); } - public boolean isContinuousGradient() { return config.getBoolean("continuous-gradient", true); } - public boolean isUseLegacyRgbFormat() { return config.getBoolean("use-legacy-rgb-format", true); } - public String getStorageType() { return config.getString("storage-type", "YAML"); } - public String getSqliteFile() { return config.getString("sqlite-file", "gradient-data.db"); } - + public boolean isEnabled() { + return config.getBoolean("enabled", true); + } + + public int getMaxColors() { + return config.getInt("max-colors", 7); + } + + public int getMinColors() { + return config.getInt("min-colors", 1); + } + + public int getPricePerColor() { + return config.getInt("price-per-color", 50); + } + + public int getPrefixPrice() { + return config.getInt("prefix-price", 500); + } + + public boolean isPrefixOneTimePurchase() { + return config.getBoolean("prefix-one-time-purchase", true); + } + + public int getColorCooldown() { + return config.getInt("color-cooldown", 60); + } + + public int getPrefixCooldown() { + return config.getInt("prefix-cooldown", 300); + } + + public int getMaxPrefixLength() { + return config.getInt("max-prefix-length", 7); + } + + public String getPrefixFormat() { + return config.getString("prefix-format", "[{prefix}] "); + } + + public boolean isGradientOnPrefix() { + return config.getBoolean("gradient-on-prefix", true); + } + + public boolean isGradientOnLuckPermsPrefix() { + return config.getBoolean("gradient-on-luckperms-prefix", true); + } + + public boolean isContinuousGradient() { + return config.getBoolean("continuous-gradient", true); + } + + public boolean isUseLegacyRgbFormat() { + return config.getBoolean("use-legacy-rgb-format", true); + } + + public String getStorageType() { + return config.getString("storage-type", "YAML"); + } + + public String getSqliteFile() { + return config.getString("sqlite-file", "gradient-data.db"); + } + public List getPrefixBlacklist() { return config.getStringList("prefix-blacklist"); } @@ -83,17 +130,17 @@ public class GradientConfig { .anyMatch(blacklisted -> lowerPrefix.contains(blacklisted.toLowerCase())); } - public boolean isUpdateDisplayName() { + public boolean isUpdateDisplayName() { if (mainConfig.contains("display.update-display-name")) { return mainConfig.getBoolean("display.update-display-name", true); } - return config.getBoolean("display.update-display-name", true); + return config.getBoolean("display.update-display-name", true); } - - public boolean isUpdateTabList() { + + public boolean isUpdateTabList() { if (mainConfig.contains("display.update-tab-list")) { return mainConfig.getBoolean("display.update-tab-list", true); } - return config.getBoolean("display.update-tab-list", true); + return config.getBoolean("display.update-tab-list", true); } } diff --git a/src/main/java/com/loki/lochat/gradient/config/GradientMessages.java b/src/main/java/com/loki/lochat/gradient/config/GradientMessages.java index 8c49f65..a44ff4b 100644 --- a/src/main/java/com/loki/lochat/gradient/config/GradientMessages.java +++ b/src/main/java/com/loki/lochat/gradient/config/GradientMessages.java @@ -32,7 +32,7 @@ public class GradientMessages { plugin.saveResource("gradient-messages.yml", false); } messages = YamlConfiguration.loadConfiguration(messagesFile); - + InputStream defStream = plugin.getResource("gradient-messages.yml"); if (defStream != null) { YamlConfiguration defConfig = YamlConfiguration.loadConfiguration( diff --git a/src/main/java/com/loki/lochat/gradient/data/GradientDataManager.java b/src/main/java/com/loki/lochat/gradient/data/GradientDataManager.java index 979d17b..b3a5d69 100644 --- a/src/main/java/com/loki/lochat/gradient/data/GradientDataManager.java +++ b/src/main/java/com/loki/lochat/gradient/data/GradientDataManager.java @@ -28,7 +28,7 @@ public class GradientDataManager { this.plugin = plugin; this.config = config; this.useSqlite = config.getStorageType().equalsIgnoreCase("SQLITE"); - + if (useSqlite) { initSqlite(); } else { @@ -40,20 +40,20 @@ public class GradientDataManager { try { File dbFile = new File(plugin.getDataFolder(), config.getSqliteFile()); sqliteConnection = DriverManager.getConnection("jdbc:sqlite:" + dbFile.getAbsolutePath()); - + try (Statement stmt = sqliteConnection.createStatement()) { stmt.executeUpdate(""" - CREATE TABLE IF NOT EXISTS gradient_data ( - uuid TEXT PRIMARY KEY, - prefix TEXT, - colors TEXT, - color_enabled INTEGER DEFAULT 1, - prefix_enabled INTEGER DEFAULT 1, - prefix_purchased INTEGER DEFAULT 0, - last_color_change INTEGER DEFAULT 0, - last_prefix_change INTEGER DEFAULT 0 - ) - """); + CREATE TABLE IF NOT EXISTS gradient_data ( + uuid TEXT PRIMARY KEY, + prefix TEXT, + colors TEXT, + color_enabled INTEGER DEFAULT 1, + prefix_enabled INTEGER DEFAULT 1, + prefix_purchased INTEGER DEFAULT 0, + last_color_change INTEGER DEFAULT 0, + last_prefix_change INTEGER DEFAULT 0 + ) + """); } plugin.getLogger().info("Gradient SQLite база данных инициализирована."); } catch (SQLException e) { @@ -65,7 +65,7 @@ public class GradientDataManager { private void loadYamlData() { File dataFile = new File(plugin.getDataFolder(), "gradient-data.yml"); if (!dataFile.exists()) return; - + FileConfiguration data = YamlConfiguration.loadConfiguration(dataFile); for (String uuidStr : data.getKeys(false)) { try { @@ -79,7 +79,8 @@ public class GradientDataManager { playerData.setLastColorChange(data.getLong(uuidStr + ".last-color-change", 0)); playerData.setLastPrefixChange(data.getLong(uuidStr + ".last-prefix-change", 0)); cache.put(uuid, playerData); - } catch (IllegalArgumentException ignored) {} + } catch (IllegalArgumentException ignored) { + } } } @@ -89,7 +90,7 @@ public class GradientDataManager { private GradientPlayerData loadPlayerData(UUID uuid) { GradientPlayerData data = new GradientPlayerData(uuid); - + if (useSqlite && sqliteConnection != null) { try (PreparedStatement stmt = sqliteConnection.prepareStatement( "SELECT prefix, colors, color_enabled, prefix_enabled, prefix_purchased, last_color_change, last_prefix_change FROM gradient_data WHERE uuid = ?")) { @@ -111,14 +112,14 @@ public class GradientDataManager { plugin.getLogger().warning("Ошибка загрузки gradient данных: " + e.getMessage()); } } - + return data; } public void savePlayerData(UUID uuid) { GradientPlayerData data = cache.get(uuid); if (data == null) return; - + if (useSqlite && sqliteConnection != null) { try (PreparedStatement stmt = sqliteConnection.prepareStatement( "INSERT OR REPLACE INTO gradient_data (uuid, prefix, colors, color_enabled, prefix_enabled, prefix_purchased, last_color_change, last_prefix_change) VALUES (?, ?, ?, ?, ?, ?, ?, ?)")) { @@ -150,7 +151,7 @@ public class GradientDataManager { private void saveYamlData() { File dataFile = new File(plugin.getDataFolder(), "gradient-data.yml"); FileConfiguration data = new YamlConfiguration(); - + for (Map.Entry entry : cache.entrySet()) { String path = entry.getKey().toString(); GradientPlayerData pd = entry.getValue(); @@ -162,7 +163,7 @@ public class GradientDataManager { data.set(path + ".last-color-change", pd.getLastColorChange()); data.set(path + ".last-prefix-change", pd.getLastPrefixChange()); } - + try { data.save(dataFile); } catch (IOException e) { diff --git a/src/main/java/com/loki/lochat/gradient/data/GradientPlayerData.java b/src/main/java/com/loki/lochat/gradient/data/GradientPlayerData.java index 2cfb3b4..4af59db 100644 --- a/src/main/java/com/loki/lochat/gradient/data/GradientPlayerData.java +++ b/src/main/java/com/loki/lochat/gradient/data/GradientPlayerData.java @@ -29,25 +29,71 @@ public class GradientPlayerData { this.lastPrefixChange = 0; } - public UUID getUuid() { return uuid; } - public String getPrefix() { return prefix; } - public void setPrefix(String prefix) { this.prefix = prefix; } - public List getColors() { return colors; } - + public UUID getUuid() { + return uuid; + } + + public String getPrefix() { + return prefix; + } + + public void setPrefix(String prefix) { + this.prefix = prefix; + } + + public List getColors() { + return colors; + } + public void setColors(List colors) { this.colors = colors != null ? new ArrayList<>(colors) : new ArrayList<>(); } - public boolean hasPrefix() { return prefix != null && !prefix.isEmpty(); } - public boolean hasColors() { return colors != null && !colors.isEmpty(); } - public boolean isColorEnabled() { return colorEnabled; } - public void setColorEnabled(boolean colorEnabled) { this.colorEnabled = colorEnabled; } - public boolean isPrefixEnabled() { return prefixEnabled; } - public void setPrefixEnabled(boolean prefixEnabled) { this.prefixEnabled = prefixEnabled; } - public boolean isPrefixPurchased() { return prefixPurchased; } - public void setPrefixPurchased(boolean prefixPurchased) { this.prefixPurchased = prefixPurchased; } - public long getLastColorChange() { return lastColorChange; } - public void setLastColorChange(long lastColorChange) { this.lastColorChange = lastColorChange; } - public long getLastPrefixChange() { return lastPrefixChange; } - public void setLastPrefixChange(long lastPrefixChange) { this.lastPrefixChange = lastPrefixChange; } + public boolean hasPrefix() { + return prefix != null && !prefix.isEmpty(); + } + + public boolean hasColors() { + return colors != null && !colors.isEmpty(); + } + + public boolean isColorEnabled() { + return colorEnabled; + } + + public void setColorEnabled(boolean colorEnabled) { + this.colorEnabled = colorEnabled; + } + + public boolean isPrefixEnabled() { + return prefixEnabled; + } + + public void setPrefixEnabled(boolean prefixEnabled) { + this.prefixEnabled = prefixEnabled; + } + + public boolean isPrefixPurchased() { + return prefixPurchased; + } + + public void setPrefixPurchased(boolean prefixPurchased) { + this.prefixPurchased = prefixPurchased; + } + + public long getLastColorChange() { + return lastColorChange; + } + + public void setLastColorChange(long lastColorChange) { + this.lastColorChange = lastColorChange; + } + + public long getLastPrefixChange() { + return lastPrefixChange; + } + + public void setLastPrefixChange(long lastPrefixChange) { + this.lastPrefixChange = lastPrefixChange; + } } diff --git a/src/main/java/com/loki/lochat/gradient/gui/GradientConfirmGUI.java b/src/main/java/com/loki/lochat/gradient/gui/GradientConfirmGUI.java index c6b86c5..6163663 100644 --- a/src/main/java/com/loki/lochat/gradient/gui/GradientConfirmGUI.java +++ b/src/main/java/com/loki/lochat/gradient/gui/GradientConfirmGUI.java @@ -23,27 +23,22 @@ import java.util.List; /** * GUI подтверждения для градиентного модуля */ -public class GradientConfirmGUI implements InventoryHolder { - - public enum ConfirmType { - COLOR, PREFIX - } +public final class GradientConfirmGUI implements InventoryHolder { private static final LegacyComponentSerializer SERIALIZER = LegacyComponentSerializer.builder() .character('&') .hexCharacter('#') .hexColors() .build(); - private final GradientModule module; private final Player player; - private final Inventory inventory; + private Inventory inventory; private final ConfirmType type; private final List colors; private final String prefix; private final int price; - public GradientConfirmGUI(GradientModule module, Player player, ConfirmType type, + public GradientConfirmGUI(GradientModule module, Player player, ConfirmType type, List colors, String prefix, int price) { this.module = module; this.player = player; @@ -51,7 +46,11 @@ public class GradientConfirmGUI implements InventoryHolder { this.colors = colors; this.prefix = prefix; this.price = price; - this.inventory = Bukkit.createInventory(this, 27, + } + + private void initInventory() { + if (inventory != null) return; + this.inventory = Bukkit.createInventory(this, 27, Component.text("Подтверждение", NamedTextColor.DARK_GRAY)); setupItems(); } @@ -65,12 +64,12 @@ public class GradientConfirmGUI implements InventoryHolder { ItemStack head = new ItemStack(Material.PLAYER_HEAD); SkullMeta skullMeta = (SkullMeta) head.getItemMeta(); skullMeta.setOwningPlayer(player); - + String preview = buildPreview(); // Для GUI используем LegacyComponentSerializer с поддержкой HEX Component previewComponent = SERIALIZER.deserialize(preview); skullMeta.displayName(previewComponent.decoration(TextDecoration.ITALIC, false)); - + List lore = new ArrayList<>(); lore.add(Component.empty()); lore.add(Component.text("Так будет выглядеть ваш ник", NamedTextColor.GRAY) @@ -134,7 +133,7 @@ public class GradientConfirmGUI implements InventoryHolder { if (lpPrefix != null && !lpPrefix.isEmpty()) { // Конвертируем LP префикс в legacy формат lpPrefix = convertToLegacy(lpPrefix); - + // Если градиент на LP префикс включен - применяем градиент на всю строку if (colorsToUse != null && !colorsToUse.isEmpty() && module.getConfig().isGradientOnLuckPermsPrefix()) { String cleanLpPrefix = stripColors(lpPrefix); @@ -187,14 +186,37 @@ public class GradientConfirmGUI implements InventoryHolder { } public void open() { + initInventory(); player.openInventory(inventory); } @Override - public @NotNull Inventory getInventory() { return inventory; } - public Player getPlayer() { return player; } - public ConfirmType getType() { return type; } - public List getColors() { return colors; } - public String getPrefix() { return prefix; } - public int getPrice() { return price; } + public @NotNull Inventory getInventory() { + initInventory(); + return inventory; + } + + public Player getPlayer() { + return player; + } + + public ConfirmType getType() { + return type; + } + + public List getColors() { + return colors; + } + + public String getPrefix() { + return prefix; + } + + public int getPrice() { + return price; + } + + public enum ConfirmType { + COLOR, PREFIX + } } diff --git a/src/main/java/com/loki/lochat/gradient/hooks/GradientLuckPermsHook.java b/src/main/java/com/loki/lochat/gradient/hooks/GradientLuckPermsHook.java index c93bf59..7f05069 100644 --- a/src/main/java/com/loki/lochat/gradient/hooks/GradientLuckPermsHook.java +++ b/src/main/java/com/loki/lochat/gradient/hooks/GradientLuckPermsHook.java @@ -22,7 +22,7 @@ public class GradientLuckPermsHook { public GradientLuckPermsHook(JavaPlugin plugin) { this.enabled = false; - + if (Bukkit.getPluginManager().isPluginEnabled("LuckPerms")) { try { this.luckPerms = LuckPermsProvider.get(); @@ -40,12 +40,12 @@ public class GradientLuckPermsHook { public void setPrefix(Player player, String prefix) { if (!isEnabled()) return; - + User user = luckPerms.getUserManager().getUser(player.getUniqueId()); if (user == null) return; - user.data().clear(node -> - node instanceof PrefixNode && ((PrefixNode) node).getPriority() == GradientConstants.LUCKPERMS_PREFIX_PRIORITY + user.data().clear(node -> + node instanceof PrefixNode && ((PrefixNode) node).getPriority() == GradientConstants.LUCKPERMS_PREFIX_PRIORITY ); if (prefix != null && !prefix.isEmpty()) { @@ -58,12 +58,12 @@ public class GradientLuckPermsHook { public void setPrefix(UUID uuid, String prefix) { if (!isEnabled()) return; - + luckPerms.getUserManager().loadUser(uuid).thenAccept(user -> { if (user == null) return; - user.data().clear(node -> - node instanceof PrefixNode && ((PrefixNode) node).getPriority() == GradientConstants.LUCKPERMS_PREFIX_PRIORITY + user.data().clear(node -> + node instanceof PrefixNode && ((PrefixNode) node).getPriority() == GradientConstants.LUCKPERMS_PREFIX_PRIORITY ); if (prefix != null && !prefix.isEmpty()) { @@ -85,10 +85,10 @@ public class GradientLuckPermsHook { public String getActivePrefix(Player player) { if (!isEnabled()) return null; - + User user = luckPerms.getUserManager().getUser(player.getUniqueId()); if (user == null) return null; - + CachedMetaData metaData = user.getCachedData().getMetaData(); return metaData.getPrefix(); } diff --git a/src/main/java/com/loki/lochat/gradient/listeners/GradientGUIListener.java b/src/main/java/com/loki/lochat/gradient/listeners/GradientGUIListener.java index 2ea3e4e..929a63f 100644 --- a/src/main/java/com/loki/lochat/gradient/listeners/GradientGUIListener.java +++ b/src/main/java/com/loki/lochat/gradient/listeners/GradientGUIListener.java @@ -19,12 +19,11 @@ import java.util.Map; */ public class GradientGUIListener implements Listener { - private final GradientModule module; - private static final Map PRICE_MSG_KEYS = Map.of( GradientConfirmGUI.ConfirmType.COLOR, "not-enough-points-color", GradientConfirmGUI.ConfirmType.PREFIX, "not-enough-points-prefix" ); + private final GradientModule module; public GradientGUIListener(GradientModule module) { this.module = module; @@ -33,9 +32,9 @@ public class GradientGUIListener implements Listener { @EventHandler public void onInventoryClick(InventoryClickEvent event) { if (!(event.getInventory().getHolder() instanceof GradientConfirmGUI gui)) return; - + event.setCancelled(true); - + if (!(event.getWhoClicked() instanceof Player player) || !player.equals(gui.getPlayer())) return; switch (event.getRawSlot()) { @@ -46,10 +45,10 @@ public class GradientGUIListener implements Listener { private void handleConfirm(Player player, GradientConfirmGUI gui) { player.closeInventory(); - + GradientMessages msg = module.getMessages(); int price = gui.getPrice(); - + if (price > 0 && !player.hasPermission("gradient.bypass.cost")) { if (!module.hasPlayerPoints()) { player.sendMessage("§cPlayerPoints не установлен!"); @@ -85,14 +84,14 @@ public class GradientGUIListener implements Listener { if (module.getLuckPermsHook() != null) { module.getLuckPermsHook().setPrefix(player, DisplayNameUtil.buildColoredPrefix(module, data)); } - msg.send(player, price > 0 ? "prefix-success" : "prefix-success-free", + msg.send(player, price > 0 ? "prefix-success" : "prefix-success-free", "price", String.valueOf(price)); } } - FoliaUtil.runEntityTask(module.getPlugin(), player, + FoliaUtil.runEntityTask(module.getPlugin(), player, () -> DisplayNameUtil.updateDisplayName(module, player, data)); - FoliaUtil.runAsync(module.getPlugin(), + FoliaUtil.runAsync(module.getPlugin(), () -> module.getDataManager().savePlayerData(player.getUniqueId())); } diff --git a/src/main/java/com/loki/lochat/gradient/listeners/GradientPlayerListener.java b/src/main/java/com/loki/lochat/gradient/listeners/GradientPlayerListener.java index e97aa4b..e3a8df7 100644 --- a/src/main/java/com/loki/lochat/gradient/listeners/GradientPlayerListener.java +++ b/src/main/java/com/loki/lochat/gradient/listeners/GradientPlayerListener.java @@ -31,7 +31,7 @@ public class GradientPlayerListener implements Listener { @EventHandler public void onPlayerQuit(PlayerQuitEvent event) { Player player = event.getPlayer(); - FoliaUtil.runAsync(module.getPlugin(), + FoliaUtil.runAsync(module.getPlugin(), () -> module.getDataManager().savePlayerData(player.getUniqueId())); } } diff --git a/src/main/java/com/loki/lochat/gradient/util/DisplayNameUtil.java b/src/main/java/com/loki/lochat/gradient/util/DisplayNameUtil.java index 3d4d56a..4fab35c 100644 --- a/src/main/java/com/loki/lochat/gradient/util/DisplayNameUtil.java +++ b/src/main/java/com/loki/lochat/gradient/util/DisplayNameUtil.java @@ -21,13 +21,14 @@ public final class DisplayNameUtil { .hexColors() .build(); - private DisplayNameUtil() {} + private DisplayNameUtil() { + } public static void updateDisplayName(GradientModule module, Player player, GradientPlayerData data) { GradientConfig cfg = module.getConfig(); String prefix = null; String prefixFormat = cfg.getPrefixFormat(); - + // Определяем префикс: сначала кастомный, потом LuckPerms if (data.isPrefixEnabled() && data.hasPrefix()) { // Есть кастомный префикс @@ -37,9 +38,9 @@ public final class DisplayNameUtil { String lpPrefix = module.getLuckPermsHook().getActivePrefix(player); if (lpPrefix != null && !lpPrefix.isEmpty()) { String displayName = buildWithLuckPermsPrefix( - lpPrefix, - player.getName(), - data.isColorEnabled() ? data.getColors() : null, + lpPrefix, + player.getName(), + data.isColorEnabled() ? data.getColors() : null, cfg.isUseLegacyRgbFormat(), cfg.isContinuousGradient() ); @@ -51,7 +52,7 @@ public final class DisplayNameUtil { return; } } - + // Строим display name с кастомным префиксом или без префикса String displayName = GradientUtil.buildDisplayName( prefix, @@ -62,7 +63,7 @@ public final class DisplayNameUtil { prefixFormat, cfg.isUseLegacyRgbFormat() ); - + // Для display name нужен §x формат, конвертируем MiniMessage в legacy displayName = convertMiniMessageToLegacy(displayName); var component = SERIALIZER.deserialize(displayName); @@ -75,12 +76,12 @@ public final class DisplayNameUtil { */ private static String convertMiniMessageToLegacy(String text) { if (text == null) return ""; - + // Конвертируем <#RRGGBB> в §x§R§R§G§G§B§B Pattern pattern = Pattern.compile("<#([0-9a-fA-F]{6})>"); Matcher matcher = pattern.matcher(text); StringBuffer sb = new StringBuffer(); - + while (matcher.find()) { String hex = matcher.group(1).toLowerCase(); StringBuilder replacement = new StringBuilder("§x"); @@ -90,18 +91,18 @@ public final class DisplayNameUtil { matcher.appendReplacement(sb, replacement.toString()); } matcher.appendTail(sb); - + return sb.toString(); } - private static String buildWithLuckPermsPrefix(String lpPrefix, String nick, - List colors, - boolean useLegacyFormat, - boolean continuousGradient) { + private static String buildWithLuckPermsPrefix(String lpPrefix, String nick, + List colors, + boolean useLegacyFormat, + boolean continuousGradient) { if (colors == null || colors.isEmpty()) { return lpPrefix + nick; } - + if (continuousGradient) { String cleanPrefix = stripColors(lpPrefix); String fullText = cleanPrefix + nick; @@ -118,15 +119,15 @@ public final class DisplayNameUtil { public static String buildColoredPrefix(GradientModule module, GradientPlayerData data) { if (!data.hasPrefix() || !data.isPrefixEnabled()) return null; - + GradientConfig cfg = module.getConfig(); String prefix = cfg.getPrefixFormat().replace("{prefix}", data.getPrefix()).stripTrailing(); - + // Применяем градиент только если цвета включены И есть цвета if (data.hasColors() && data.isColorEnabled() && cfg.isGradientOnPrefix()) { return GradientUtil.applyGradient(prefix, data.getColors(), cfg.isUseLegacyRgbFormat()); } - + // Возвращаем префикс без цветов return prefix; } @@ -137,12 +138,12 @@ public final class DisplayNameUtil { public static String getFullDisplayName(GradientModule module, Player player) { GradientPlayerData data = module.getDataManager().getPlayerData(player.getUniqueId()); GradientConfig cfg = module.getConfig(); - + String prefix = null; if (data.isPrefixEnabled() && data.hasPrefix()) { prefix = data.getPrefix(); } - + return GradientUtil.buildDisplayName( prefix, player.getName(), diff --git a/src/main/java/com/loki/lochat/gradient/util/FoliaUtil.java b/src/main/java/com/loki/lochat/gradient/util/FoliaUtil.java index 2b2d5b4..d3ccaf4 100644 --- a/src/main/java/com/loki/lochat/gradient/util/FoliaUtil.java +++ b/src/main/java/com/loki/lochat/gradient/util/FoliaUtil.java @@ -17,7 +17,8 @@ public final class FoliaUtil { IS_FOLIA = checkFolia(); } - private FoliaUtil() {} + private FoliaUtil() { + } private static boolean checkFolia() { try { diff --git a/src/main/java/com/loki/lochat/gradient/util/GradientConstants.java b/src/main/java/com/loki/lochat/gradient/util/GradientConstants.java index 20a12e3..931bc58 100644 --- a/src/main/java/com/loki/lochat/gradient/util/GradientConstants.java +++ b/src/main/java/com/loki/lochat/gradient/util/GradientConstants.java @@ -5,15 +5,14 @@ package com.loki.lochat.gradient.util; */ public final class GradientConstants { - private GradientConstants() {} - public static final long MILLIS_PER_SECOND = 1000L; - // GUI слоты public static final int GUI_CONFIRM_SLOT = 11; public static final int GUI_CANCEL_SLOT = 15; public static final int GUI_PREVIEW_SLOT = 13; - // LuckPerms public static final int LUCKPERMS_PREFIX_PRIORITY = 100; + + private GradientConstants() { + } } diff --git a/src/main/java/com/loki/lochat/gradient/util/GradientUtil.java b/src/main/java/com/loki/lochat/gradient/util/GradientUtil.java index 821f2f5..d883b18 100644 --- a/src/main/java/com/loki/lochat/gradient/util/GradientUtil.java +++ b/src/main/java/com/loki/lochat/gradient/util/GradientUtil.java @@ -11,7 +11,8 @@ public final class GradientUtil { private static final Pattern HEX_PATTERN = Pattern.compile("^#[0-9A-Fa-f]{6}$"); - private GradientUtil() {} + private GradientUtil() { + } public static boolean isValidHex(String color) { return HEX_PATTERN.matcher(color).matches(); @@ -50,7 +51,7 @@ public final class GradientUtil { // Вычисляем позицию символа от 0.0 до 1.0 double ratio = length > 1 ? (double) i / (length - 1) : 0.0; Color interpolated = interpolateMultiColor(colors, ratio); - String hex = String.format("#%02x%02x%02x", + String hex = String.format("#%02x%02x%02x", interpolated.getRed(), interpolated.getGreen(), interpolated.getBlue()); result.append(formatHex(hex, useLegacyFormat)).append(chars[i]); } @@ -142,7 +143,7 @@ public final class GradientUtil { for (int i = 0; i < length; i++) { double ratio = length > 1 ? (double) i / (length - 1) : 0.0; Color interpolated = interpolateMultiColor(colors, ratio); - String hex = String.format("#%02x%02x%02x", + String hex = String.format("#%02x%02x%02x", interpolated.getRed(), interpolated.getGreen(), interpolated.getBlue()); result.append(formatHexForTab(hex)).append(chars[i]); } @@ -151,8 +152,8 @@ public final class GradientUtil { return result.toString(); } - public static String buildDisplayName(String prefix, String nick, List colors, - boolean gradientOnPrefix, boolean continuousGradient, + public static String buildDisplayName(String prefix, String nick, List colors, + boolean gradientOnPrefix, boolean continuousGradient, String prefixFormat, boolean useLegacyFormat) { if (colors == null || colors.isEmpty()) { if (prefix != null && !prefix.isEmpty()) { diff --git a/src/main/java/com/loki/lochat/integrations/LibertyBansHook.java b/src/main/java/com/loki/lochat/integrations/LibertyBansHook.java index 38163d4..1fd11bc 100644 --- a/src/main/java/com/loki/lochat/integrations/LibertyBansHook.java +++ b/src/main/java/com/loki/lochat/integrations/LibertyBansHook.java @@ -16,7 +16,7 @@ public class LibertyBansHook { public LibertyBansHook(LoChat plugin) { this.plugin = plugin; this.muteService = plugin.getServiceRegistry().get(MuteService.class); - + // Проверяем наличие LibertyBans if (plugin.getServer().getPluginManager().getPlugin("LibertyBans") != null) { plugin.getLogger().info("LibertyBans обнаружен. Используйте встроенную систему мутов LoChat (/lmute, /lunmute)"); diff --git a/src/main/java/com/loki/lochat/integrations/PlaceholderAPIHook.java b/src/main/java/com/loki/lochat/integrations/PlaceholderAPIHook.java index 0372979..71fa31e 100644 --- a/src/main/java/com/loki/lochat/integrations/PlaceholderAPIHook.java +++ b/src/main/java/com/loki/lochat/integrations/PlaceholderAPIHook.java @@ -1,7 +1,10 @@ package com.loki.lochat.integrations; import com.loki.lochat.LoChat; -import com.loki.lochat.api.service.*; +import com.loki.lochat.api.service.ChatService; +import com.loki.lochat.api.service.IgnoreService; +import com.loki.lochat.api.service.PMService; +import com.loki.lochat.api.service.SpyService; import com.loki.lochat.gradient.GradientModule; import me.clip.placeholderapi.expansion.PlaceholderExpansion; import org.bukkit.Bukkit; @@ -66,25 +69,25 @@ public class PlaceholderAPIHook extends PlaceholderExpansion { yield lastPlayer.getName() != null ? lastPlayer.getName() : ""; } case "spy_enabled" -> String.valueOf(spyService.isSpying(uuid)); - + // Gradient placeholders (совместимость с LoPreff) // Используем TAB формат §x§R§R§G§G§B§B для совместимости с TAB плагином case "gradient_full", "full" -> { Player onlinePlayer = player.getPlayer(); if (onlinePlayer == null) yield player.getName() != null ? player.getName() : ""; - + // Если gradient модуль выключен — берём только LuckPerms префикс + ник if (gradient == null || !gradient.isEnabled()) { yield player.getName() != null ? player.getName() : ""; } - + // Используем TAB формат для плейсхолдеров yield gradient.getFormattedNameForTab(onlinePlayer); } case "gradient_name", "name" -> { Player onlinePlayer = player.getPlayer(); if (onlinePlayer == null) yield player.getName() != null ? player.getName() : ""; - + if (gradient == null || !gradient.isEnabled()) { yield player.getName(); } @@ -93,14 +96,14 @@ public class PlaceholderAPIHook extends PlaceholderExpansion { case "gradient_prefix", "prefix" -> { Player onlinePlayer = player.getPlayer(); if (onlinePlayer == null) yield ""; - + if (gradient == null || !gradient.isEnabled()) yield ""; yield gradient.getPrefix(onlinePlayer); } case "lp_prefix" -> { Player onlinePlayer = player.getPlayer(); if (onlinePlayer == null) yield ""; - + if (gradient == null || !gradient.isEnabled()) yield ""; yield gradient.getLuckPermsPrefix(onlinePlayer); } diff --git a/src/main/java/com/loki/lochat/integrations/SkinsRestorerHook.java b/src/main/java/com/loki/lochat/integrations/SkinsRestorerHook.java index 7e67746..42ecb5a 100644 --- a/src/main/java/com/loki/lochat/integrations/SkinsRestorerHook.java +++ b/src/main/java/com/loki/lochat/integrations/SkinsRestorerHook.java @@ -35,9 +35,9 @@ public class SkinsRestorerHook { Class apiClass = Class.forName("net.skinsrestorer.api.SkinsRestorerAPI"); Method getApiMethod = apiClass.getMethod("getApi"); skinsAPI = getApiMethod.invoke(null); - + getSkinDataMethod = skinsAPI.getClass().getMethod("getSkinData", String.class); - + enabled = true; plugin.getLogger().info("SkinsRestorer подключен!"); } catch (Exception e) { @@ -52,6 +52,7 @@ public class SkinsRestorerHook { /** * Получает текстуру скина игрока + * * @param player игрок * @return URL текстуры или null */ @@ -72,6 +73,7 @@ public class SkinsRestorerHook { /** * Получает URL головы игрока для отображения + * * @param playerName имя игрока * @return URL головы */ diff --git a/src/main/java/com/loki/lochat/listener/ChatEventListener.java b/src/main/java/com/loki/lochat/listener/ChatEventListener.java index 1404db1..98b7bcf 100644 --- a/src/main/java/com/loki/lochat/listener/ChatEventListener.java +++ b/src/main/java/com/loki/lochat/listener/ChatEventListener.java @@ -5,8 +5,8 @@ import com.loki.lochat.core.filter.AdvancedMessageFilter; import com.loki.lochat.core.registry.ServiceRegistry; import com.loki.lochat.utils.MentionHandler; import com.loki.lochat.utils.TextFormatter; -import io.papermc.paper.event.player.AsyncChatEvent; import io.papermc.paper.chat.ChatRenderer; +import io.papermc.paper.event.player.AsyncChatEvent; import net.kyori.adventure.audience.Audience; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.event.ClickEvent; @@ -25,129 +25,129 @@ public class ChatEventListener implements Listener { private final MessageService messageService; private final AdvancedMessageFilter advancedFilter; private final MentionHandler mentionHandler; - + public ChatEventListener(JavaPlugin plugin, ServiceRegistry registry) { this.plugin = plugin; this.messageService = registry.get(MessageService.class); this.advancedFilter = new AdvancedMessageFilter(plugin.getConfig()); this.mentionHandler = new MentionHandler(plugin); } - + @EventHandler(priority = EventPriority.HIGHEST) public void onChat(AsyncChatEvent event) { Player sender = event.getPlayer(); String message = PlainTextComponentSerializer.plainText().serialize(event.message()); - + boolean allowed = messageService.processMessage(sender, message); - + if (!allowed) { event.setCancelled(true); return; } - + AdvancedMessageFilter.FilterResult filterResult = advancedFilter.filterMessage(sender, message); - - if (!filterResult.isAllowed()) { + + if (!filterResult.allowed()) { event.setCancelled(true); - sender.sendMessage(com.loki.lochat.utils.ChatFormatter.parse(filterResult.getBlockReason())); + sender.sendMessage(com.loki.lochat.utils.ChatFormatter.parse(filterResult.blockReason())); return; } - - String filteredMessage = filterResult.getFilteredMessage(); + + String filteredMessage = filterResult.filteredMessage(); event.message(Component.text(filteredMessage)); - + event.renderer(new EnhancedChatRenderer(sender, event.message())); } - + private class EnhancedChatRenderer implements ChatRenderer { private final Player sender; private final Component originalMessage; - + public EnhancedChatRenderer(Player sender, Component originalMessage) { this.sender = sender; this.originalMessage = originalMessage; } - + @Override public Component render(Player source, Component sourceDisplayName, Component message, Audience viewer) { String prefix = plugin.getConfig().getString("chat.global.prefix", "[G]"); Component playerComponent = createPlayerComponent(source, sourceDisplayName); Component processedMessage = message; - + processedMessage = TextFormatter.formatMarkdown(processedMessage); processedMessage = processUrls(processedMessage); processedMessage = processEmojis(processedMessage); - + if (viewer instanceof Player viewerPlayer) { processedMessage = mentionHandler.processMentions(processedMessage, source, viewerPlayer); } - + return Component.text(prefix + " ") .append(playerComponent) .append(Component.text(": ")) .append(processedMessage); } - + private Component createPlayerComponent(Player player, Component displayName) { if (!plugin.getConfig().getBoolean("chat.hover.enabled", true)) { return displayName.clickEvent(ClickEvent.suggestCommand("/msg " + player.getName() + " ")); } - + java.util.List hoverLines = plugin.getConfig().getStringList("chat.hover.format"); if (hoverLines.isEmpty()) { hoverLines = java.util.Arrays.asList( - "Игрок: {player}", - "Мир: {world}", - "", - "▶ Клик: написать ЛС" + "Игрок: {player}", + "Мир: {world}", + "", + "▶ Клик: написать ЛС" ); } - + net.kyori.adventure.text.TextComponent.Builder hoverBuilder = Component.text(); for (int i = 0; i < hoverLines.size(); i++) { String line = hoverLines.get(i); - + line = line.replace("{player}", player.getName()) - .replace("{world}", player.getWorld().getName()) - .replace("{ping}", String.valueOf(player.getPing())) - .replace("{gamemode}", player.getGameMode().name()) - .replace("{health}", String.valueOf(Math.round(player.getHealth()))) - .replace("{food}", String.valueOf(player.getFoodLevel())); - + .replace("{world}", player.getWorld().getName()) + .replace("{ping}", String.valueOf(player.getPing())) + .replace("{gamemode}", player.getGameMode().name()) + .replace("{health}", String.valueOf(Math.round(player.getHealth()))) + .replace("{food}", String.valueOf(player.getFoodLevel())); + Component lineComponent = com.loki.lochat.utils.ChatFormatter.parse(line); hoverBuilder.append(lineComponent); - + if (i < hoverLines.size() - 1) { hoverBuilder.append(Component.newline()); } } - + return displayName .hoverEvent(HoverEvent.showText(hoverBuilder.build())) .clickEvent(ClickEvent.suggestCommand("/msg " + player.getName() + " ")); } - + private Component processUrls(Component message) { String plainText = PlainTextComponentSerializer.plainText().serialize(message); String urlPattern = "(https?://[\\w\\-._~:/?#\\[\\]@!35538117-c5a8-4bfe-b9f2-b0dcf9374222'()*+,;=%]+)"; java.util.regex.Pattern pattern = java.util.regex.Pattern.compile(urlPattern); java.util.regex.Matcher matcher = pattern.matcher(plainText); - + Component result = message; while (matcher.find()) { String url = matcher.group(1); Component urlComponent = Component.text(url, NamedTextColor.AQUA, TextDecoration.UNDERLINED) .hoverEvent(HoverEvent.showText(Component.text("Открыть: " + url, NamedTextColor.GRAY))) .clickEvent(ClickEvent.openUrl(url)); - - result = result.replaceText(builder -> - builder.matchLiteral(url).replacement(urlComponent) + + result = result.replaceText(builder -> + builder.matchLiteral(url).replacement(urlComponent) ); } - + return result; } - + private Component processEmojis(Component message) { Component result = message; result = result.replaceText(builder -> builder.matchLiteral(":heart:").replacement("❤")); diff --git a/src/main/java/com/loki/lochat/listener/PlayerEventListener.java b/src/main/java/com/loki/lochat/listener/PlayerEventListener.java index 6b9c4fc..0f2e846 100644 --- a/src/main/java/com/loki/lochat/listener/PlayerEventListener.java +++ b/src/main/java/com/loki/lochat/listener/PlayerEventListener.java @@ -15,12 +15,12 @@ import org.bukkit.event.player.PlayerQuitEvent; public class PlayerEventListener implements Listener { private final PlayerDataService playerDataService; private final NickService nickService; - + public PlayerEventListener(ServiceRegistry registry) { this.playerDataService = registry.get(PlayerDataService.class); this.nickService = registry.get(NickService.class); } - + @EventHandler public void onJoin(PlayerJoinEvent event) { Player player = event.getPlayer(); @@ -29,7 +29,7 @@ public class PlayerEventListener implements Listener { nickService.updatePlayerDisplay(player); } } - + @EventHandler public void onQuit(PlayerQuitEvent event) { Player player = event.getPlayer(); diff --git a/src/main/java/com/loki/lochat/managers/AutoMessageManager.java b/src/main/java/com/loki/lochat/managers/AutoMessageManager.java index 2b5da7a..5d626fa 100644 --- a/src/main/java/com/loki/lochat/managers/AutoMessageManager.java +++ b/src/main/java/com/loki/lochat/managers/AutoMessageManager.java @@ -19,7 +19,7 @@ public class AutoMessageManager { private final Random random = new Random(); private final AtomicInteger currentIndex = new AtomicInteger(0); private boolean running = false; - + private Map> messages; private List messageOrder; private String prefix; @@ -35,21 +35,21 @@ public class AutoMessageManager { if (!file.exists()) { plugin.saveResource("automessages.yml", false); } - + FileConfiguration config = YamlConfiguration.loadConfiguration(file); - + // Настройки prefix = config.getString("settings.prefix", "&6[&eINFO&6]&r"); mode = config.getString("settings.mode", "sequential").toLowerCase(); - + // Загружаем сообщения messages = new LinkedHashMap<>(); ConfigurationSection msgSection = config.getConfigurationSection("messages"); - + if (msgSection != null) { for (String key : msgSection.getKeys(false)) { List lines = new ArrayList<>(); - + if (msgSection.isList(key)) { lines.addAll(msgSection.getStringList(key)); } else { @@ -58,16 +58,16 @@ public class AutoMessageManager { lines.add(single); } } - + if (!lines.isEmpty()) { messages.put(key, lines); } } } - + // Определяем порядок messageOrder = new ArrayList<>(); - + if (mode.equals("custom")) { String orderStr = config.getString("settings.order", ""); for (String item : orderStr.split(",")) { @@ -87,11 +87,11 @@ public class AutoMessageManager { } } } - + if (messageOrder.isEmpty()) { messageOrder.addAll(messages.keySet()); } - + plugin.getLogger().info("Загружено " + messages.size() + " автосообщений"); } @@ -125,14 +125,14 @@ public class AutoMessageManager { } String messageKey; - + if (mode.equals("random")) { messageKey = messageOrder.get(random.nextInt(messageOrder.size())); } else { int index = currentIndex.getAndUpdate(i -> (i + 1) % messageOrder.size()); messageKey = messageOrder.get(index); } - + List lines = messages.get(messageKey); if (lines == null || lines.isEmpty()) return; @@ -140,7 +140,7 @@ public class AutoMessageManager { for (String line : lines) { // Заменяем плейсхолдеры String processed = line.replace("%online%", String.valueOf(Bukkit.getOnlinePlayers().size())); - + // Добавляем префикс к первой непустой строке Component formatted; if (isFirstLine && !line.trim().isEmpty()) { @@ -149,7 +149,7 @@ public class AutoMessageManager { } else { formatted = ChatFormatter.parse(processed); } - + for (var player : Bukkit.getOnlinePlayers()) { player.sendMessage(formatted); } diff --git a/src/main/java/com/loki/lochat/managers/CustomCommandManager.java b/src/main/java/com/loki/lochat/managers/CustomCommandManager.java index 4a3b48d..26da019 100644 --- a/src/main/java/com/loki/lochat/managers/CustomCommandManager.java +++ b/src/main/java/com/loki/lochat/managers/CustomCommandManager.java @@ -24,14 +24,15 @@ public class CustomCommandManager { private final LoChat plugin; private final Map commands; - public CustomCommandManager(LoChat plugin) { + private CustomCommandManager(LoChat plugin) { this.plugin = plugin; this.commands = new HashMap<>(); - init(); } - - private void init() { - loadCommands(); + + public static CustomCommandManager create(LoChat plugin) { + CustomCommandManager manager = new CustomCommandManager(plugin); + manager.loadCommands(); + return manager; } private void loadCommands() { @@ -41,15 +42,15 @@ public class CustomCommandManager { } FileConfiguration commandsConfig = YamlConfiguration.loadConfiguration(commandsFile); - + // Очищаем старые команды commands.clear(); - + // Загружаем команды из конфига for (String commandName : commandsConfig.getKeys(false)) { ConfigurationSection section = commandsConfig.getConfigurationSection(commandName); if (section == null) continue; - + CustomCommandData data = new CustomCommandData( commandName, section.getString("permission"), @@ -58,13 +59,13 @@ public class CustomCommandManager { section.getString("type", "chat"), section.getString("target", "sender") ); - + commands.put(commandName, data); - + // Регистрируем команду registerCommand(data); } - + plugin.getLogger().info("Загружено " + commands.size() + " кастомных команд"); } @@ -74,17 +75,17 @@ public class CustomCommandManager { Field commandMapField = Bukkit.getServer().getClass().getDeclaredField("commandMap"); commandMapField.setAccessible(true); CommandMap commandMap = (CommandMap) commandMapField.get(Bukkit.getServer()); - + // Создаем и регистрируем команду CustomCommand command = new CustomCommand(data.name, this); commandMap.register("lochat", command); - + // Регистрируем алиасы for (String alias : data.aliases) { CustomCommand aliasCommand = new CustomCommand(alias, this); commandMap.register("lochat", aliasCommand); } - + } catch (Exception e) { plugin.getLogger().severe("Ошибка регистрации команды " + data.name + ": " + e.getMessage()); } @@ -105,18 +106,18 @@ public class CustomCommandManager { } } } - + if (data == null) return false; - + // Проверяем права if (data.permission != null && !player.hasPermission(data.permission)) { player.sendMessage(ChatFormatter.parse(plugin.getMessageConfig().getNoPermission())); return true; } - + // Обрабатываем плейсхолдеры String message = processPlaceholders(data.message, player, args); - + // Выполняем команду в зависимости от типа switch (data.type.toLowerCase()) { case "broadcast" -> sendBroadcast(data.target, message); @@ -124,26 +125,26 @@ public class CustomCommandManager { case "actionbar" -> sendActionBar(data.target, player, message); default -> sendChatMessage(data.target, player, message); } - + return true; } private String processPlaceholders(String message, Player player, String[] args) { String result = message; - + // Базовые плейсхолдеры result = result.replace("{player}", player.getName()); result = result.replace("{x}", String.valueOf(player.getLocation().getBlockX())); result = result.replace("{y}", String.valueOf(player.getLocation().getBlockY())); result = result.replace("{z}", String.valueOf(player.getLocation().getBlockZ())); result = result.replace("{world}", player.getWorld().getName()); - + // Аргументы команды for (int i = 0; i < args.length; i++) { result = result.replace("{arg" + i + "}", args[i]); } result = result.replace("{args}", String.join(" ", args)); - + // PlaceholderAPI если доступен if (Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI")) { try { @@ -156,13 +157,13 @@ public class CustomCommandManager { plugin.getLogger().warning("Ошибка при обработке PlaceholderAPI плейсхолдеров: " + e.getMessage()); } } - + return result; } private void sendChatMessage(String target, Player sender, String message) { Component component = ChatFormatter.parse(message); - + switch (target.toLowerCase()) { case "sender" -> sender.sendMessage(component); case "all" -> { @@ -208,10 +209,10 @@ public class CustomCommandManager { String[] parts = message.split("\\n", 2); Component title = ChatFormatter.parse(parts[0]); Component subtitle = parts.length > 1 ? ChatFormatter.parse(parts[1]) : Component.empty(); - - Title titleObj = Title.title(title, subtitle, + + Title titleObj = Title.title(title, subtitle, Title.Times.times(Duration.ofMillis(500), Duration.ofSeconds(3), Duration.ofMillis(500))); - + switch (target.toLowerCase()) { case "sender" -> sender.showTitle(titleObj); case "all" -> { @@ -236,7 +237,7 @@ public class CustomCommandManager { private void sendActionBar(String target, Player sender, String message) { Component component = ChatFormatter.parse(message); - + switch (target.toLowerCase()) { case "sender" -> sender.sendActionBar(component); case "all" -> { @@ -263,22 +264,7 @@ public class CustomCommandManager { return commands; } - public static class CustomCommandData { - public final String name; - public final String permission; - public final String message; - public final List aliases; - public final String type; - public final String target; - - public CustomCommandData(String name, String permission, String message, - List aliases, String type, String target) { - this.name = name; - this.permission = permission; - this.message = message; - this.aliases = aliases; - this.type = type; - this.target = target; - } + public record CustomCommandData(String name, String permission, String message, List aliases, String type, + String target) { } } \ No newline at end of file diff --git a/src/main/java/com/loki/lochat/managers/EmojiManager.java b/src/main/java/com/loki/lochat/managers/EmojiManager.java index f38e49e..f2b28a5 100644 --- a/src/main/java/com/loki/lochat/managers/EmojiManager.java +++ b/src/main/java/com/loki/lochat/managers/EmojiManager.java @@ -17,9 +17,14 @@ public class EmojiManager { private boolean enabled; private boolean requirePermission; - public EmojiManager(LoChat plugin) { + private EmojiManager(LoChat plugin) { this.plugin = plugin; - load(); + } + + public static EmojiManager create(LoChat plugin) { + EmojiManager manager = new EmojiManager(plugin); + manager.load(); + return manager; } public void load() { diff --git a/src/main/java/com/loki/lochat/util/ChatFormatter.java b/src/main/java/com/loki/lochat/util/ChatFormatter.java index dc3cf73..f35d12e 100644 --- a/src/main/java/com/loki/lochat/util/ChatFormatter.java +++ b/src/main/java/com/loki/lochat/util/ChatFormatter.java @@ -11,7 +11,7 @@ import org.bukkit.command.CommandSender; public class ChatFormatter { private static final MiniMessage MINI_MESSAGE = MiniMessage.miniMessage(); private static final LegacyComponentSerializer LEGACY = LegacyComponentSerializer.legacyAmpersand(); - + public static Object parse(String message) { try { return MINI_MESSAGE.deserialize(message); @@ -19,14 +19,14 @@ public class ChatFormatter { return LEGACY.deserialize(message); } } - + public static String toPlain(Object message) { if (message instanceof Component component) { return LegacyComponentSerializer.legacySection().serialize(component); } return message.toString(); } - + public static void sendMessage(CommandSender sender, Object message) { if (message instanceof Component component) { sender.sendMessage(component); @@ -34,17 +34,17 @@ public class ChatFormatter { sender.sendMessage(message.toString()); } } - + public static void broadcast(Object message) { if (message instanceof Component component) { org.bukkit.Bukkit.broadcast(component); } } - + public static String stripTags(String message) { return message.replaceAll("<[^>]+>", "").replaceAll("§[0-9a-fk-or]", ""); } - + public static String convertAllColors(String message) { return message.replace("&", "§"); } diff --git a/src/main/java/com/loki/lochat/util/DistanceUtil.java b/src/main/java/com/loki/lochat/util/DistanceUtil.java index cf9dbd8..5491d9e 100644 --- a/src/main/java/com/loki/lochat/util/DistanceUtil.java +++ b/src/main/java/com/loki/lochat/util/DistanceUtil.java @@ -6,12 +6,12 @@ import org.bukkit.entity.Player; * Утилита для проверки расстояния между игроками */ public class DistanceUtil { - + public static boolean isInRange(Player player1, Player player2, int radius) { if (!player1.getWorld().equals(player2.getWorld())) { return false; } - + return player1.getLocation().distance(player2.getLocation()) <= radius; } } diff --git a/src/main/java/com/loki/lochat/util/FoliaUtil.java b/src/main/java/com/loki/lochat/util/FoliaUtil.java index dbc62aa..e451744 100644 --- a/src/main/java/com/loki/lochat/util/FoliaUtil.java +++ b/src/main/java/com/loki/lochat/util/FoliaUtil.java @@ -9,7 +9,7 @@ import org.bukkit.plugin.java.JavaPlugin; */ public class FoliaUtil { private static boolean isFolia; - + static { try { Class.forName("io.papermc.paper.threadedregions.RegionizedServer"); @@ -18,11 +18,11 @@ public class FoliaUtil { isFolia = false; } } - + public static boolean isFolia() { return isFolia; } - + public static void runAsync(JavaPlugin plugin, Runnable task) { if (isFolia) { Bukkit.getAsyncScheduler().runNow(plugin, scheduledTask -> task.run()); @@ -30,7 +30,7 @@ public class FoliaUtil { Bukkit.getScheduler().runTaskAsynchronously(plugin, task); } } - + public static void runEntityTask(JavaPlugin plugin, Entity entity, Runnable task) { if (isFolia) { entity.getScheduler().run(plugin, scheduledTask -> task.run(), null); @@ -38,12 +38,13 @@ public class FoliaUtil { Bukkit.getScheduler().runTask(plugin, task); } } - + /** * Запускает глобальную повторяющуюся задачу - * @param plugin плагин - * @param task задача - * @param delayTicks задержка перед первым запуском (в тиках) + * + * @param plugin плагин + * @param task задача + * @param delayTicks задержка перед первым запуском (в тиках) * @param periodTicks период повторения (в тиках) */ public static void runTimerAsync(JavaPlugin plugin, Runnable task, long delayTicks, long periodTicks) { diff --git a/src/main/java/com/loki/lochat/util/TimeParser.java b/src/main/java/com/loki/lochat/util/TimeParser.java index 3c3152c..e6c5499 100644 --- a/src/main/java/com/loki/lochat/util/TimeParser.java +++ b/src/main/java/com/loki/lochat/util/TimeParser.java @@ -4,17 +4,18 @@ package com.loki.lochat.util; * Утилита для парсинга времени (DRY - вынесена общая логика) */ public class TimeParser { - + /** * Парсит строку времени в миллисекунды + * * @param timeStr строка вида "1d", "2h", "30m", "60s" * @return миллисекунды или -1 при ошибке */ public static long parse(String timeStr) { if (timeStr == null || timeStr.isEmpty()) return 0; - + timeStr = timeStr.toLowerCase(); - + try { if (timeStr.endsWith("d")) { return Long.parseLong(timeStr.replace("d", "")) * 24 * 60 * 60 * 1000L; @@ -31,18 +32,18 @@ public class TimeParser { return -1; } } - + /** * Форматирует миллисекунды в читаемую строку */ public static String format(long millis) { if (millis <= 0) return "0с"; - + long seconds = millis / 1000; long minutes = seconds / 60; long hours = minutes / 60; long days = hours / 24; - + if (days > 0) { return days + "д " + (hours % 24) + "ч"; } else if (hours > 0) { diff --git a/src/main/java/com/loki/lochat/utils/AdventureManager.java b/src/main/java/com/loki/lochat/utils/AdventureManager.java index 69a05ec..6c08581 100644 --- a/src/main/java/com/loki/lochat/utils/AdventureManager.java +++ b/src/main/java/com/loki/lochat/utils/AdventureManager.java @@ -8,28 +8,28 @@ import org.bukkit.plugin.Plugin; * Менеджер для работы с Adventure API на Arclight/Forge серверах */ public class AdventureManager { - + private static boolean adventureAvailable = false; private static Object audiences; - + public static void init(Plugin plugin) { try { // Проверяем наличие Adventure API Class.forName("net.kyori.adventure.text.Component"); Class audiencesClass = Class.forName("net.kyori.adventure.platform.bukkit.BukkitAudiences"); - + // Создаем BukkitAudiences через рефлексию Object audiencesInstance = audiencesClass.getMethod("create", Plugin.class).invoke(null, plugin); audiences = audiencesInstance; adventureAvailable = true; - + plugin.getLogger().info("Adventure API обнаружен - используем нативную поддержку"); } catch (Exception e) { adventureAvailable = false; plugin.getLogger().info("Adventure API не найден - используем legacy режим"); } } - + public static void shutdown() { if (audiences != null && adventureAvailable) { try { @@ -41,7 +41,7 @@ public class AdventureManager { } adventureAvailable = false; } - + public static void sendMessage(CommandSender sender, Object message) { if (adventureAvailable && audiences != null) { try { @@ -53,7 +53,7 @@ public class AdventureManager { // Fallback на legacy } } - + // Legacy fallback if (message instanceof String) { sender.sendMessage((String) message); @@ -61,7 +61,7 @@ public class AdventureManager { sender.sendMessage(message.toString()); } } - + public static void sendMessage(Player player, Object message) { if (adventureAvailable && audiences != null) { try { @@ -73,7 +73,7 @@ public class AdventureManager { // Fallback на legacy } } - + // Legacy fallback if (message instanceof String) { player.sendMessage((String) message); @@ -81,7 +81,7 @@ public class AdventureManager { player.sendMessage(message.toString()); } } - + public static boolean isAdventureAvailable() { return adventureAvailable; } diff --git a/src/main/java/com/loki/lochat/utils/ChatFormatter.java b/src/main/java/com/loki/lochat/utils/ChatFormatter.java index 9bb8981..c8e1349 100644 --- a/src/main/java/com/loki/lochat/utils/ChatFormatter.java +++ b/src/main/java/com/loki/lochat/utils/ChatFormatter.java @@ -11,7 +11,8 @@ public final class ChatFormatter { private static final PlainTextComponentSerializer PLAIN = PlainTextComponentSerializer.plainText(); - private ChatFormatter() {} + private ChatFormatter() { + } /* ===================== BASIC ===================== */ @@ -38,7 +39,7 @@ public final class ChatFormatter { */ private static String convertLegacyFormats(String message) { if (message == null) return ""; - + // Конвертируем &#RRGGBB в <#RRGGBB> java.util.regex.Pattern pattern1 = java.util.regex.Pattern.compile("&#([0-9a-fA-F]{6})"); java.util.regex.Matcher matcher1 = pattern1.matcher(message); @@ -49,7 +50,7 @@ public final class ChatFormatter { } matcher1.appendTail(sb1); message = sb1.toString(); - + // Конвертируем #RRGGBB в <#RRGGBB> (только если не внутри тегов) java.util.regex.Pattern pattern2 = java.util.regex.Pattern.compile("(?)"); java.util.regex.Matcher matcher2 = pattern2.matcher(message); @@ -60,7 +61,7 @@ public final class ChatFormatter { } matcher2.appendTail(sb2); message = sb2.toString(); - + // Конвертируем §[0-9a-fk-or] в соответствующие MiniMessage теги message = message.replaceAll("§0", ""); message = message.replaceAll("§1", ""); @@ -84,7 +85,7 @@ public final class ChatFormatter { message = message.replaceAll("§n", ""); message = message.replaceAll("§o", ""); message = message.replaceAll("§r", ""); - + // Конвертируем &[0-9a-fk-or] в соответствующие MiniMessage теги message = message.replaceAll("&0", ""); message = message.replaceAll("&1", ""); @@ -102,7 +103,7 @@ public final class ChatFormatter { message = message.replaceAll("&d", ""); message = message.replaceAll("&e", ""); message = message.replaceAll("&f", ""); - + // Конвертируем форматирование message = message.replaceAll("&k", ""); message = message.replaceAll("&l", ""); @@ -110,7 +111,7 @@ public final class ChatFormatter { message = message.replaceAll("&n", ""); message = message.replaceAll("&o", ""); message = message.replaceAll("&r", ""); - + return message; } @@ -122,7 +123,7 @@ public final class ChatFormatter { public static String toPlain(Component component) { return component == null ? "" : PLAIN.serialize(component); } - + public static String toPlain(Object obj) { if (obj == null) return ""; if (obj instanceof Component component) { @@ -130,7 +131,7 @@ public final class ChatFormatter { } return obj.toString(); } - + /** * Отправляет сообщение игроку */ @@ -190,7 +191,7 @@ public final class ChatFormatter { // Получаем отображаемые имена игроков String senderDisplay = getPlayerDisplayName(sender); String receiverDisplay = getPlayerDisplayName(receiver); - + return parse(format .replace("{sender}", sender.getName()) .replace("{receiver}", receiver.getName()) @@ -208,7 +209,7 @@ public final class ChatFormatter { // Получаем отображаемые имена игроков String senderDisplay = getPlayerDisplayName(sender); String receiverDisplay = getPlayerDisplayName(receiver); - + return parse(format .replace("{sender}", sender.getName()) .replace("{receiver}", receiver.getName()) @@ -223,12 +224,12 @@ public final class ChatFormatter { private static String getPlayerDisplayName(Player player) { // Получаем экземпляр плагина com.loki.lochat.LoChat plugin = com.loki.lochat.LoChat.getInstance(); - + // Если градиентный модуль включен, используем его if (plugin.getGradientModule() != null && plugin.getGradientModule().isEnabled()) { return plugin.getGradientModule().getFormattedName(player); } - + // Иначе просто имя игрока return player.getName(); } diff --git a/src/main/java/com/loki/lochat/utils/Constants.java b/src/main/java/com/loki/lochat/utils/Constants.java index dfe05e6..97c1373 100644 --- a/src/main/java/com/loki/lochat/utils/Constants.java +++ b/src/main/java/com/loki/lochat/utils/Constants.java @@ -5,27 +5,24 @@ package com.loki.lochat.utils; */ public final class Constants { - private Constants() {} - // Чат public static final int DEFAULT_LOCAL_RADIUS = 100; public static final int CLEAR_CHAT_LINES = 100; - // Время public static final long MILLIS_IN_SECOND = 1000L; public static final int SECONDS_IN_MINUTE = 60; public static final int MINUTES_IN_HOUR = 60; public static final int HOURS_IN_DAY = 24; - // Градиенты public static final int DEFAULT_PRICE_PER_COLOR = 50; public static final int DEFAULT_PREFIX_PRICE = 500; public static final int LUCKPERMS_PREFIX_PRIORITY = 100; - // Folia/Paper совместимость public static final int TICKS_PER_SECOND = 20; public static final int MILLIS_PER_TICK = 50; - // Анти-спам public static final int PERCENTAGE_MULTIPLIER = 100; + + private Constants() { + } } \ No newline at end of file diff --git a/src/main/java/com/loki/lochat/utils/DistanceUtil.java b/src/main/java/com/loki/lochat/utils/DistanceUtil.java index 4c7f9a1..2111444 100644 --- a/src/main/java/com/loki/lochat/utils/DistanceUtil.java +++ b/src/main/java/com/loki/lochat/utils/DistanceUtil.java @@ -5,22 +5,23 @@ import org.bukkit.entity.Player; public class DistanceUtil { - private DistanceUtil() {} + private DistanceUtil() { + } public static boolean isInRange(Player player1, Player player2, int radius) { // Проверка на один мир if (!player1.getWorld().equals(player2.getWorld())) { return false; } - + Location loc1 = player1.getLocation(); Location loc2 = player2.getLocation(); - + // Быстрая проверка по квадрату (без sqrt) double dx = loc1.getX() - loc2.getX(); double dz = loc1.getZ() - loc2.getZ(); double radiusSquared = (double) radius * radius; - + return (dx * dx + dz * dz) <= radiusSquared; } diff --git a/src/main/java/com/loki/lochat/utils/MentionHandler.java b/src/main/java/com/loki/lochat/utils/MentionHandler.java index 64caad3..c4e053e 100644 --- a/src/main/java/com/loki/lochat/utils/MentionHandler.java +++ b/src/main/java/com/loki/lochat/utils/MentionHandler.java @@ -16,22 +16,22 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; public class MentionHandler { - + private static final Pattern EVERYONE_PATTERN = Pattern.compile("@everyone\\b"); private static final Pattern HERE_PATTERN = Pattern.compile("@here\\b"); private static final Pattern ROLE_PATTERN = Pattern.compile("@role:([\\w.]+)"); private static final Pattern PLAYER_PATTERN = Pattern.compile("@(\\w+)"); - + private final JavaPlugin plugin; - + public MentionHandler(JavaPlugin plugin) { this.plugin = plugin; } - + public Component processMentions(Component message, Player sender, Player viewer) { String plainText = PlainTextComponentSerializer.plainText().serialize(message); List mentionedPlayers = new ArrayList<>(); - + if (sender.hasPermission("lochat.mention.everyone")) { Matcher everyoneMatcher = EVERYONE_PATTERN.matcher(plainText); if (everyoneMatcher.find()) { @@ -39,7 +39,7 @@ public class MentionHandler { message = highlightMention(message, "@everyone"); } } - + if (sender.hasPermission("lochat.mention.here")) { Matcher hereMatcher = HERE_PATTERN.matcher(plainText); if (hereMatcher.find()) { @@ -47,57 +47,57 @@ public class MentionHandler { message = highlightMention(message, "@here"); } } - + if (sender.hasPermission("lochat.mention.role")) { Matcher roleMatcher = ROLE_PATTERN.matcher(plainText); while (roleMatcher.find()) { String permission = roleMatcher.group(1); String fullMention = "@role:" + permission; - + for (Player player : Bukkit.getOnlinePlayers()) { if (player.hasPermission(permission)) { mentionedPlayers.add(player); } } - + message = highlightMention(message, fullMention); } } - + Matcher playerMatcher = PLAYER_PATTERN.matcher(plainText); while (playerMatcher.find()) { String playerName = playerMatcher.group(1); Player mentioned = Bukkit.getPlayerExact(playerName); - + if (mentioned != null && mentioned.isOnline()) { mentionedPlayers.add(mentioned); message = highlightMention(message, "@" + playerName); } } - + if (mentionedPlayers.contains(viewer)) { playMentionSound(viewer); message = highlightForViewer(message, viewer); } - + return message; } - + private Component highlightMention(Component message, String mention) { - return message.replaceText(builder -> - builder.matchLiteral(mention) - .replacement(Component.text(mention, NamedTextColor.YELLOW, TextDecoration.BOLD)) + return message.replaceText(builder -> + builder.matchLiteral(mention) + .replacement(Component.text(mention, NamedTextColor.YELLOW, TextDecoration.BOLD)) ); } - + private Component highlightForViewer(Component message, Player viewer) { String viewerMention = "@" + viewer.getName(); - return message.replaceText(builder -> - builder.matchLiteral(viewerMention) - .replacement(Component.text(viewerMention, NamedTextColor.GOLD, TextDecoration.BOLD)) + return message.replaceText(builder -> + builder.matchLiteral(viewerMention) + .replacement(Component.text(viewerMention, NamedTextColor.GOLD, TextDecoration.BOLD)) ); } - + private void playMentionSound(Player player) { FoliaUtil.runEntityTask(plugin, player, () -> { player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1.0f, 1.5f); diff --git a/src/main/java/com/loki/lochat/utils/PlayerUtil.java b/src/main/java/com/loki/lochat/utils/PlayerUtil.java index 655d1f0..bdb2b3f 100644 --- a/src/main/java/com/loki/lochat/utils/PlayerUtil.java +++ b/src/main/java/com/loki/lochat/utils/PlayerUtil.java @@ -2,6 +2,7 @@ package com.loki.lochat.utils; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; +import org.bukkit.Sound; import org.bukkit.entity.Player; import java.util.UUID; @@ -11,10 +12,32 @@ import java.util.UUID; */ public final class PlayerUtil { - private PlayerUtil() {} + private PlayerUtil() { + } + + /** + * Safely parses a sound name from config. + * Uses deprecated Sound.valueOf() for backward compatibility with string-based config values. + * + * @param soundName the sound name to parse + * @param defaultSound the default sound to return if parsing fails + * @return the parsed Sound or the default if invalid + */ + @SuppressWarnings("deprecation") + public static Sound parseSound(String soundName, Sound defaultSound) { + if (soundName == null || soundName.isEmpty()) { + return defaultSound; + } + try { + return Sound.valueOf(soundName.toUpperCase()); + } catch (IllegalArgumentException e) { + return defaultSound; + } + } /** * Находит игрока по имени (онлайн или оффлайн) + * * @param name имя игрока * @return UUID игрока или null если не найден */ @@ -36,6 +59,7 @@ public final class PlayerUtil { /** * Проверяет, существует ли игрок (играл на сервере) + * * @param name имя игрока * @return true если игрок существует */ @@ -45,6 +69,7 @@ public final class PlayerUtil { /** * Получает имя игрока по UUID + * * @param uuid UUID игрока * @return имя игрока или null */ @@ -60,6 +85,7 @@ public final class PlayerUtil { /** * Проверяет, онлайн ли игрок + * * @param uuid UUID игрока * @return true если игрок онлайн */ diff --git a/src/main/java/com/loki/lochat/utils/TextFormatter.java b/src/main/java/com/loki/lochat/utils/TextFormatter.java index 1d44c0b..ca02b13 100644 --- a/src/main/java/com/loki/lochat/utils/TextFormatter.java +++ b/src/main/java/com/loki/lochat/utils/TextFormatter.java @@ -7,42 +7,42 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; public class TextFormatter { - + private static final Pattern BOLD_PATTERN = Pattern.compile("\\*\\*(.+?)\\*\\*"); private static final Pattern ITALIC_PATTERN = Pattern.compile("\\*(.+?)\\*"); private static final Pattern UNDERLINE_PATTERN = Pattern.compile("__(.+?)__"); private static final Pattern STRIKETHROUGH_PATTERN = Pattern.compile("~~(.+?)~~"); private static final Pattern CODE_PATTERN = Pattern.compile("`(.+?)`"); - + public static Component formatMarkdown(Component message) { String text = PlainTextComponentSerializer.plainText().serialize(message); - + text = formatBold(text); text = formatItalic(text); text = formatUnderline(text); text = formatStrikethrough(text); text = formatCode(text); - + return ChatFormatter.parse(text); } - + private static String formatBold(String text) { Matcher matcher = BOLD_PATTERN.matcher(text); StringBuffer result = new StringBuffer(); - + while (matcher.find()) { String content = matcher.group(1); matcher.appendReplacement(result, "" + content + ""); } matcher.appendTail(result); - + return result.toString(); } - + private static String formatItalic(String text) { Matcher matcher = ITALIC_PATTERN.matcher(text); StringBuffer result = new StringBuffer(); - + while (matcher.find()) { String content = matcher.group(1); if (!content.startsWith("*") && !content.endsWith("*")) { @@ -50,46 +50,46 @@ public class TextFormatter { } } matcher.appendTail(result); - + return result.toString(); } - + private static String formatUnderline(String text) { Matcher matcher = UNDERLINE_PATTERN.matcher(text); StringBuffer result = new StringBuffer(); - + while (matcher.find()) { String content = matcher.group(1); matcher.appendReplacement(result, "" + content + ""); } matcher.appendTail(result); - + return result.toString(); } - + private static String formatStrikethrough(String text) { Matcher matcher = STRIKETHROUGH_PATTERN.matcher(text); StringBuffer result = new StringBuffer(); - + while (matcher.find()) { String content = matcher.group(1); matcher.appendReplacement(result, "" + content + ""); } matcher.appendTail(result); - + return result.toString(); } - + private static String formatCode(String text) { Matcher matcher = CODE_PATTERN.matcher(text); StringBuffer result = new StringBuffer(); - + while (matcher.find()) { String content = matcher.group(1); matcher.appendReplacement(result, "󙀸`" + content + "`"); } matcher.appendTail(result); - + return result.toString(); } } diff --git a/src/main/resources/custom-commands.yml b/src/main/resources/custom-commands.yml index 2f88475..d44c95b 100644 --- a/src/main/resources/custom-commands.yml +++ b/src/main/resources/custom-commands.yml @@ -28,7 +28,7 @@ help: /website - официальный сайт /coords - ваши координаты /time - время на сервере - aliases: ["помощь", "хелп"] + aliases: [ "помощь", "хелп" ] type: "chat" target: "sender" @@ -42,7 +42,7 @@ rules: 5. Не используйте мат и оскорбления Нарушение правил карается мутом или баном! - aliases: ["правила", "rule"] + aliases: [ "правила", "rule" ] type: "chat" target: "sender" @@ -57,7 +57,7 @@ discord: • Общаться с игроками • Получать новости сервера • Участвовать в событиях - aliases: ["дискорд", "ds"] + aliases: [ "дискорд", "ds" ] type: "chat" target: "sender" @@ -70,7 +70,7 @@ website: • Карта сервера • Статистика игроков • Форум и новости - aliases: ["сайт", "site"] + aliases: [ "сайт", "site" ] type: "chat" target: "sender" @@ -85,7 +85,7 @@ coords: Y: {y} Z: {z} Мир: {world} - aliases: ["координаты", "pos", "position"] + aliases: [ "координаты", "pos", "position" ] type: "actionbar" target: "sender" @@ -94,7 +94,7 @@ time: Время на сервере: %server_time_24% Дата: %server_date% Онлайн: %server_online% игроков - aliases: ["время", "дата"] + aliases: [ "время", "дата" ] type: "chat" target: "sender" @@ -108,7 +108,7 @@ restart-warning: ⚠ ВНИМАНИЕ! ⚠ Сервер будет перезагружен через 5 минут! Сохраните свой прогресс и подготовьтесь к перезагрузке. - aliases: ["рестарт", "reboot"] + aliases: [ "рестарт", "reboot" ] type: "title" target: "all" @@ -117,7 +117,7 @@ maintenance: message: | Сервер переходит в режим технических работ Ожидаемое время: 30 минут - aliases: ["тех-работы", "maintenance"] + aliases: [ "тех-работы", "maintenance" ] type: "broadcast" target: "all" @@ -146,7 +146,7 @@ welcome: message: | Добро пожаловать на сервер! Игрок {player} присоединился к игре - aliases: ["привет", "hello"] + aliases: [ "привет", "hello" ] type: "title" target: "sender" diff --git a/src/main/resources/gradient-config.yml b/src/main/resources/gradient-config.yml index 16e413f..99487be 100644 --- a/src/main/resources/gradient-config.yml +++ b/src/main/resources/gradient-config.yml @@ -76,16 +76,16 @@ playerpoints: # Предустановленные градиенты presets: - fire: ["#FF4500", "#FF6347", "#FFD700"] - ocean: ["#00CED1", "#1E90FF", "#4169E1"] - forest: ["#228B22", "#32CD32", "#90EE90"] - sunset: ["#FF69B4", "#FF1493", "#DC143C"] - rainbow: ["#FF0000", "#FF7F00", "#FFFF00", "#00FF00", "#0000FF", "#4B0082", "#9400D3"] - ice: ["#B0E0E6", "#87CEEB", "#4682B4"] - gold: ["#FFD700", "#FFA500", "#FF8C00"] - purple: ["#9370DB", "#8A2BE2", "#4B0082"] - pink: ["#FFB6C1", "#FF69B4", "#FF1493"] - green: ["#00FF7F", "#00FA9A", "#98FB98"] + fire: [ "#FF4500", "#FF6347", "#FFD700" ] + ocean: [ "#00CED1", "#1E90FF", "#4169E1" ] + forest: [ "#228B22", "#32CD32", "#90EE90" ] + sunset: [ "#FF69B4", "#FF1493", "#DC143C" ] + rainbow: [ "#FF0000", "#FF7F00", "#FFFF00", "#00FF00", "#0000FF", "#4B0082", "#9400D3" ] + ice: [ "#B0E0E6", "#87CEEB", "#4682B4" ] + gold: [ "#FFD700", "#FFA500", "#FF8C00" ] + purple: [ "#9370DB", "#8A2BE2", "#4B0082" ] + pink: [ "#FFB6C1", "#FF69B4", "#FF1493" ] + green: [ "#00FF7F", "#00FA9A", "#98FB98" ] # ┌─────────────────────────────────────────────────────────────────────────────┐ # │ GUI НАСТРОЙКИ │ diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 584ae9c..d76321b 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -18,127 +18,127 @@ commands: description: Send global message usage: /g permission: chat.global.use - aliases: [п] + aliases: [ п ] globalchat: description: Toggle global chat usage: /globalchat toggle permission: chat.global.toggle - aliases: [пдщифдсрфе] + aliases: [ пдщифдсрфе ] l: description: Send local message usage: /l permission: chat.local.use - aliases: [д] + aliases: [ д ] msg: description: Send private message usage: /msg permission: chat.pm.use - aliases: [tell, w, pm, m, ьып, ееддж, цж, зьж, ьж] + aliases: [ tell, w, pm, m, ьып, ееддж, цж, зьж, ьж ] reply: description: Reply to last message usage: /reply permission: chat.pm.use - aliases: [r, ответить, кузду, к] + aliases: [ r, ответить, кузду, к ] ignore: description: Ignore player usage: /ignore permission: chat.pm.ignore - aliases: [игнор, шптщку] + aliases: [ игнор, шптщку ] unignore: description: Unignore player usage: /unignore permission: chat.pm.ignore - aliases: [разигнор, гтшптщку] + aliases: [ разигнор, гтшптщку ] announce: description: Send announcement usage: /announce permission: chat.announce.use - aliases: [объявление, анонс, фттщгтсу] + aliases: [ объявление, анонс, фттщгтсу ] nick: description: Set custom nickname usage: /nick [nickname|reset] permission: lochat.nick - aliases: [ник, тшсл] + aliases: [ ник, тшсл ] chatspy: description: Toggle chat spy mode usage: /chatspy permission: chat.spy - aliases: [spy, шпион, срфезуж, зуж] + aliases: [ spy, шпион, срфезуж, зуж ] clearchat: description: Clear chat for all players usage: /clearchat permission: chat.clear - aliases: [cc, очиститьчат, сдуфксрфе, сс] + aliases: [ cc, очиститьчат, сдуфксрфе, сс ] clearchatconfig: description: Configure clear chat message usage: /clearchatconfig [text] permission: lochat.clearchat.config - aliases: [ccc, настройкаочистки] + aliases: [ ccc, настройкаочистки ] lochat: description: LoChat admin command usage: /lochat [reload] permission: lochat.admin - aliases: [дщсрфе] + aliases: [ дщсрфе ] color: description: Set gradient nick color usage: /color [hex2] ... permission: gradient.color - aliases: [gradient, цвет, градиент, сщдщк, пкфвшуте] + aliases: [ gradient, цвет, градиент, сщдщк, пкфвшуте ] prefix: description: Set custom prefix usage: /prefix permission: gradient.prefix - aliases: [префикс, зкуашч] + aliases: [ префикс, зкуашч ] aprefix: description: Admin gradient commands usage: /aprefix permission: gradient.admin - aliases: [gradientadmin, азкуашч, пкфвшуетефвьшт] + aliases: [ gradientadmin, азкуашч, пкфвшуетефвьшт ] lmute: description: Mute a player usage: /lmute [time] [-s] [reason] permission: lochat.mute - aliases: [mute, мут, ьгеу] + aliases: [ mute, мут, ьгеу ] lunmute: description: Unmute a player usage: /lunmute [-s] permission: lochat.unmute - aliases: [unmute, размут, гтьгеу] + aliases: [ unmute, размут, гтьгеу ] lmutelist: description: List all active mutes usage: /lmutelist permission: lochat.mutelist - aliases: [mutelist, мутлист, ьгеудшые] + aliases: [ mutelist, мутлист, ьгеудшые ] lmutehistory: description: View mute history of a player usage: /lmutehistory permission: lochat.mutehistory - aliases: [mutehistory, мутистория, ьгеершыещку] + aliases: [ mutehistory, мутистория, ьгеершыещку ] lmuteblame: description: View mutes issued by a moderator usage: /lmuteblame permission: lochat.muteblame - aliases: [muteblame, мутблейм, ьгеуидфьу] + aliases: [ muteblame, мутблейм, ьгеуидфьу ] permissions: chat.global.use: