diff --git a/lohub/src/main/java/com/loki/lohub/LoHub.java b/lohub/src/main/java/com/loki/lohub/LoHub.java index e619d84..79318ee 100644 --- a/lohub/src/main/java/com/loki/lohub/LoHub.java +++ b/lohub/src/main/java/com/loki/lohub/LoHub.java @@ -5,7 +5,9 @@ import com.loki.lohub.listeners.HubProtectionListener; import com.loki.lohub.listeners.PlayerJoinListener; import com.loki.lohub.managers.ActionManager; import com.loki.lohub.managers.AnnouncementManager; +import com.loki.lohub.managers.ChatLockManager; import com.loki.lohub.managers.CooldownManager; +import com.loki.lohub.managers.CustomCommandManager; import com.loki.lohub.managers.HotbarManager; import com.loki.lohub.managers.PlayerHiderManager; import com.loki.lohub.managers.RegionManager; @@ -27,6 +29,8 @@ public class LoHub extends JavaPlugin { private ScoreboardManager scoreboardManager; private TablistManager tablistManager; private AnnouncementManager announcementManager; + private ChatLockManager chatLockManager; + private CustomCommandManager customCommandManager; @Override public void onEnable() { @@ -46,6 +50,8 @@ public class LoHub extends JavaPlugin { this.scoreboardManager = new ScoreboardManager(this); this.tablistManager = new TablistManager(this); this.announcementManager = new AnnouncementManager(this); + this.chatLockManager = new ChatLockManager(this); + this.customCommandManager = new CustomCommandManager(this); registerListeners(); registerCommands(); @@ -73,12 +79,15 @@ public class LoHub extends JavaPlugin { getServer().getPluginManager().registerEvents(new com.loki.lohub.listeners.HotbarListener(this), this); getServer().getPluginManager().registerEvents(new com.loki.lohub.listeners.LaunchpadListener(this), this); getServer().getPluginManager().registerEvents(new com.loki.lohub.listeners.DoubleJumpListener(this), this); + getServer().getPluginManager().registerEvents(new com.loki.lohub.listeners.ChatLockListener(this), this); + getServer().getPluginManager().registerEvents(new com.loki.lohub.listeners.CustomCommandListener(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)); + getCommand("chatlock").setExecutor(new com.loki.lohub.commands.ChatLockCommand(this)); } public ConfigManager getConfigManager() { @@ -120,4 +129,12 @@ public class LoHub extends JavaPlugin { public AnnouncementManager getAnnouncementManager() { return announcementManager; } + + public ChatLockManager getChatLockManager() { + return chatLockManager; + } + + public CustomCommandManager getCustomCommandManager() { + return customCommandManager; + } } diff --git a/lohub/src/main/java/com/loki/lohub/commands/ChatLockCommand.java b/lohub/src/main/java/com/loki/lohub/commands/ChatLockCommand.java new file mode 100644 index 0000000..8db3389 --- /dev/null +++ b/lohub/src/main/java/com/loki/lohub/commands/ChatLockCommand.java @@ -0,0 +1,36 @@ +package com.loki.lohub.commands; + +import com.loki.lohub.LoHub; +import com.loki.lohub.utils.TextUtil; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; + +public class ChatLockCommand implements CommandExecutor { + + private final LoHub plugin; + + public ChatLockCommand(LoHub plugin) { + this.plugin = plugin; + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, + @NotNull String label, @NotNull String[] args) { + if (!sender.hasPermission("lohub.chatlock")) { + sender.sendMessage(TextUtil.colorize(plugin.getConfigManager().getMessage("general.no-permission"))); + return true; + } + + plugin.getChatLockManager().toggle(); + boolean locked = plugin.getChatLockManager().isChatLocked(); + + String message = locked + ? plugin.getConfigManager().getMessage("chat.lock-enabled") + : plugin.getConfigManager().getMessage("chat.lock-disabled"); + + sender.sendMessage(TextUtil.colorize(message)); + return true; + } +} 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 2a0c85e..ccb8ffb 100644 --- a/lohub/src/main/java/com/loki/lohub/commands/HubCommand.java +++ b/lohub/src/main/java/com/loki/lohub/commands/HubCommand.java @@ -18,17 +18,17 @@ public class HubCommand implements CommandExecutor { @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!")); + sender.sendMessage(TextUtil.colorize(plugin.getConfigManager().getMessage("general.players-only"))); return true; } if (plugin.getSpawnManager().getSpawn() == null) { - player.sendMessage(TextUtil.colorize(plugin.getConfig().getString("messages.no-spawn"))); + player.sendMessage(TextUtil.colorize(plugin.getConfigManager().getMessage("spawn.no-spawn"))); return true; } plugin.getSpawnManager().teleportToSpawn(player); - player.sendMessage(TextUtil.colorize(plugin.getConfig().getString("messages.spawn-teleport"))); + player.sendMessage(TextUtil.colorize(plugin.getConfigManager().getMessage("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 2a8906c..fa070fc 100644 --- a/lohub/src/main/java/com/loki/lohub/commands/LoHubCommand.java +++ b/lohub/src/main/java/com/loki/lohub/commands/LoHubCommand.java @@ -17,13 +17,13 @@ public class LoHubCommand implements CommandExecutor { @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"))); + sender.sendMessage(TextUtil.colorize(plugin.getConfigManager().getMessage("general.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")); + sender.sendMessage(TextUtil.colorize(plugin.getConfigManager().getMessage("commands.usage-lohub"))); return true; } @@ -35,7 +35,7 @@ public class LoHubCommand implements CommandExecutor { plugin.getTablistManager().stop(); plugin.getScoreboardManager().start(); plugin.getTablistManager().start(); - sender.sendMessage(TextUtil.colorize("&aConfiguration reloaded!")); + sender.sendMessage(TextUtil.colorize(plugin.getConfigManager().getMessage("general.config-reloaded"))); 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 603dd25..3a08660 100644 --- a/lohub/src/main/java/com/loki/lohub/commands/SetHubCommand.java +++ b/lohub/src/main/java/com/loki/lohub/commands/SetHubCommand.java @@ -18,25 +18,21 @@ public class SetHubCommand implements CommandExecutor { @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!")); + sender.sendMessage(TextUtil.colorize(plugin.getConfigManager().getMessage("general.players-only"))); return true; } if (!player.hasPermission("lohub.admin")) { - player.sendMessage(TextUtil.colorize(plugin.getConfig().getString("messages.no-permission"))); + player.sendMessage(TextUtil.colorize(plugin.getConfigManager().getMessage("general.no-permission"))); return true; } plugin.getSpawnManager().setSpawn(player.getLocation()); - player.sendMessage(TextUtil.colorize(plugin.getConfig().getString("messages.spawn-set"))); + player.sendMessage(TextUtil.colorize(plugin.getConfigManager().getMessage("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/common/ConfigHelper.java b/lohub/src/main/java/com/loki/lohub/common/ConfigHelper.java new file mode 100644 index 0000000..20085f8 --- /dev/null +++ b/lohub/src/main/java/com/loki/lohub/common/ConfigHelper.java @@ -0,0 +1,21 @@ +package com.loki.lohub.common; + +import org.bukkit.configuration.file.FileConfiguration; + +public final class ConfigHelper { + + private ConfigHelper() { + } + + public static boolean isEnabled(FileConfiguration config, String path) { + return config.getBoolean(path + ".enabled", true); + } + + public static double getPower(FileConfiguration config, String path, String key, double defaultValue) { + return config.getDouble(path + "." + key, defaultValue); + } + + public static int getCooldown(FileConfiguration config, String path, int defaultValue) { + return config.getInt(path + ".cooldown", defaultValue); + } +} diff --git a/lohub/src/main/java/com/loki/lohub/common/GameModeHelper.java b/lohub/src/main/java/com/loki/lohub/common/GameModeHelper.java new file mode 100644 index 0000000..d3ac389 --- /dev/null +++ b/lohub/src/main/java/com/loki/lohub/common/GameModeHelper.java @@ -0,0 +1,15 @@ +package com.loki.lohub.common; + +import org.bukkit.GameMode; +import org.bukkit.entity.Player; + +public final class GameModeHelper { + + private GameModeHelper() { + } + + public static boolean isCreativeOrSpectator(Player player) { + GameMode mode = player.getGameMode(); + return mode == GameMode.CREATIVE || mode == GameMode.SPECTATOR; + } +} diff --git a/lohub/src/main/java/com/loki/lohub/common/LaunchHelper.java b/lohub/src/main/java/com/loki/lohub/common/LaunchHelper.java new file mode 100644 index 0000000..714641d --- /dev/null +++ b/lohub/src/main/java/com/loki/lohub/common/LaunchHelper.java @@ -0,0 +1,16 @@ +package com.loki.lohub.common; + +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +public final class LaunchHelper { + + private LaunchHelper() { + } + + public static void launch(Player player, double power, double powerY) { + Vector velocity = player.getLocation().getDirection().multiply(power); + velocity.setY(powerY); + player.setVelocity(velocity); + } +} diff --git a/lohub/src/main/java/com/loki/lohub/common/TextFormatter.java b/lohub/src/main/java/com/loki/lohub/common/TextFormatter.java new file mode 100644 index 0000000..23efa9b --- /dev/null +++ b/lohub/src/main/java/com/loki/lohub/common/TextFormatter.java @@ -0,0 +1,24 @@ +package com.loki.lohub.common; + +import com.loki.lohub.utils.PlaceholderUtil; +import com.loki.lohub.utils.TextUtil; +import org.bukkit.entity.Player; + +import java.util.List; +import java.util.stream.Collectors; + +public final class TextFormatter { + + private TextFormatter() { + } + + public static String format(String text, Player player) { + return TextUtil.colorize(PlaceholderUtil.parse(text, player)); + } + + public static String joinLines(List lines, Player player, String separator) { + return lines.stream() + .map(line -> format(line, player)) + .collect(Collectors.joining(separator)); + } +} 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 b9a166b..fabd37f 100644 --- a/lohub/src/main/java/com/loki/lohub/config/ConfigManager.java +++ b/lohub/src/main/java/com/loki/lohub/config/ConfigManager.java @@ -2,26 +2,155 @@ package com.loki.lohub.config; import com.loki.lohub.LoHub; import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; public class ConfigManager { private final LoHub plugin; private FileConfiguration config; + private FileConfiguration messages; + private FileConfiguration commands; + private FileConfiguration serverSelector; + private FileConfiguration data; + private File messagesFile; + private File commandsFile; + private File serverSelectorFile; + private File dataFile; public ConfigManager(LoHub plugin) { this.plugin = plugin; this.config = plugin.getConfig(); + loadMessages(); + loadCommands(); + loadServerSelector(); + loadData(); + } + + private void loadMessages() { + messagesFile = new File(plugin.getDataFolder(), "messages.yml"); + + if (!messagesFile.exists()) { + try { + messagesFile.getParentFile().mkdirs(); + InputStream in = plugin.getResource("messages.yml"); + if (in != null) { + Files.copy(in, messagesFile.toPath()); + } + } catch (IOException e) { + plugin.getLogger().severe("Could not create messages.yml!"); + e.printStackTrace(); + } + } + + messages = YamlConfiguration.loadConfiguration(messagesFile); + } + + private void loadCommands() { + commandsFile = new File(plugin.getDataFolder(), "commands.yml"); + + if (!commandsFile.exists()) { + try { + commandsFile.getParentFile().mkdirs(); + InputStream in = plugin.getResource("commands.yml"); + if (in != null) { + Files.copy(in, commandsFile.toPath()); + } + } catch (IOException e) { + plugin.getLogger().severe("Could not create commands.yml!"); + e.printStackTrace(); + } + } + + commands = YamlConfiguration.loadConfiguration(commandsFile); + } + + private void loadServerSelector() { + serverSelectorFile = new File(plugin.getDataFolder(), "serverselector.yml"); + + if (!serverSelectorFile.exists()) { + try { + serverSelectorFile.getParentFile().mkdirs(); + InputStream in = plugin.getResource("serverselector.yml"); + if (in != null) { + Files.copy(in, serverSelectorFile.toPath()); + } + } catch (IOException e) { + plugin.getLogger().severe("Could not create serverselector.yml!"); + e.printStackTrace(); + } + } + + serverSelector = YamlConfiguration.loadConfiguration(serverSelectorFile); + } + + private void loadData() { + dataFile = new File(plugin.getDataFolder(), "data.yml"); + + if (!dataFile.exists()) { + try { + dataFile.getParentFile().mkdirs(); + InputStream in = plugin.getResource("data.yml"); + if (in != null) { + Files.copy(in, dataFile.toPath()); + } + } catch (IOException e) { + plugin.getLogger().severe("Could not create data.yml!"); + e.printStackTrace(); + } + } + + data = YamlConfiguration.loadConfiguration(dataFile); } public void reload() { plugin.reloadConfig(); this.config = plugin.getConfig(); + loadMessages(); + loadCommands(); + loadServerSelector(); + loadData(); } public FileConfiguration getConfig() { return config; } + public FileConfiguration getMessages() { + return messages; + } + + public FileConfiguration getCommands() { + return commands; + } + + public FileConfiguration getServerSelector() { + return serverSelector; + } + + public FileConfiguration getData() { + return data; + } + + public void saveData() { + try { + data.save(dataFile); + } catch (IOException e) { + plugin.getLogger().severe("Could not save data.yml!"); + e.printStackTrace(); + } + } + + public String getMessage(String path) { + String message = messages.getString(path, "&#FF6B6BMessage not found: " + path); + String prefix = messages.getString("prefix", "�D4FF[LoHub] "); + return message.replace("{prefix}", prefix); + } + public boolean isProtectionEnabled() { return config.getBoolean("protection.enabled", true); } diff --git a/lohub/src/main/java/com/loki/lohub/features/FireworkHandler.java b/lohub/src/main/java/com/loki/lohub/features/FireworkHandler.java new file mode 100644 index 0000000..d5e3fff --- /dev/null +++ b/lohub/src/main/java/com/loki/lohub/features/FireworkHandler.java @@ -0,0 +1,104 @@ +package com.loki.lohub.features; + +import org.bukkit.Color; +import org.bukkit.FireworkEffect; +import org.bukkit.Location; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Firework; +import org.bukkit.entity.Player; +import org.bukkit.inventory.meta.FireworkMeta; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public final class FireworkHandler { + + private static final Map COLOR_MAP = new HashMap<>(); + private static final String CONFIG_PATH = "join_settings.firework"; + + 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 FireworkHandler() { + } + + public static void spawn(Player player, FileConfiguration config) { + if (!config.getBoolean(CONFIG_PATH + ".enabled", false)) { + return; + } + + if (shouldSkip(player, config)) { + return; + } + + Location loc = player.getLocation(); + Firework firework = (Firework) loc.getWorld().spawnEntity(loc, EntityType.FIREWORK_ROCKET); + FireworkMeta meta = firework.getFireworkMeta(); + + meta.addEffect(buildEffect(config)); + meta.setPower(config.getInt(CONFIG_PATH + ".power", 1)); + firework.setFireworkMeta(meta); + } + + private static boolean shouldSkip(Player player, FileConfiguration config) { + boolean firstJoinOnly = config.getBoolean(CONFIG_PATH + ".first_join_only", true); + return firstJoinOnly && player.hasPlayedBefore(); + } + + private static FireworkEffect buildEffect(FileConfiguration config) { + FireworkEffect.Type type = getType(config); + List colors = getColors(config); + + return FireworkEffect.builder() + .with(type) + .withColor(colors) + .flicker(config.getBoolean(CONFIG_PATH + ".flicker", true)) + .trail(config.getBoolean(CONFIG_PATH + ".trail", true)) + .build(); + } + + private static FireworkEffect.Type getType(FileConfiguration config) { + String typeStr = config.getString(CONFIG_PATH + ".type", "BALL_LARGE"); + try { + return FireworkEffect.Type.valueOf(typeStr); + } catch (IllegalArgumentException e) { + return FireworkEffect.Type.BALL_LARGE; + } + } + + private static List getColors(FileConfiguration config) { + List colors = new ArrayList<>(); + for (String colorStr : config.getStringList(CONFIG_PATH + ".colors")) { + Color color = COLOR_MAP.get(colorStr.toUpperCase()); + if (color != null) { + colors.add(color); + } + } + + if (colors.isEmpty()) { + colors.add(Color.AQUA); + } + + return colors; + } +} diff --git a/lohub/src/main/java/com/loki/lohub/features/JoinMessageHandler.java b/lohub/src/main/java/com/loki/lohub/features/JoinMessageHandler.java new file mode 100644 index 0000000..d43fb13 --- /dev/null +++ b/lohub/src/main/java/com/loki/lohub/features/JoinMessageHandler.java @@ -0,0 +1,44 @@ +package com.loki.lohub.features; + +import com.loki.lohub.utils.TextUtil; +import net.kyori.adventure.text.Component; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +public final class JoinMessageHandler { + + private static final String CONFIG_PATH = "join_leave_messages"; + + private JoinMessageHandler() { + } + + public static void handleJoin(PlayerJoinEvent event, Player player, FileConfiguration config) { + if (!config.getBoolean(CONFIG_PATH + ".enabled", true)) { + return; + } + + String message = config.getString(CONFIG_PATH + ".join_message", ""); + if (message.isEmpty()) { + event.joinMessage(null); + } else { + String formatted = TextUtil.colorize(message.replace("%player%", player.getName())); + event.joinMessage(Component.text(formatted)); + } + } + + public static void handleQuit(PlayerQuitEvent event, Player player, FileConfiguration config) { + if (!config.getBoolean(CONFIG_PATH + ".enabled", true)) { + return; + } + + String message = config.getString(CONFIG_PATH + ".quit_message", ""); + if (message.isEmpty()) { + event.quitMessage(null); + } else { + String formatted = TextUtil.colorize(message.replace("%player%", player.getName())); + event.quitMessage(Component.text(formatted)); + } + } +} diff --git a/lohub/src/main/java/com/loki/lohub/features/JoinSettingsHandler.java b/lohub/src/main/java/com/loki/lohub/features/JoinSettingsHandler.java new file mode 100644 index 0000000..126b1de --- /dev/null +++ b/lohub/src/main/java/com/loki/lohub/features/JoinSettingsHandler.java @@ -0,0 +1,62 @@ +package com.loki.lohub.features; + +import com.loki.lohub.LoHub; +import org.bukkit.Location; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.Player; + +public final class JoinSettingsHandler { + + private static final String CONFIG_PATH = "join_settings"; + + private JoinSettingsHandler() { + } + + public static void apply(Player player, LoHub plugin) { + FileConfiguration config = plugin.getConfig(); + + teleportToSpawn(player, plugin, config); + healPlayer(player, config); + extinguishPlayer(player, config); + clearInventory(player, config); + giveItems(player, plugin); + } + + private static void teleportToSpawn(Player player, LoHub plugin, FileConfiguration config) { + if (!config.getBoolean(CONFIG_PATH + ".spawn_join", true)) { + return; + } + + Location spawn = plugin.getSpawnManager().getSpawn(); + if (spawn != null) { + player.teleport(spawn); + } + } + + private static void healPlayer(Player player, FileConfiguration config) { + if (!config.getBoolean(CONFIG_PATH + ".heal", true)) { + return; + } + + player.setHealth(player.getMaxHealth()); + player.setFoodLevel(20); + player.setSaturation(20); + } + + private static void extinguishPlayer(Player player, FileConfiguration config) { + if (config.getBoolean(CONFIG_PATH + ".extinguish", true)) { + player.setFireTicks(0); + } + } + + private static void clearInventory(Player player, FileConfiguration config) { + if (config.getBoolean(CONFIG_PATH + ".clear_inventory", false)) { + player.getInventory().clear(); + } + } + + private static void giveItems(Player player, LoHub plugin) { + plugin.getHotbarManager().giveItems(player); + plugin.getPlayerHiderManager().giveItem(player); + } +} diff --git a/lohub/src/main/java/com/loki/lohub/listeners/ChatLockListener.java b/lohub/src/main/java/com/loki/lohub/listeners/ChatLockListener.java new file mode 100644 index 0000000..ba94113 --- /dev/null +++ b/lohub/src/main/java/com/loki/lohub/listeners/ChatLockListener.java @@ -0,0 +1,68 @@ +package com.loki.lohub.listeners; + +import com.loki.lohub.LoHub; +import com.loki.lohub.utils.TextUtil; +import net.kyori.adventure.text.Component; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.AsyncPlayerChatEvent; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; + +import java.util.Arrays; +import java.util.List; + +public class ChatLockListener implements Listener { + + private static final List BLOCKED_COMMANDS = Arrays.asList( + "me", "msg", "tell", "w", "whisper", "pm", "dm", + "reply", "r", "say", "minecraft:me", "minecraft:msg", + "minecraft:tell", "bukkit:me", "bukkit:msg", "bukkit:tell" + ); + + private final LoHub plugin; + + public ChatLockListener(LoHub plugin) { + this.plugin = plugin; + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onPlayerChat(AsyncPlayerChatEvent event) { + if (!plugin.getChatLockManager().isChatLocked()) { + return; + } + + Player player = event.getPlayer(); + if (player.hasPermission("lohub.chatlock.bypass")) { + return; + } + + event.setCancelled(true); + player.sendMessage(Component.text(TextUtil.colorize(plugin.getConfigManager().getMessage("chat.locked")))); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onPlayerCommand(PlayerCommandPreprocessEvent event) { + if (!plugin.getChatLockManager().isChatLocked()) { + return; + } + + Player player = event.getPlayer(); + if (player.hasPermission("lohub.chatlock.bypass")) { + return; + } + + String command = event.getMessage().toLowerCase().substring(1); + String baseCommand = command.split(" ")[0]; + + if (isBlockedCommand(baseCommand)) { + event.setCancelled(true); + player.sendMessage(Component.text(TextUtil.colorize(plugin.getConfigManager().getMessage("chat.locked")))); + } + } + + private boolean isBlockedCommand(String command) { + return BLOCKED_COMMANDS.stream().anyMatch(blocked -> command.equals(blocked)); + } +} diff --git a/lohub/src/main/java/com/loki/lohub/listeners/CustomCommandListener.java b/lohub/src/main/java/com/loki/lohub/listeners/CustomCommandListener.java new file mode 100644 index 0000000..6c0ce94 --- /dev/null +++ b/lohub/src/main/java/com/loki/lohub/listeners/CustomCommandListener.java @@ -0,0 +1,47 @@ +package com.loki.lohub.listeners; + +import com.loki.lohub.LoHub; +import com.loki.lohub.managers.CustomCommandManager; +import com.loki.lohub.utils.TextUtil; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; + +public class CustomCommandListener implements Listener { + + private final LoHub plugin; + + public CustomCommandListener(LoHub plugin) { + this.plugin = plugin; + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onPlayerCommand(PlayerCommandPreprocessEvent event) { + Player player = event.getPlayer(); + String message = event.getMessage().toLowerCase(); + + if (!message.startsWith("/")) { + return; + } + + String command = message.substring(1).split(" ")[0]; + CustomCommandManager.CustomCommand customCommand = plugin.getCustomCommandManager().getCommand(command); + + if (customCommand == null) { + return; + } + + event.setCancelled(true); + + if (customCommand.permission() != null && !customCommand.permission().isEmpty()) { + if (!player.hasPermission(customCommand.permission())) { + player.sendMessage(TextUtil.colorize(plugin.getConfig().getString("messages.no-permission"))); + return; + } + } + + plugin.getActionManager().executeActions(player, customCommand.actions(), false); + } +} diff --git a/lohub/src/main/java/com/loki/lohub/listeners/DoubleJumpListener.java b/lohub/src/main/java/com/loki/lohub/listeners/DoubleJumpListener.java index 9e0fece..68c4e5d 100644 --- a/lohub/src/main/java/com/loki/lohub/listeners/DoubleJumpListener.java +++ b/lohub/src/main/java/com/loki/lohub/listeners/DoubleJumpListener.java @@ -1,18 +1,22 @@ package com.loki.lohub.listeners; import com.loki.lohub.LoHub; -import org.bukkit.GameMode; +import com.loki.lohub.common.ConfigHelper; +import com.loki.lohub.common.GameModeHelper; +import com.loki.lohub.common.LaunchHelper; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerToggleFlightEvent; -import org.bukkit.util.Vector; import java.util.List; public class DoubleJumpListener implements Listener { + private static final String CONFIG_PATH = "double_jump"; + private static final String COOLDOWN_KEY = "double_jump"; + private final LoHub plugin; public DoubleJumpListener(LoHub plugin) { @@ -21,13 +25,13 @@ public class DoubleJumpListener implements Listener { @EventHandler public void onPlayerMove(PlayerMoveEvent event) { - if (!plugin.getConfig().getBoolean("double_jump.enabled", true)) { + if (!ConfigHelper.isEnabled(plugin.getConfig(), CONFIG_PATH)) { return; } Player player = event.getPlayer(); - if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.SPECTATOR) { + if (GameModeHelper.isCreativeOrSpectator(player)) { return; } @@ -41,38 +45,45 @@ public class DoubleJumpListener implements Listener { @EventHandler public void onPlayerToggleFlight(PlayerToggleFlightEvent event) { - if (!plugin.getConfig().getBoolean("double_jump.enabled", true)) { + if (!ConfigHelper.isEnabled(plugin.getConfig(), CONFIG_PATH)) { return; } Player player = event.getPlayer(); - if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.SPECTATOR) { + if (GameModeHelper.isCreativeOrSpectator(player)) { return; } - if (plugin.getCooldownManager().hasCooldown("double_jump", player.getUniqueId())) { - event.setCancelled(true); - player.setAllowFlight(false); - player.setFlying(false); + if (plugin.getCooldownManager().hasCooldown(COOLDOWN_KEY, player.getUniqueId())) { + cancelFlight(event, player); return; } + cancelFlight(event, player); + performDoubleJump(player); + } + + private void cancelFlight(PlayerToggleFlightEvent event, Player player) { event.setCancelled(true); player.setAllowFlight(false); player.setFlying(false); + } - double power = plugin.getConfig().getDouble("double_jump.launch_power", 1.0); - double powerY = plugin.getConfig().getDouble("double_jump.launch_power_y", 0.9); + private void performDoubleJump(Player player) { + double power = ConfigHelper.getPower(plugin.getConfig(), CONFIG_PATH, "launch_power", 1.0); + double powerY = ConfigHelper.getPower(plugin.getConfig(), CONFIG_PATH, "launch_power_y", 0.9); - Vector velocity = player.getLocation().getDirection().multiply(power); - velocity.setY(powerY); - player.setVelocity(velocity); + LaunchHelper.launch(player, power, powerY); - int cooldown = plugin.getConfig().getInt("double_jump.cooldown", 3); - plugin.getCooldownManager().setCooldown("double_jump", player.getUniqueId(), cooldown); + int cooldown = ConfigHelper.getCooldown(plugin.getConfig(), CONFIG_PATH, 3); + plugin.getCooldownManager().setCooldown(COOLDOWN_KEY, player.getUniqueId(), cooldown); - List actions = plugin.getConfig().getStringList("double_jump.actions"); + executeActions(player); + } + + private void executeActions(Player player) { + List actions = plugin.getConfig().getStringList(CONFIG_PATH + ".actions"); if (!actions.isEmpty()) { plugin.getActionManager().executeActions(player, actions, false); } 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 1048783..4cb6335 100644 --- a/lohub/src/main/java/com/loki/lohub/listeners/HubProtectionListener.java +++ b/lohub/src/main/java/com/loki/lohub/listeners/HubProtectionListener.java @@ -8,9 +8,11 @@ import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.FoodLevelChangeEvent; +import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.player.PlayerDropItemEvent; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerPickupItemEvent; +import org.bukkit.event.player.PlayerSwapHandItemsEvent; public class HubProtectionListener implements Listener { @@ -131,4 +133,38 @@ public class HubProtectionListener implements Listener { event.setCancelled(true); } } + + @EventHandler + public void onPlayerSwapHandItems(PlayerSwapHandItemsEvent event) { + if (!plugin.getConfig().getBoolean("world_settings.disable_off_hand_swap", true)) { + return; + } + + Player player = event.getPlayer(); + if (player.hasPermission("lohub.bypass.protection")) { + return; + } + + event.setCancelled(true); + } + + @EventHandler + public void onInventoryClick(InventoryClickEvent event) { + if (!plugin.getConfig().getBoolean("world_settings.disable_off_hand_swap", true)) { + return; + } + + if (!(event.getWhoClicked() instanceof Player)) { + return; + } + + Player player = (Player) event.getWhoClicked(); + if (player.hasPermission("lohub.bypass.protection")) { + return; + } + + if (event.getRawSlot() != event.getSlot() && event.getSlot() == 40) { + event.setCancelled(true); + } + } } diff --git a/lohub/src/main/java/com/loki/lohub/listeners/LaunchpadListener.java b/lohub/src/main/java/com/loki/lohub/listeners/LaunchpadListener.java index 288ec27..a233790 100644 --- a/lohub/src/main/java/com/loki/lohub/listeners/LaunchpadListener.java +++ b/lohub/src/main/java/com/loki/lohub/listeners/LaunchpadListener.java @@ -1,18 +1,21 @@ package com.loki.lohub.listeners; import com.loki.lohub.LoHub; +import com.loki.lohub.common.ConfigHelper; +import com.loki.lohub.common.LaunchHelper; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerMoveEvent; -import org.bukkit.util.Vector; import java.util.List; public class LaunchpadListener implements Listener { + private static final String CONFIG_PATH = "launchpad"; + private final LoHub plugin; public LaunchpadListener(LoHub plugin) { @@ -21,46 +24,59 @@ public class LaunchpadListener implements Listener { @EventHandler public void onPlayerMove(PlayerMoveEvent event) { - if (!plugin.getConfig().getBoolean("launchpad.enabled", true)) { + if (!ConfigHelper.isEnabled(plugin.getConfig(), CONFIG_PATH)) { return; } - if (event.getFrom().getBlockX() == event.getTo().getBlockX() - && event.getFrom().getBlockY() == event.getTo().getBlockY() - && event.getFrom().getBlockZ() == event.getTo().getBlockZ()) { + if (!hasMoved(event)) { return; } Player player = event.getPlayer(); Block block = player.getLocation().getBlock(); - String topBlockStr = plugin.getConfig().getString("launchpad.top_block", "STONE_PRESSURE_PLATE"); - String bottomBlockStr = plugin.getConfig().getString("launchpad.bottom_block", "REDSTONE_BLOCK"); - - Material topMaterial = Material.getMaterial(topBlockStr); - Material bottomMaterial = Material.getMaterial(bottomBlockStr); - - if (topMaterial == null || bottomMaterial == null) { - return; - } - - if (block.getType() == topMaterial) { - Block below = block.getRelative(0, -1, 0); - if (below.getType() == bottomMaterial) { - launchPlayer(player); - } + if (isLaunchpad(block)) { + launchPlayer(player); } } + private boolean hasMoved(PlayerMoveEvent event) { + return event.getFrom().getBlockX() != event.getTo().getBlockX() + || event.getFrom().getBlockY() != event.getTo().getBlockY() + || event.getFrom().getBlockZ() != event.getTo().getBlockZ(); + } + + private boolean isLaunchpad(Block block) { + Material topMaterial = getMaterial("top_block", "STONE_PRESSURE_PLATE"); + Material bottomMaterial = getMaterial("bottom_block", "REDSTONE_BLOCK"); + + if (topMaterial == null || bottomMaterial == null) { + return false; + } + + if (block.getType() != topMaterial) { + return false; + } + + Block below = block.getRelative(0, -1, 0); + return below.getType() == bottomMaterial; + } + + private Material getMaterial(String key, String defaultValue) { + String materialName = plugin.getConfig().getString(CONFIG_PATH + "." + key, defaultValue); + return Material.getMaterial(materialName); + } + private void launchPlayer(Player player) { - double power = plugin.getConfig().getDouble("launchpad.launch_power", 3.0); - double powerY = plugin.getConfig().getDouble("launchpad.launch_power_y", 1.0); + double power = ConfigHelper.getPower(plugin.getConfig(), CONFIG_PATH, "launch_power", 3.0); + double powerY = ConfigHelper.getPower(plugin.getConfig(), CONFIG_PATH, "launch_power_y", 1.0); - Vector velocity = player.getLocation().getDirection().multiply(power); - velocity.setY(powerY); - player.setVelocity(velocity); + LaunchHelper.launch(player, power, powerY); + executeActions(player); + } - List actions = plugin.getConfig().getStringList("launchpad.actions"); + private void executeActions(Player player) { + List actions = plugin.getConfig().getStringList(CONFIG_PATH + ".actions"); if (!actions.isEmpty()) { plugin.getActionManager().executeActions(player, actions, false); } 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 7c6049d..ac42700 100644 --- a/lohub/src/main/java/com/loki/lohub/listeners/PlayerJoinListener.java +++ b/lohub/src/main/java/com/loki/lohub/listeners/PlayerJoinListener.java @@ -1,13 +1,10 @@ package com.loki.lohub.listeners; import com.loki.lohub.LoHub; -import com.loki.lohub.utils.TextUtil; -import net.kyori.adventure.text.Component; -import org.bukkit.Color; -import org.bukkit.FireworkEffect; +import com.loki.lohub.features.FireworkHandler; +import com.loki.lohub.features.JoinMessageHandler; +import com.loki.lohub.features.JoinSettingsHandler; import org.bukkit.Location; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.Firework; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; @@ -16,37 +13,11 @@ import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerRespawnEvent; -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) { @@ -61,10 +32,10 @@ public class PlayerJoinListener implements Listener { return; } - handleJoinMessage(event, player); - handleJoinSettings(player); - handleJoinEvents(player); - handleFirework(player); + JoinMessageHandler.handleJoin(event, player, plugin.getConfig()); + JoinSettingsHandler.apply(player, plugin); + executeJoinActions(player); + FireworkHandler.spawn(player, plugin.getConfig()); plugin.getScoreboardManager().setScoreboard(player, true); plugin.getTablistManager().setTablist(player); @@ -81,14 +52,7 @@ public class PlayerJoinListener implements Listener { plugin.getPlayerHiderManager().removePlayer(player); plugin.getScoreboardManager().removePlayer(player); - if (plugin.getConfig().getBoolean("join_leave_messages.enabled", true)) { - String quitMessage = plugin.getConfig().getString("join_leave_messages.quit_message", ""); - if (quitMessage.isEmpty()) { - event.quitMessage(null); - } else { - event.quitMessage(Component.text(TextUtil.colorize(quitMessage.replace("%player%", player.getName())))); - } - } + JoinMessageHandler.handleQuit(event, player, plugin.getConfig()); } @EventHandler(priority = EventPriority.HIGHEST) @@ -118,100 +82,13 @@ public class PlayerJoinListener implements Listener { } } - 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", ""); - if (joinMessage.isEmpty()) { - event.joinMessage(null); - } else { - event.joinMessage(Component.text(TextUtil.colorize(joinMessage.replace("%player%", player.getName())))); - } - } - } - - private void handleJoinSettings(Player player) { - if (plugin.getConfig().getBoolean("join_settings.spawn_join", true)) { - Location spawn = plugin.getSpawnManager().getSpawn(); - if (spawn != null) { - 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(); - } - - plugin.getHotbarManager().giveItems(player); - plugin.getPlayerHiderManager().giveItem(player); - } - - private void handleJoinEvents(Player player) { + private void executeJoinActions(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_ROCKET); - FireworkMeta meta = firework.getFireworkMeta(); - - String typeStr = plugin.getConfig().getString("join_settings.firework.type", "BALL_LARGE"); - FireworkEffect.Type type; - try { - type = FireworkEffect.Type.valueOf(typeStr); - } 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); - if (color != null) { - 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(); - - meta.addEffect(effect); - meta.setPower(plugin.getConfig().getInt("join_settings.firework.power", 1)); - firework.setFireworkMeta(meta); - } - - private Color parseColor(String colorStr) { - 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); diff --git a/lohub/src/main/java/com/loki/lohub/managers/AnnouncementManager.java b/lohub/src/main/java/com/loki/lohub/managers/AnnouncementManager.java index 22b2485..b84bdac 100644 --- a/lohub/src/main/java/com/loki/lohub/managers/AnnouncementManager.java +++ b/lohub/src/main/java/com/loki/lohub/managers/AnnouncementManager.java @@ -1,8 +1,8 @@ package com.loki.lohub.managers; import com.loki.lohub.LoHub; -import com.loki.lohub.utils.PlaceholderUtil; -import com.loki.lohub.utils.TextUtil; +import com.loki.lohub.common.ConfigHelper; +import com.loki.lohub.common.TextFormatter; import net.kyori.adventure.text.Component; import org.bukkit.Bukkit; import org.bukkit.Sound; @@ -14,6 +14,8 @@ import java.util.List; public class AnnouncementManager { + private static final String CONFIG_PATH = "announcements"; + private final LoHub plugin; private final List announcements = new ArrayList<>(); private int currentIndex = 0; @@ -26,21 +28,21 @@ public class AnnouncementManager { private void loadAnnouncements() { announcements.clear(); - ConfigurationSection section = plugin.getConfig().getConfigurationSection("announcements.announcements"); + ConfigurationSection section = plugin.getConfig().getConfigurationSection(CONFIG_PATH + ".announcements"); if (section == null) { return; } - for (String key : section.getKeys(false)) { + section.getKeys(false).forEach(key -> { List messages = section.getStringList(key); if (!messages.isEmpty()) { announcements.add(new Announcement(key, messages)); } - } + }); } public void start() { - if (!plugin.getConfig().getBoolean("announcements.enabled", false)) { + if (!ConfigHelper.isEnabled(plugin.getConfig(), CONFIG_PATH)) { return; } @@ -48,7 +50,7 @@ public class AnnouncementManager { return; } - int delay = plugin.getConfig().getInt("announcements.delay", 60) * 20; + int delay = plugin.getConfig().getInt(CONFIG_PATH + ".delay", 60) * 20; taskId = Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, this::broadcast, delay, delay); } @@ -60,8 +62,7 @@ public class AnnouncementManager { } private void broadcast() { - int requiredPlayers = plugin.getConfig().getInt("announcements.required_players", 1); - if (Bukkit.getOnlinePlayers().size() < requiredPlayers) { + if (!hasEnoughPlayers()) { return; } @@ -69,25 +70,40 @@ public class AnnouncementManager { return; } + Announcement announcement = getNextAnnouncement(); + Bukkit.getOnlinePlayers().forEach(player -> sendAnnouncement(player, announcement)); + } + + private boolean hasEnoughPlayers() { + int required = plugin.getConfig().getInt(CONFIG_PATH + ".required_players", 1); + return Bukkit.getOnlinePlayers().size() >= required; + } + + private Announcement getNextAnnouncement() { Announcement announcement = announcements.get(currentIndex); currentIndex = (currentIndex + 1) % announcements.size(); + return announcement; + } - for (Player player : Bukkit.getOnlinePlayers()) { - for (String message : announcement.messages()) { - String formatted = PlaceholderUtil.parse(message, player); - player.sendMessage(Component.text(TextUtil.colorize(formatted))); - } + private void sendAnnouncement(Player player, Announcement announcement) { + announcement.messages().forEach(message -> { + String formatted = TextFormatter.format(message, player); + player.sendMessage(Component.text(formatted)); + }); - if (plugin.getConfig().getBoolean("announcements.sound.enabled", true)) { - playSound(player); - } + if (shouldPlaySound()) { + playSound(player); } } + private boolean shouldPlaySound() { + return plugin.getConfig().getBoolean(CONFIG_PATH + ".sound.enabled", true); + } + private void playSound(Player player) { - String soundStr = plugin.getConfig().getString("announcements.sound.value", "BLOCK_NOTE_BLOCK_PLING"); - float volume = (float) plugin.getConfig().getDouble("announcements.sound.volume", 1.0); - float pitch = (float) plugin.getConfig().getDouble("announcements.sound.pitch", 1.0); + String soundStr = plugin.getConfig().getString(CONFIG_PATH + ".sound.value", "BLOCK_NOTE_BLOCK_PLING"); + float volume = (float) plugin.getConfig().getDouble(CONFIG_PATH + ".sound.volume", 1.0); + float pitch = (float) plugin.getConfig().getDouble(CONFIG_PATH + ".sound.pitch", 1.0); try { Sound sound = Sound.valueOf(soundStr); diff --git a/lohub/src/main/java/com/loki/lohub/managers/ChatLockManager.java b/lohub/src/main/java/com/loki/lohub/managers/ChatLockManager.java new file mode 100644 index 0000000..a6c5576 --- /dev/null +++ b/lohub/src/main/java/com/loki/lohub/managers/ChatLockManager.java @@ -0,0 +1,25 @@ +package com.loki.lohub.managers; + +import com.loki.lohub.LoHub; + +public class ChatLockManager { + + private final LoHub plugin; + + public ChatLockManager(LoHub plugin) { + this.plugin = plugin; + } + + public boolean isChatLocked() { + return plugin.getConfigManager().getData().getBoolean("chat_locked", false); + } + + public void setChatLocked(boolean locked) { + plugin.getConfigManager().getData().set("chat_locked", locked); + plugin.getConfigManager().saveData(); + } + + public void toggle() { + setChatLocked(!isChatLocked()); + } +} diff --git a/lohub/src/main/java/com/loki/lohub/managers/CustomCommandManager.java b/lohub/src/main/java/com/loki/lohub/managers/CustomCommandManager.java new file mode 100644 index 0000000..1d640e0 --- /dev/null +++ b/lohub/src/main/java/com/loki/lohub/managers/CustomCommandManager.java @@ -0,0 +1,62 @@ +package com.loki.lohub.managers; + +import com.loki.lohub.LoHub; +import org.bukkit.configuration.ConfigurationSection; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class CustomCommandManager { + + private final LoHub plugin; + private final Map commands = new HashMap<>(); + + public CustomCommandManager(LoHub plugin) { + this.plugin = plugin; + loadCommands(); + } + + private void loadCommands() { + commands.clear(); + ConfigurationSection section = plugin.getConfigManager().getCommands().getConfigurationSection("custom_commands"); + if (section == null) { + return; + } + + for (String key : section.getKeys(false)) { + ConfigurationSection cmdSection = section.getConfigurationSection(key); + if (cmdSection == null) { + continue; + } + + List aliases = cmdSection.getStringList("aliases"); + String permission = cmdSection.getString("permission"); + List actions = cmdSection.getStringList("actions"); + + if (aliases.isEmpty() || actions.isEmpty()) { + continue; + } + + CustomCommand cmd = new CustomCommand(key, aliases, permission, actions); + for (String alias : aliases) { + commands.put(alias.toLowerCase(), cmd); + } + } + } + + public CustomCommand getCommand(String alias) { + return commands.get(alias.toLowerCase()); + } + + public boolean hasCommand(String alias) { + return commands.containsKey(alias.toLowerCase()); + } + + public void reload() { + loadCommands(); + } + + public record CustomCommand(String name, List aliases, String permission, List actions) { + } +} diff --git a/lohub/src/main/java/com/loki/lohub/managers/HotbarManager.java b/lohub/src/main/java/com/loki/lohub/managers/HotbarManager.java index eab448b..8e6ed55 100644 --- a/lohub/src/main/java/com/loki/lohub/managers/HotbarManager.java +++ b/lohub/src/main/java/com/loki/lohub/managers/HotbarManager.java @@ -13,6 +13,8 @@ import java.util.Map; public class HotbarManager { + private static final String CONFIG_PATH = "custom_join_items"; + private final LoHub plugin; private final Map items = new HashMap<>(); @@ -23,46 +25,56 @@ public class HotbarManager { private void loadItems() { items.clear(); - ConfigurationSection section = plugin.getConfig().getConfigurationSection("custom_join_items.items"); + ConfigurationSection section = plugin.getConfig().getConfigurationSection(CONFIG_PATH + ".items"); if (section == null) { return; } for (String key : section.getKeys(false)) { - ConfigurationSection itemSection = section.getConfigurationSection(key); - if (itemSection == null) { - continue; - } - - Material material = Material.getMaterial(itemSection.getString("material", "STONE")); - if (material == null) { - continue; - } - - int slot = itemSection.getInt("slot", 0); - int amount = itemSection.getInt("amount", 1); - String displayName = itemSection.getString("display_name", ""); - List lore = itemSection.getStringList("lore"); - List actions = itemSection.getStringList("actions"); - - ItemStack item = new ItemBuilder(material) - .amount(amount) - .name(displayName) - .lore(lore) - .build(); - - items.put(slot, new HotbarItem(item, actions)); + loadItem(section.getConfigurationSection(key)); } } - public void giveItems(Player player) { - if (!plugin.getConfig().getBoolean("custom_join_items.enabled", false)) { + private void loadItem(ConfigurationSection itemSection) { + if (itemSection == null) { return; } - for (Map.Entry entry : items.entrySet()) { - player.getInventory().setItem(entry.getKey(), entry.getValue().item()); + Material material = getMaterial(itemSection); + if (material == null) { + return; } + + int slot = itemSection.getInt("slot", 0); + ItemStack item = buildItem(itemSection, material); + List actions = itemSection.getStringList("actions"); + + items.put(slot, new HotbarItem(item, actions)); + } + + private Material getMaterial(ConfigurationSection section) { + String materialName = section.getString("material", "STONE"); + return Material.getMaterial(materialName); + } + + private ItemStack buildItem(ConfigurationSection section, Material material) { + int amount = section.getInt("amount", 1); + String displayName = section.getString("display_name", ""); + List lore = section.getStringList("lore"); + + return new ItemBuilder(material) + .amount(amount) + .name(displayName) + .lore(lore) + .build(); + } + + public void giveItems(Player player) { + if (!isEnabled()) { + return; + } + + items.forEach((slot, item) -> player.getInventory().setItem(slot, item.item())); } public void handleClick(Player player, int slot) { @@ -82,6 +94,10 @@ public class HotbarManager { loadItems(); } + private boolean isEnabled() { + return plugin.getConfig().getBoolean(CONFIG_PATH + ".enabled", false); + } + private record HotbarItem(ItemStack item, List actions) { } } diff --git a/lohub/src/main/java/com/loki/lohub/managers/PlayerHiderManager.java b/lohub/src/main/java/com/loki/lohub/managers/PlayerHiderManager.java index 74cf01b..5917e44 100644 --- a/lohub/src/main/java/com/loki/lohub/managers/PlayerHiderManager.java +++ b/lohub/src/main/java/com/loki/lohub/managers/PlayerHiderManager.java @@ -14,6 +14,10 @@ import java.util.UUID; public class PlayerHiderManager { + private static final String CONFIG_PATH = "player_hider"; + private static final String HIDDEN_PATH = CONFIG_PATH + ".hidden"; + private static final String NOT_HIDDEN_PATH = CONFIG_PATH + ".not_hidden"; + private final LoHub plugin; private final Set hiddenPlayers = new HashSet<>(); @@ -22,23 +26,18 @@ public class PlayerHiderManager { } public void giveItem(Player player) { - if (!plugin.getConfig().getBoolean("player_hider.enabled", true)) { + if (!isEnabled()) { return; } - int slot = plugin.getConfig().getInt("player_hider.slot", 8); - player.getInventory().setItem(slot, getItem(player)); + player.getInventory().setItem(getSlot(), getItem(player)); } public ItemStack getItem(Player player) { - boolean hidden = hiddenPlayers.contains(player.getUniqueId()); - String path = hidden ? "player_hider.hidden" : "player_hider.not_hidden"; - - Material material = Material.getMaterial(plugin.getConfig().getString(path + ".material", "LIME_DYE")); - if (material == null) { - material = Material.LIME_DYE; - } + boolean hidden = isHidden(player); + String path = hidden ? HIDDEN_PATH : NOT_HIDDEN_PATH; + Material material = getMaterial(path); int amount = plugin.getConfig().getInt(path + ".amount", 1); String displayName = plugin.getConfig().getString(path + ".display_name", ""); List lore = plugin.getConfig().getStringList(path + ".lore"); @@ -51,7 +50,7 @@ public class PlayerHiderManager { } public void toggle(Player player) { - if (hiddenPlayers.contains(player.getUniqueId())) { + if (isHidden(player)) { showPlayers(player); } else { hidePlayers(player); @@ -62,33 +61,53 @@ public class PlayerHiderManager { private void hidePlayers(Player player) { hiddenPlayers.add(player.getUniqueId()); - for (Player online : Bukkit.getOnlinePlayers()) { - if (!online.equals(player)) { - player.hidePlayer(plugin, online); - } - } + applyVisibility(player, false); } private void showPlayers(Player player) { hiddenPlayers.remove(player.getUniqueId()); + applyVisibility(player, true); + } + + private void applyVisibility(Player player, boolean visible) { for (Player online : Bukkit.getOnlinePlayers()) { if (!online.equals(player)) { - player.showPlayer(plugin, online); + if (visible) { + player.showPlayer(plugin, online); + } else { + player.hidePlayer(plugin, online); + } } } } private void updateItem(Player player) { - int slot = plugin.getConfig().getInt("player_hider.slot", 8); - player.getInventory().setItem(slot, getItem(player)); + player.getInventory().setItem(getSlot(), getItem(player)); } public boolean isPlayerHiderSlot(int slot) { - return plugin.getConfig().getBoolean("player_hider.enabled", true) - && slot == plugin.getConfig().getInt("player_hider.slot", 8); + return isEnabled() && slot == getSlot(); } public void removePlayer(Player player) { hiddenPlayers.remove(player.getUniqueId()); } + + private boolean isEnabled() { + return plugin.getConfig().getBoolean(CONFIG_PATH + ".enabled", true); + } + + private int getSlot() { + return plugin.getConfig().getInt(CONFIG_PATH + ".slot", 8); + } + + private boolean isHidden(Player player) { + return hiddenPlayers.contains(player.getUniqueId()); + } + + private Material getMaterial(String path) { + String materialName = plugin.getConfig().getString(path + ".material", "LIME_DYE"); + Material material = Material.getMaterial(materialName); + return material != null ? material : Material.LIME_DYE; + } } diff --git a/lohub/src/main/java/com/loki/lohub/managers/ScoreboardManager.java b/lohub/src/main/java/com/loki/lohub/managers/ScoreboardManager.java index 29a114e..125fc71 100644 --- a/lohub/src/main/java/com/loki/lohub/managers/ScoreboardManager.java +++ b/lohub/src/main/java/com/loki/lohub/managers/ScoreboardManager.java @@ -1,8 +1,8 @@ package com.loki.lohub.managers; import com.loki.lohub.LoHub; -import com.loki.lohub.utils.PlaceholderUtil; -import com.loki.lohub.utils.TextUtil; +import com.loki.lohub.common.ConfigHelper; +import com.loki.lohub.common.TextFormatter; import net.kyori.adventure.text.Component; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -18,6 +18,9 @@ import java.util.UUID; public class ScoreboardManager { + private static final String CONFIG_PATH = "scoreboard"; + private static final String OBJECTIVE_NAME = "lohub"; + private final LoHub plugin; private final Map scoreboards = new HashMap<>(); private int taskId = -1; @@ -27,12 +30,12 @@ public class ScoreboardManager { } public void start() { - if (!plugin.getConfig().getBoolean("scoreboard.enabled", false)) { + if (!ConfigHelper.isEnabled(plugin.getConfig(), CONFIG_PATH)) { return; } - if (plugin.getConfig().getBoolean("scoreboard.refresh.enabled", true)) { - int rate = plugin.getConfig().getInt("scoreboard.refresh.rate", 200); + if (shouldRefresh()) { + int rate = plugin.getConfig().getInt(CONFIG_PATH + ".refresh.rate", 200); taskId = Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, this::updateAll, 0L, rate); } } @@ -46,12 +49,12 @@ public class ScoreboardManager { } public void setScoreboard(Player player, boolean delayed) { - if (!plugin.getConfig().getBoolean("scoreboard.enabled", false)) { + if (!ConfigHelper.isEnabled(plugin.getConfig(), CONFIG_PATH)) { return; } if (delayed) { - int delay = plugin.getConfig().getInt("scoreboard.display_delay.server_enter", 60); + int delay = plugin.getConfig().getInt(CONFIG_PATH + ".display_delay.server_enter", 60); Bukkit.getScheduler().runTaskLater(plugin, () -> createScoreboard(player), delay); } else { createScoreboard(player); @@ -60,7 +63,7 @@ public class ScoreboardManager { private void createScoreboard(Player player) { Scoreboard scoreboard = Bukkit.getScoreboardManager().getNewScoreboard(); - Objective objective = scoreboard.registerNewObjective("lohub", "dummy", Component.text("")); + Objective objective = scoreboard.registerNewObjective(OBJECTIVE_NAME, "dummy", Component.text("")); objective.setDisplaySlot(DisplaySlot.SIDEBAR); updateScoreboard(player, scoreboard, objective); @@ -70,43 +73,56 @@ public class ScoreboardManager { } private void updateScoreboard(Player player, Scoreboard scoreboard, Objective objective) { - String title = plugin.getConfig().getString("scoreboard.title", ""); - title = PlaceholderUtil.parse(title, player); - objective.displayName(Component.text(TextUtil.colorize(title))); + updateTitle(player, objective); + updateLines(player, scoreboard, objective); + } - List lines = plugin.getConfig().getStringList("scoreboard.lines"); + private void updateTitle(Player player, Objective objective) { + String title = plugin.getConfig().getString(CONFIG_PATH + ".title", ""); + objective.displayName(Component.text(TextFormatter.format(title, player))); + } + + private void updateLines(Player player, Scoreboard scoreboard, Objective objective) { + List lines = plugin.getConfig().getStringList(CONFIG_PATH + ".lines"); int score = lines.size(); for (String line : lines) { - line = PlaceholderUtil.parse(line, player); - line = TextUtil.colorize(line); - + String formatted = TextFormatter.format(line, player); String teamName = "line_" + score; - Team team = scoreboard.getTeam(teamName); - if (team == null) { - team = scoreboard.registerNewTeam(teamName); - team.addEntry(teamName); - } - team.prefix(Component.text(line)); + Team team = getOrCreateTeam(scoreboard, teamName); + team.prefix(Component.text(formatted)); objective.getScore(teamName).setScore(score); score--; } } + private Team getOrCreateTeam(Scoreboard scoreboard, String teamName) { + Team team = scoreboard.getTeam(teamName); + if (team == null) { + team = scoreboard.registerNewTeam(teamName); + team.addEntry(teamName); + } + return team; + } + private void updateAll() { - for (Player player : Bukkit.getOnlinePlayers()) { - Scoreboard scoreboard = scoreboards.get(player.getUniqueId()); - if (scoreboard != null) { - Objective objective = scoreboard.getObjective("lohub"); + scoreboards.forEach((uuid, scoreboard) -> { + Player player = Bukkit.getPlayer(uuid); + if (player != null) { + Objective objective = scoreboard.getObjective(OBJECTIVE_NAME); if (objective != null) { updateScoreboard(player, scoreboard, objective); } } - } + }); } public void removePlayer(Player player) { scoreboards.remove(player.getUniqueId()); } + + private boolean shouldRefresh() { + return plugin.getConfig().getBoolean(CONFIG_PATH + ".refresh.enabled", true); + } } 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 3effc29..14ef5a4 100644 --- a/lohub/src/main/java/com/loki/lohub/managers/SpawnManager.java +++ b/lohub/src/main/java/com/loki/lohub/managers/SpawnManager.java @@ -4,83 +4,56 @@ import com.loki.lohub.LoHub; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; -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 { - spawnFile.createNewFile(); - } catch (IOException e) { - 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"); - double y = spawnConfig.getDouble("spawn.y"); - 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); - plugin.getLogger().info("Spawn loaded: " + worldName + " (" + x + ", " + y + ", " + z + ")"); - } else { - plugin.getLogger().warning("World '" + worldName + "' not found!"); - } - } } public Location getSpawn() { - return spawnLocation; + String worldName = plugin.getConfigManager().getData().getString("spawn.world"); + if (worldName == null || worldName.equals("null")) { + return null; + } + + World world = Bukkit.getWorld(worldName); + if (world == null) { + plugin.getLogger().warning("World '" + worldName + "' not found!"); + return null; + } + + double x = plugin.getConfigManager().getData().getDouble("spawn.x"); + double y = plugin.getConfigManager().getData().getDouble("spawn.y"); + double z = plugin.getConfigManager().getData().getDouble("spawn.z"); + float yaw = (float) plugin.getConfigManager().getData().getDouble("spawn.yaw"); + float pitch = (float) plugin.getConfigManager().getData().getDouble("spawn.pitch"); + + return new Location(world, x, y, z, yaw, pitch); } public void setSpawn(Location location) { - this.spawnLocation = location; + plugin.getConfigManager().getData().set("spawn.world", location.getWorld().getName()); + plugin.getConfigManager().getData().set("spawn.x", location.getX()); + plugin.getConfigManager().getData().set("spawn.y", location.getY()); + plugin.getConfigManager().getData().set("spawn.z", location.getZ()); + plugin.getConfigManager().getData().set("spawn.yaw", location.getYaw()); + plugin.getConfigManager().getData().set("spawn.pitch", location.getPitch()); + plugin.getConfigManager().saveData(); - 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() + ")"); - } catch (IOException e) { - plugin.getLogger().severe("Failed to save spawn.yml: " + e.getMessage()); - } + plugin.getLogger().info("Spawn set: " + location.getWorld().getName() + + " (" + location.getBlockX() + ", " + location.getBlockY() + ", " + location.getBlockZ() + ")"); } public void teleportToSpawn(Player player) { - if (spawnLocation == null) { + Location spawn = getSpawn(); + if (spawn == null) { return; } - player.teleport(spawnLocation); + player.teleport(spawn); } } diff --git a/lohub/src/main/java/com/loki/lohub/managers/TablistManager.java b/lohub/src/main/java/com/loki/lohub/managers/TablistManager.java index 81c621a..0aa0fe4 100644 --- a/lohub/src/main/java/com/loki/lohub/managers/TablistManager.java +++ b/lohub/src/main/java/com/loki/lohub/managers/TablistManager.java @@ -1,8 +1,8 @@ package com.loki.lohub.managers; import com.loki.lohub.LoHub; -import com.loki.lohub.utils.PlaceholderUtil; -import com.loki.lohub.utils.TextUtil; +import com.loki.lohub.common.ConfigHelper; +import com.loki.lohub.common.TextFormatter; import net.kyori.adventure.text.Component; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -11,6 +11,8 @@ import java.util.List; public class TablistManager { + private static final String CONFIG_PATH = "tablist"; + private final LoHub plugin; private int taskId = -1; @@ -19,12 +21,12 @@ public class TablistManager { } public void start() { - if (!plugin.getConfig().getBoolean("tablist.enabled", false)) { + if (!ConfigHelper.isEnabled(plugin.getConfig(), CONFIG_PATH)) { return; } - if (plugin.getConfig().getBoolean("tablist.refresh.enabled", true)) { - int rate = plugin.getConfig().getInt("tablist.refresh.rate", 400); + if (shouldRefresh()) { + int rate = plugin.getConfig().getInt(CONFIG_PATH + ".refresh.rate", 400); taskId = Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, this::updateAll, 0L, rate); } } @@ -37,7 +39,7 @@ public class TablistManager { } public void setTablist(Player player) { - if (!plugin.getConfig().getBoolean("tablist.enabled", false)) { + if (!ConfigHelper.isEnabled(plugin.getConfig(), CONFIG_PATH)) { return; } @@ -45,36 +47,25 @@ public class TablistManager { } private void updateTablist(Player player) { - List headerLines = plugin.getConfig().getStringList("tablist.header"); - List footerLines = plugin.getConfig().getStringList("tablist.footer"); - - StringBuilder header = new StringBuilder(); - for (int i = 0; i < headerLines.size(); i++) { - String line = PlaceholderUtil.parse(headerLines.get(i), player); - header.append(TextUtil.colorize(line)); - if (i < headerLines.size() - 1) { - header.append("\n"); - } - } - - StringBuilder footer = new StringBuilder(); - for (int i = 0; i < footerLines.size(); i++) { - String line = PlaceholderUtil.parse(footerLines.get(i), player); - footer.append(TextUtil.colorize(line)); - if (i < footerLines.size() - 1) { - footer.append("\n"); - } - } + String header = formatLines(CONFIG_PATH + ".header", player); + String footer = formatLines(CONFIG_PATH + ".footer", player); player.sendPlayerListHeaderAndFooter( - Component.text(header.toString()), - Component.text(footer.toString()) + Component.text(header), + Component.text(footer) ); } + private String formatLines(String path, Player player) { + List lines = plugin.getConfig().getStringList(path); + return TextFormatter.joinLines(lines, player, "\n"); + } + private void updateAll() { - for (Player player : Bukkit.getOnlinePlayers()) { - updateTablist(player); - } + Bukkit.getOnlinePlayers().forEach(this::updateTablist); + } + + private boolean shouldRefresh() { + return plugin.getConfig().getBoolean(CONFIG_PATH + ".refresh.enabled", true); } } diff --git a/lohub/src/main/resources/commands.yml b/lohub/src/main/resources/commands.yml new file mode 100644 index 0000000..6d97226 --- /dev/null +++ b/lohub/src/main/resources/commands.yml @@ -0,0 +1,105 @@ +# ╔══════════════════════════════════════════════════════════════════════════════╗ +# ║ LoHub Custom Commands Configuration ║ +# ║ Create custom commands with actions ║ +# ╚══════════════════════════════════════════════════════════════════════════════╝ +# +# ACTIONS: +# [MESSAGE] text - Send message to player +# [BROADCAST] text - Broadcast to all players +# [TITLE] title;subtitle;fadeIn;stay;fadeOut - Send title +# [ACTIONBAR] text - Send actionbar message +# [SOUND] sound - Play sound +# [COMMAND] command - Execute as player +# [CONSOLE] command - Execute as console +# [GAMEMODE] mode - Change gamemode +# [EFFECT] effect;level - Give potion effect +# [CLOSE] - Close inventory +# +# PLACEHOLDERS: +# %player% - Player name +# %player_displayname% - Player display name +# %online% - Online players count +# %online_max% - Max players +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# +# | CUSTOM COMMANDS | +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# + +custom_commands: + # Discord command + discord: + aliases: + - discord + - дискорд + - ds + permission: null # null = no permission required + actions: + - "[MESSAGE] B59B6Discord: &#FFFFFFdiscord.example.net" + - "[SOUND] BLOCK_NOTE_BLOCK_PLING" + + # Website command + website: + aliases: + - website + - site + - сайт + - web + permission: null + actions: + - "[MESSAGE] �D4FFWebsite: &#FFFFFFwww.example.net" + - "[SOUND] BLOCK_NOTE_BLOCK_PLING" + + # Store command + store: + aliases: + - store + - shop + - магазин + - донат + permission: null + actions: + - "[MESSAGE] &#FF6B6BStore: &#FFFFFFstore.example.net" + - "[SOUND] BLOCK_NOTE_BLOCK_PLING" + + # Clear inventory command (admin only) + clearinventory: + aliases: + - ci + - clearinv + - очиститьинв + permission: lohub.admin + actions: + - "[CONSOLE] minecraft:clear %player%" + - "[MESSAGE] {prefix}BCB77Your inventory has been cleared!" + - "[SOUND] ENTITY_ITEM_PICKUP" + + # Heal command (admin only) + heal: + aliases: + - heal + - хил + permission: lohub.admin + actions: + - "[CONSOLE] minecraft:effect give %player% minecraft:instant_health 1 10 true" + - "[CONSOLE] minecraft:effect give %player% minecraft:saturation 1 10 true" + - "[MESSAGE] {prefix}BCB77You have been healed!" + - "[SOUND] ENTITY_PLAYER_LEVELUP" + + # Rules command + rules: + aliases: + - rules + - правила + permission: null + actions: + - "[MESSAGE] &r" + - "[MESSAGE] &#FFD700╔═══ Server Rules ═══╗" + - "[MESSAGE] &r" + - "[MESSAGE] BCB771. Be respectful to all players" + - "[MESSAGE] BCB772. No cheating or hacking" + - "[MESSAGE] BCB773. No spam in chat" + - "[MESSAGE] BCB774. Follow staff instructions" + - "[MESSAGE] BCB775. Have fun!" + - "[MESSAGE] &r" + - "[MESSAGE] &#FFD700╚═══════════════════════╝" + - "[SOUND] BLOCK_NOTE_BLOCK_PLING" diff --git a/lohub/src/main/resources/config.yml b/lohub/src/main/resources/config.yml index 7620319..c8eb24f 100644 --- a/lohub/src/main/resources/config.yml +++ b/lohub/src/main/resources/config.yml @@ -328,16 +328,14 @@ announcements: - "&#FFD700╚═══════════════════════╝" - "&r" +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# +# | CUSTOM COMMANDS | +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# +# All custom commands are now in commands.yml +# You can create custom commands with actions there + # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# # | MESSAGES | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# - -messages: - prefix: "�D4FF[�D4FFL�CAF7o�C0EEH�B7E6u�ADDDbcCC]" - spawn-set: "BCB77Spawn set successfully!" - spawn-teleport: "BCB77Teleporting to spawn..." - no-spawn: "&#FF6B6BSpawn not set! Use /sethub" - no-permission: "&#FF6B6BYou don't have permission!" - players-only: "&#FF6B6BThis command is only for players!" - config-reloaded: "BCB77Configuration reloaded!" - usage: "&#FFD700Usage: /lohub reload" +# All messages are now in messages.yml +# You can customize the plugin prefix and all messages there diff --git a/lohub/src/main/resources/data.yml b/lohub/src/main/resources/data.yml new file mode 100644 index 0000000..b34f190 --- /dev/null +++ b/lohub/src/main/resources/data.yml @@ -0,0 +1,17 @@ +# ╔══════════════════════════════════════════════════════════════════════════════╗ +# ║ LoHub Data Storage ║ +# ║ DO NOT EDIT THIS FILE MANUALLY! ║ +# ║ This file is automatically managed by the plugin ║ +# ╚══════════════════════════════════════════════════════════════════════════════╝ + +# Chat lock state +chat_locked: false + +# Spawn location (set via /sethub command) +spawn: + world: null + x: 0.0 + y: 0.0 + z: 0.0 + yaw: 0.0 + pitch: 0.0 diff --git a/lohub/src/main/resources/messages.yml b/lohub/src/main/resources/messages.yml new file mode 100644 index 0000000..4858018 --- /dev/null +++ b/lohub/src/main/resources/messages.yml @@ -0,0 +1,84 @@ +# ╔══════════════════════════════════════════════════════════════════════════════╗ +# ║ LoHub Messages Configuration ║ +# ║ All plugin messages in one place ║ +# ╚══════════════════════════════════════════════════════════════════════════════╝ + +# Plugin prefix (used in all messages with {prefix} placeholder) +prefix: "�D4FF[�D4FFL�CAF7o�C0EEH�B7E6u�ADDDbcCC] " + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# +# | GENERAL MESSAGES | +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# + +general: + no-permission: "{prefix}&#FF6B6BYou don't have permission!" + players-only: "{prefix}&#FF6B6BThis command is only for players!" + config-reloaded: "{prefix}BCB77Configuration reloaded!" + invalid-player: "{prefix}&#FF6B6BPlayer %player% not found!" + cooldown-active: "{prefix}&#FF6B6BPlease wait %time%s before using this again!" + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# +# | SPAWN MESSAGES | +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# + +spawn: + set: "{prefix}BCB77Spawn set successfully!" + teleport: "{prefix}BCB77Teleporting to spawn..." + no-spawn: "{prefix}&#FF6B6BSpawn not set! Use /sethub" + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# +# | CHAT LOCK MESSAGES | +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# + +chat: + locked: "{prefix}&#FF6B6BChat is currently locked!" + lock-enabled: "{prefix}BCB77Chat has been locked!" + lock-disabled: "{prefix}&#FF6B6BChat has been unlocked!" + lock-broadcast-enabled: "{prefix}&#FFD700%player% &#AAAAAAhas locked the chat!" + lock-broadcast-disabled: "{prefix}&#FFD700%player% &#AAAAAAhas unlocked the chat!" + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# +# | PLAYER HIDER MESSAGES | +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# + +player-hider: + hidden: "{prefix}&#FF6B6BPlayers are now hidden!" + shown: "{prefix}BCB77Players are now visible!" + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# +# | WORLD PROTECTION MESSAGES | +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# + +protection: + item-drop: "{prefix}&#FF6B6BYou cannot drop items here!" + item-pickup: "{prefix}&#FF6B6BYou cannot pickup items here!" + block-place: "{prefix}&#FF6B6BYou cannot place blocks here!" + block-break: "{prefix}&#FF6B6BYou cannot break blocks here!" + block-interact: "{prefix}&#FF6B6BYou cannot interact with this!" + player-pvp: "{prefix}&#FF6B6BPVP is disabled here!" + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# +# | DOUBLE JUMP MESSAGES | +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# + +double-jump: + cooldown: "{prefix}&#FF6B6BWait %time%s before double jumping again!" + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# +# | COMMAND MESSAGES | +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# + +commands: + usage-lohub: "{prefix}&#FFD700Usage: /lohub reload" + usage-hub: "{prefix}&#FFD700Usage: /hub" + usage-sethub: "{prefix}&#FFD700Usage: /sethub" + usage-chatlock: "{prefix}&#FFD700Usage: /chatlock" + command-blocked: "{prefix}&#FF6B6BThis command is blocked!" + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# +# | ANTI-SWEAR MESSAGES | +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# + +anti-swear: + blocked: "{prefix}&#FF6B6BYour message contains inappropriate language!" + admin-notify: "{prefix}&#FFD700%player% &#AAAAAAattempted to say: &#FF6B6B%word%" diff --git a/lohub/src/main/resources/plugin.yml b/lohub/src/main/resources/plugin.yml index 7d2717a..23c1066 100644 --- a/lohub/src/main/resources/plugin.yml +++ b/lohub/src/main/resources/plugin.yml @@ -27,6 +27,12 @@ commands: description: LoHub admin command usage: /lohub [reload] permission: lohub.admin + + chatlock: + description: Lock/unlock chat + usage: /chatlock + permission: lohub.chatlock + aliases: [ lockchat, чатлок ] permissions: lohub.hub: @@ -38,3 +44,9 @@ permissions: lohub.bypass.protection: description: Bypass world protection default: op + lohub.chatlock: + description: Can lock/unlock chat + default: op + lohub.chatlock.bypass: + description: Can bypass chat lock + default: op diff --git a/lohub/src/main/resources/serverselector.yml b/lohub/src/main/resources/serverselector.yml new file mode 100644 index 0000000..aaab081 --- /dev/null +++ b/lohub/src/main/resources/serverselector.yml @@ -0,0 +1,139 @@ +# ╔══════════════════════════════════════════════════════════════════════════════╗ +# ║ LoHub Server Selector Configuration ║ +# ║ GUI menu for server selection ║ +# ╚══════════════════════════════════════════════════════════════════════════════╝ +# +# This file defines the server selector GUI that players can open +# You can customize the items, layout, and actions +# +# ITEM ACTIONS: +# [MESSAGE] text - Send message to player +# [BROADCAST] text - Broadcast to all players +# [TITLE] title;subtitle;fadeIn;stay;fadeOut - Send title +# [ACTIONBAR] text - Send actionbar message +# [SOUND] sound - Play sound +# [COMMAND] command - Execute as player +# [CONSOLE] command - Execute as console +# [PROXY] server - Send player to BungeeCord/Velocity server +# [CLOSE] - Close inventory +# +# ITEM FLAGS: +# - HIDE_ATTRIBUTES +# - HIDE_DESTROYS +# - HIDE_ENCHANTS +# - HIDE_PLACED_ON +# - HIDE_POTION_EFFECTS +# - HIDE_UNBREAKABLE +# +# PLAYER HEADS: +# material: PLAYER_HEAD +# username: # OR +# base64: +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# +# | SERVER SELECTOR GUI | +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# + +# GUI settings +gui: + # Title of the inventory + title: "&#FFD700S&#FFC700e&#FFB700r&#FFA700v&#FF9700e&#FF8700r &#FF7700S&#FF6700e&#FF5700l&#FF4700e&#FF3700c&#FF2700t&#FF1700o&#FF0700r" + + # Number of rows (1-6, each row = 9 slots) + rows: 3 + + # Auto-update GUI (for placeholders) + refresh: + enabled: false + rate: 40 # In ticks (20 ticks = 1 second) + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# +# | GUI ITEMS | +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# + +items: + # Filler item (decorative glass) + filler: + material: GRAY_STAINED_GLASS_PANE + slot: -1 # -1 = fill all empty slots + amount: 1 + display_name: " " + item_flags: + - HIDE_ATTRIBUTES + + # Survival server + survival: + material: GRASS_BLOCK + slot: 11 + amount: 1 + glow: true + display_name: "BCB77S>C973uAC76Fr3C56Bv1C367i(C163v&BF5FaFBD5Bl" + lore: + - "" + - "&#AAAAAAClassic survival experience" + - "&#AAAAAABuild, mine, and survive!" + - "" + - "&#FFD700Click to join!" + actions: + - "[CLOSE]" + - "[MESSAGE] {prefix}BCB77Connecting to Survival..." + - "[SOUND] ENTITY_ENDERMAN_TELEPORT" + # For BungeeCord/Velocity: + # - "[PROXY] survival" + # For Multiverse-Core (multi-world): + # - "[CONSOLE] mvtp %player% survival_world" + + # Creative server + creative: + material: COMMAND_BLOCK + slot: 13 + amount: 1 + glow: true + display_name: "&#FF6B6BC&#FF5757r&#FF4343e&#FF2F2Fa&#FF1B1Bt&#FF0707i&#F30000v&#DF0000e" + lore: + - "" + - "&#AAAAAAUnlimited creativity!" + - "&#AAAAAABuild anything you imagine" + - "" + - "&#FFD700Click to join!" + actions: + - "[CLOSE]" + - "[MESSAGE] {prefix}&#FF6B6BConnecting to Creative..." + - "[SOUND] ENTITY_ENDERMAN_TELEPORT" + # For BungeeCord/Velocity: + # - "[PROXY] creative" + # For Multiverse-Core: + # - "[CONSOLE] mvtp %player% creative_world" + + # Minigames server + minigames: + material: DIAMOND_SWORD + slot: 15 + amount: 1 + glow: true + display_name: " B59B6ME4FB0iῑAAnA3BA4iD319Eg򓚖aȔD92m񰸵e餝Fs" + lore: + - "" + - "&#AAAAAAFun minigames and competitions" + - "&#AAAAAAPlay with friends!" + - "" + - "&#FFD700Click to join!" + actions: + - "[CLOSE]" + - "[MESSAGE] {prefix} B59B6Connecting to Minigames..." + - "[SOUND] ENTITY_ENDERMAN_TELEPORT" + # For BungeeCord/Velocity: + # - "[PROXY] minigames" + + # Close button + close: + material: BARRIER + slot: 22 + amount: 1 + display_name: "&#FF6B6BClose" + lore: + - "" + - "&#AAAAAAClick to close this menu" + actions: + - "[CLOSE]" + - "[SOUND] BLOCK_CHEST_CLOSE" diff --git a/src/main/java/com/loki/lochat/core/service/MuteHistoryManager.java b/src/main/java/com/loki/lochat/core/service/MuteHistoryManager.java new file mode 100644 index 0000000..79462c2 --- /dev/null +++ b/src/main/java/com/loki/lochat/core/service/MuteHistoryManager.java @@ -0,0 +1,81 @@ +package com.loki.lochat.core.service; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.reflect.TypeToken; +import com.loki.lochat.data.model.MuteData; + +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +public class MuteHistoryManager { + + private final Map> history = new ConcurrentHashMap<>(); + private final File historyFile; + private final Gson gson = new GsonBuilder().setPrettyPrinting().create(); + + public MuteHistoryManager(File historyFile) { + this.historyFile = historyFile; + load(); + } + + public void addEntry(UUID uuid, String playerName, long duration, String reason, String mutedBy) { + List entries = history.computeIfAbsent(uuid, k -> new ArrayList<>()); + entries.add(new MuteData.MuteHistoryEntry( + playerName, + duration, + reason, + mutedBy, + System.currentTimeMillis(), + false, + null, + 0 + )); + } + + public void updateUnmute(UUID uuid, String unmutedBy) { + List entries = history.get(uuid); + if (entries != null && !entries.isEmpty()) { + MuteData.MuteHistoryEntry lastEntry = entries.get(entries.size() - 1); + if (lastEntry.unmutedBy == null) { + lastEntry.unmuted = true; + lastEntry.unmutedBy = unmutedBy; + lastEntry.unmutedAt = System.currentTimeMillis(); + } + } + } + + public List getHistory(UUID uuid) { + return history.getOrDefault(uuid, Collections.emptyList()); + } + + public void save() { + try (FileWriter writer = new FileWriter(historyFile)) { + gson.toJson(history, writer); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void load() { + if (!historyFile.exists()) { + return; + } + + try (FileReader reader = new FileReader(historyFile)) { + Type type = new TypeToken>>() { + }.getType(); + Map> loaded = gson.fromJson(reader, type); + if (loaded != null) { + history.putAll(loaded); + } + } catch (IOException e) { + e.printStackTrace(); + } + } +} 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 4422fb8..dc6d4b1 100644 --- a/src/main/java/com/loki/lochat/core/service/MuteServiceImpl.java +++ b/src/main/java/com/loki/lochat/core/service/MuteServiceImpl.java @@ -6,6 +6,7 @@ import com.google.gson.reflect.TypeToken; import com.loki.lochat.api.service.MuteService; import com.loki.lochat.data.model.MuteData; import com.loki.lochat.gradient.util.FoliaUtil; +import com.loki.lochat.utils.TimeFormatter; import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; @@ -14,23 +15,19 @@ import java.lang.reflect.Type; import java.util.*; import java.util.concurrent.ConcurrentHashMap; -/** - * Реализация сервиса мутов - */ public class MuteServiceImpl implements MuteService { + private final JavaPlugin plugin; private final Map mutes = new ConcurrentHashMap<>(); - private final Map> history = new ConcurrentHashMap<>(); + private final MuteHistoryManager historyManager; 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"); - this.historyFile = new File(plugin.getDataFolder(), "mute-history.json"); + this.historyManager = new MuteHistoryManager(new File(plugin.getDataFolder(), "mute-history.json")); load(); - loadHistory(); } @Override @@ -39,9 +36,7 @@ public class MuteServiceImpl implements MuteService { MuteData data = new MuteData(uuid, playerName, endTime, reason, mutedBy); mutes.put(uuid, data); - // Добавляем в историю - addToHistory(uuid, playerName, duration, reason, mutedBy); - + historyManager.addEntry(uuid, playerName, duration, reason, mutedBy); saveAsync(); } @@ -49,7 +44,7 @@ public class MuteServiceImpl implements MuteService { public boolean unmute(UUID uuid, String unmutedBy) { MuteData removed = mutes.remove(uuid); if (removed != null) { - updateHistoryUnmute(uuid, unmutedBy); + historyManager.updateUnmute(uuid, unmutedBy); saveAsync(); return true; } @@ -59,9 +54,11 @@ public class MuteServiceImpl implements MuteService { @Override public boolean isMuted(UUID uuid) { MuteData data = mutes.get(uuid); - if (data == null) return false; + if (data == null) { + return false; + } - if (data.getEndTime() > 0 && System.currentTimeMillis() > data.getEndTime()) { + if (isExpired(data)) { mutes.remove(uuid); saveAsync(); return false; @@ -71,66 +68,35 @@ public class MuteServiceImpl implements MuteService { @Override public MuteData getMuteData(UUID uuid) { - if (!isMuted(uuid)) return null; - return mutes.get(uuid); + return isMuted(uuid) ? mutes.get(uuid) : null; } @Override public long getRemainingTime(UUID uuid) { MuteData data = mutes.get(uuid); - if (data == null) return 0; - if (data.getEndTime() == 0) return -1; // Перманентный + if (data == null) { + return 0; + } + 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) { - return hours + "ч " + (minutes % 60) + "м"; - } else if (minutes > 0) { - return minutes + "м " + (seconds % 60) + "с"; - } else { - return seconds + "с"; - } + return TimeFormatter.format(millis); } @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; - } else if (timeStr.endsWith("h")) { - return Long.parseLong(timeStr.replace("h", "")) * 60 * 60 * multiplier; - } else if (timeStr.endsWith("m")) { - return Long.parseLong(timeStr.replace("m", "")) * 60 * multiplier; - } else if (timeStr.endsWith("s")) { - return Long.parseLong(timeStr.replace("s", "")) * multiplier; - } else { - return Long.parseLong(timeStr) * 60 * multiplier; - } - } catch (NumberFormatException e) { - return -1; - } + return TimeFormatter.parse(timeStr); } @Override public long getMaxDuration(Player player) { if (player.hasPermission("lochat.mute.dur.perm")) { - return 0; // Перманентный + return 0; } String[] durations = {"30d", "14d", "7d", "3d", "1d", "12h", "6h", "1h", "30m", "10m"}; @@ -140,7 +106,7 @@ public class MuteServiceImpl implements MuteService { } } - return -1; // Нет прав + return -1; } @Override @@ -154,37 +120,39 @@ public class MuteServiceImpl implements MuteService { } long maxDuration = getMaxDuration(player); - if (maxDuration == -1) return false; - if (maxDuration == 0) return true; + 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<>()); + return historyManager.getHistory(uuid); } @Override public List getMutesByOperator(String operatorName) { List result = new ArrayList<>(); - for (List playerHistory : history.values()) { - for (MuteData.MuteHistoryEntry entry : playerHistory) { - if (entry.mutedBy != null && entry.mutedBy.equalsIgnoreCase(operatorName)) { - result.add(entry); - } - } - } + mutes.keySet().forEach(uuid -> { + historyManager.getHistory(uuid).stream() + .filter(entry -> entry.mutedBy != null && entry.mutedBy.equalsIgnoreCase(operatorName)) + .forEach(result::add); + }); result.sort((a, b) -> Long.compare(b.mutedAt, a.mutedAt)); return result; } @Override public UUID getUUIDByName(String name) { - for (Map.Entry> entry : history.entrySet()) { - for (MuteData.MuteHistoryEntry historyEntry : entry.getValue()) { - if (historyEntry.playerName != null && historyEntry.playerName.equalsIgnoreCase(name)) { - return entry.getKey(); + for (UUID uuid : mutes.keySet()) { + for (MuteData.MuteHistoryEntry entry : historyManager.getHistory(uuid)) { + if (entry.playerName != null && entry.playerName.equalsIgnoreCase(name)) { + return uuid; } } } @@ -193,10 +161,7 @@ public class MuteServiceImpl implements MuteService { @Override public Map getActiveMutes() { - mutes.entrySet().removeIf(entry -> { - MuteData data = entry.getValue(); - return data.getEndTime() > 0 && System.currentTimeMillis() > data.getEndTime(); - }); + mutes.entrySet().removeIf(entry -> isExpired(entry.getValue())); return new HashMap<>(mutes); } @@ -212,23 +177,37 @@ public class MuteServiceImpl implements MuteService { @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); - } + ensureDataFolderExists(); + saveMutes(); + historyManager.save(); } catch (IOException e) { - plugin.getLogger().warning("Ошибка сохранения мутов: " + e.getMessage()); + plugin.getLogger().warning("Error saving mutes: " + e.getMessage()); + } + } + + private boolean isExpired(MuteData data) { + return data.getEndTime() > 0 && System.currentTimeMillis() > data.getEndTime(); + } + + private void ensureDataFolderExists() { + if (!dataFile.getParentFile().exists()) { + dataFile.getParentFile().mkdirs(); + } + } + + private void saveMutes() throws IOException { + Map toSave = new ConcurrentHashMap<>(); + mutes.forEach((uuid, data) -> toSave.put(uuid.toString(), data)); + + try (Writer writer = new FileWriter(dataFile)) { + gson.toJson(toSave, writer); } } private void load() { - if (!dataFile.exists()) return; + if (!dataFile.exists()) { + return; + } try (Reader reader = new FileReader(dataFile)) { Type type = new TypeToken>() { @@ -243,86 +222,11 @@ public class MuteServiceImpl implements MuteService { }); } } catch (IOException e) { - plugin.getLogger().warning("Ошибка загрузки мутов: " + e.getMessage()); + plugin.getLogger().warning("Error loading mutes: " + e.getMessage()); } } - private void loadHistory() { - if (!historyFile.exists()) return; - - try (Reader reader = new FileReader(historyFile)) { - 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 (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); - } - } catch (IOException e) { - 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( - playerName, - duration, - reason, - mutedBy, - System.currentTimeMillis(), - false, - null, - 0 - )); - saveHistoryAsync(); - } - - private void updateHistoryUnmute(UUID uuid, String unmutedBy) { - List playerHistory = history.get(uuid); - if (playerHistory != null && !playerHistory.isEmpty()) { - for (int i = playerHistory.size() - 1; i >= 0; i--) { - MuteData.MuteHistoryEntry entry = playerHistory.get(i); - if (!entry.unmuted) { - entry.unmuted = true; - entry.unmutedBy = unmutedBy; - entry.unmutedAt = System.currentTimeMillis(); - break; - } - } - } - saveHistoryAsync(); - } - - private void saveHistoryAsync() { - FoliaUtil.runAsync(plugin, this::saveHistory); - } - private void saveAsync() { - FoliaUtil.runAsync(plugin, () -> { - save(); - saveHistory(); - }); + FoliaUtil.runAsync(plugin, this::save); } } diff --git a/src/main/java/com/loki/lochat/utils/TimeFormatter.java b/src/main/java/com/loki/lochat/utils/TimeFormatter.java new file mode 100644 index 0000000..a5c12ee --- /dev/null +++ b/src/main/java/com/loki/lochat/utils/TimeFormatter.java @@ -0,0 +1,59 @@ +package com.loki.lochat.utils; + +public final class TimeFormatter { + + private TimeFormatter() { + } + + 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) { + return hours + "ч " + (minutes % 60) + "м"; + } else if (minutes > 0) { + return minutes + "м " + (seconds % 60) + "с"; + } else { + return seconds + "с"; + } + } + + public static long parse(String timeStr) { + if (timeStr == null || timeStr.isEmpty()) { + return 0; + } + + long totalMillis = 0; + StringBuilder number = new StringBuilder(); + + for (char c : timeStr.toCharArray()) { + if (Character.isDigit(c)) { + number.append(c); + } else if (number.length() > 0) { + long value = Long.parseLong(number.toString()); + totalMillis += getMillisForUnit(c, value); + number.setLength(0); + } + } + + return totalMillis; + } + + private static long getMillisForUnit(char unit, long value) { + return switch (Character.toLowerCase(unit)) { + case 's', 'с' -> value * 1000; + case 'm', 'м' -> value * 60 * 1000; + case 'h', 'ч' -> value * 60 * 60 * 1000; + case 'd', 'д' -> value * 24 * 60 * 60 * 1000; + default -> 0; + }; + } +}