diff --git a/TODO.md b/TODO.md index 9846635..c3783bf 100644 --- a/TODO.md +++ b/TODO.md @@ -20,7 +20,7 @@ --- ### 2. LoHub - Hub плагин (Paper/Folia) -**Статус:** 🔄 В разработке (21% готово) +**Статус:** ✅ Готов к использованию (100% готово) #### ✅ Готово - ✅ Spawn система с телепортом @@ -28,49 +28,62 @@ - ✅ Защита мира (блоки, PvP, мобы) - ✅ Команды /hub, /sethub, /lohub - ✅ Базовые утилиты (ItemBuilder, TextUtil, PlaceholderUtil) +- ✅ **ЭТАП 2: Action система** + - ✅ Action интерфейс и ActionType enum + - ✅ MessageAction, BroadcastAction, TitleAction, ActionbarAction + - ✅ SoundAction, CommandAction, ConsoleAction + - ✅ GamemodeAction, EffectAction, CloseAction + - ✅ ActionManager с regex парсингом +- ✅ **ЭТАП 3: Join система** + - ✅ PlayerJoinListener (join/quit/respawn/death) + - ✅ Телепорт на спавн при входе + - ✅ Хил и очистка эффектов + - ✅ Кастомные сообщения входа/выхода + - ✅ Фейерверки при первом входе + - ✅ Интеграция с Action системой +- ✅ **ЭТАП 4: Custom Join Items** + - ✅ HotbarManager - управление предметами + - ✅ Выдача предметов при входе + - ✅ HotbarListener - обработка кликов + - ✅ Защита от выбрасывания предметов + - ✅ Интеграция с Action системой +- ✅ **ЭТАП 5: Launchpad** + - ✅ LaunchpadListener - прыжковые площадки + - ✅ Проверка блоков (плита + редстоун) + - ✅ Настраиваемая сила прыжка + - ✅ Интеграция с Action системой +- ✅ **ЭТАП 6: Double Jump** + - ✅ DoubleJumpListener - двойной прыжок + - ✅ Интеграция с CooldownManager + - ✅ Настраиваемая сила и кулдаун + - ✅ Интеграция с Action системой +- ✅ **ЭТАП 7: Player Hider** + - ✅ PlayerHiderManager - управление видимостью + - ✅ Скрытие/показ игроков + - ✅ Предмет для переключения + - ✅ Кулдаун на использование +- ✅ **ЭТАП 8: Scoreboard** + - ✅ ScoreboardManager - управление скорбордом + - ✅ Настраиваемый заголовок и строки + - ✅ Автообновление с настраиваемым интервалом + - ✅ PlaceholderAPI интеграция +- ✅ **ЭТАП 9: Tablist** + - ✅ TablistManager - управление табом + - ✅ Настраиваемый header и footer + - ✅ Автообновление с настраиваемым интервалом + - ✅ PlaceholderAPI интеграция +- ✅ **ЭТАП 10: Announcements** + - ✅ AnnouncementManager - система объявлений + - ✅ Множественные объявления с ротацией + - ✅ Настраиваемый интервал и звук + - ✅ Минимальное количество игроков + - ✅ PlaceholderAPI интеграция -#### 🔄 В работе - ЭТАП 2: Action система -- [ ] Action интерфейс и ActionType enum -- [ ] MessageAction - отправка сообщений -- [ ] SoundAction - звуки -- [ ] TitleAction - title/subtitle -- [ ] CommandAction - команды от игрока -- [ ] ConsoleAction - команды от консоли -- [ ] GamemodeAction - смена режима -- [ ] EffectAction - эффекты -- [ ] ActionManager - парсинг и выполнение - -#### 📋 Запланировано -**ЭТАП 3: Join система** -- [ ] PlayerJoinListener -- [ ] Телепорт на спавн при входе -- [ ] Хил и очистка эффектов -- [ ] Кастомные сообщения входа/выхода -- [ ] Интеграция с Action системой - -**ЭТАП 4: Custom Join Items** -- [ ] HotbarManager -- [ ] Выдача предметов при входе -- [ ] Обработка кликов (actions) -- [ ] Защита от выбрасывания - -**ЭТАП 5: Launchpad** -- [ ] LaunchpadListener -- [ ] Прыжковые площадки (плита + редстоун) - -**ЭТАП 6: Double Jump** -- [ ] DoubleJumpListener -- [ ] CooldownManager -- [ ] Двойной прыжок в воздухе - -**ЭТАП 7: Player Hider** -- [ ] PlayerHiderManager -- [ ] Скрытие/показ игроков -- [ ] Предмет для переключения - -**ЭТАП 8-10: Опционально** -- [ ] Scoreboard модуль -- [ ] Tablist модуль +#### 📋 Дополнительно +- Все основные функции реализованы +- Конфигурация полностью настраиваема через config.yml +- Поддержка PlaceholderAPI для всех текстовых элементов +- Команда /lohub reload для перезагрузки конфигурации - [ ] Announcements модуль --- diff --git a/lohub/src/main/java/com/loki/lohub/LoHub.java b/lohub/src/main/java/com/loki/lohub/LoHub.java index e5661bd..e619d84 100644 --- a/lohub/src/main/java/com/loki/lohub/LoHub.java +++ b/lohub/src/main/java/com/loki/lohub/LoHub.java @@ -4,9 +4,14 @@ import com.loki.lohub.config.ConfigManager; 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.CooldownManager; +import com.loki.lohub.managers.HotbarManager; +import com.loki.lohub.managers.PlayerHiderManager; import com.loki.lohub.managers.RegionManager; +import com.loki.lohub.managers.ScoreboardManager; import com.loki.lohub.managers.SpawnManager; +import com.loki.lohub.managers.TablistManager; import com.loki.lohub.utils.PlaceholderUtil; import org.bukkit.plugin.java.JavaPlugin; @@ -17,6 +22,11 @@ public class LoHub extends JavaPlugin { private RegionManager regionManager; private ActionManager actionManager; private CooldownManager cooldownManager; + private HotbarManager hotbarManager; + private PlayerHiderManager playerHiderManager; + private ScoreboardManager scoreboardManager; + private TablistManager tablistManager; + private AnnouncementManager announcementManager; @Override public void onEnable() { @@ -31,23 +41,38 @@ public class LoHub extends JavaPlugin { this.regionManager = new RegionManager(this); this.actionManager = new ActionManager(this); this.cooldownManager = new CooldownManager(); + this.hotbarManager = new HotbarManager(this); + this.playerHiderManager = new PlayerHiderManager(this); + this.scoreboardManager = new ScoreboardManager(this); + this.tablistManager = new TablistManager(this); + this.announcementManager = new AnnouncementManager(this); registerListeners(); registerCommands(); regionManager.createHubRegion(); + scoreboardManager.start(); + tablistManager.start(); + announcementManager.start(); + getLogger().info("LoHub successfully loaded!"); } @Override public void onDisable() { + scoreboardManager.stop(); + tablistManager.stop(); + announcementManager.stop(); getLogger().info("LoHub disabled!"); } private void registerListeners() { getServer().getPluginManager().registerEvents(new HubProtectionListener(this), this); getServer().getPluginManager().registerEvents(new PlayerJoinListener(this), this); + 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); } private void registerCommands() { @@ -75,4 +100,24 @@ public class LoHub extends JavaPlugin { public CooldownManager getCooldownManager() { return cooldownManager; } + + public HotbarManager getHotbarManager() { + return hotbarManager; + } + + public PlayerHiderManager getPlayerHiderManager() { + return playerHiderManager; + } + + public ScoreboardManager getScoreboardManager() { + return scoreboardManager; + } + + public TablistManager getTablistManager() { + return tablistManager; + } + + public AnnouncementManager getAnnouncementManager() { + return announcementManager; + } } 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 4e8fcc1..2a8906c 100644 --- a/lohub/src/main/java/com/loki/lohub/commands/LoHubCommand.java +++ b/lohub/src/main/java/com/loki/lohub/commands/LoHubCommand.java @@ -29,6 +29,12 @@ public class LoHubCommand implements CommandExecutor { if (args[0].equalsIgnoreCase("reload")) { plugin.getConfigManager().reload(); + plugin.getHotbarManager().reload(); + plugin.getAnnouncementManager().reload(); + plugin.getScoreboardManager().stop(); + plugin.getTablistManager().stop(); + plugin.getScoreboardManager().start(); + plugin.getTablistManager().start(); sender.sendMessage(TextUtil.colorize("&aConfiguration reloaded!")); return true; } diff --git a/lohub/src/main/java/com/loki/lohub/listeners/DoubleJumpListener.java b/lohub/src/main/java/com/loki/lohub/listeners/DoubleJumpListener.java new file mode 100644 index 0000000..9e0fece --- /dev/null +++ b/lohub/src/main/java/com/loki/lohub/listeners/DoubleJumpListener.java @@ -0,0 +1,80 @@ +package com.loki.lohub.listeners; + +import com.loki.lohub.LoHub; +import org.bukkit.GameMode; +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 final LoHub plugin; + + public DoubleJumpListener(LoHub plugin) { + this.plugin = plugin; + } + + @EventHandler + public void onPlayerMove(PlayerMoveEvent event) { + if (!plugin.getConfig().getBoolean("double_jump.enabled", true)) { + return; + } + + Player player = event.getPlayer(); + + if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.SPECTATOR) { + return; + } + + if (!player.isOnGround() && !player.getAllowFlight()) { + player.setAllowFlight(true); + } else if (player.isOnGround() && player.getAllowFlight()) { + player.setAllowFlight(false); + player.setFlying(false); + } + } + + @EventHandler + public void onPlayerToggleFlight(PlayerToggleFlightEvent event) { + if (!plugin.getConfig().getBoolean("double_jump.enabled", true)) { + return; + } + + Player player = event.getPlayer(); + + if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.SPECTATOR) { + return; + } + + if (plugin.getCooldownManager().hasCooldown("double_jump", player.getUniqueId())) { + event.setCancelled(true); + player.setAllowFlight(false); + player.setFlying(false); + return; + } + + 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); + + Vector velocity = player.getLocation().getDirection().multiply(power); + velocity.setY(powerY); + player.setVelocity(velocity); + + int cooldown = plugin.getConfig().getInt("double_jump.cooldown", 3); + plugin.getCooldownManager().setCooldown("double_jump", player.getUniqueId(), cooldown); + + List actions = plugin.getConfig().getStringList("double_jump.actions"); + if (!actions.isEmpty()) { + plugin.getActionManager().executeActions(player, actions, false); + } + } +} diff --git a/lohub/src/main/java/com/loki/lohub/listeners/HotbarListener.java b/lohub/src/main/java/com/loki/lohub/listeners/HotbarListener.java new file mode 100644 index 0000000..57fedaa --- /dev/null +++ b/lohub/src/main/java/com/loki/lohub/listeners/HotbarListener.java @@ -0,0 +1,58 @@ +package com.loki.lohub.listeners; + +import com.loki.lohub.LoHub; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerDropItemEvent; +import org.bukkit.event.player.PlayerInteractEvent; + +public class HotbarListener implements Listener { + + private final LoHub plugin; + + public HotbarListener(LoHub plugin) { + this.plugin = plugin; + } + + @EventHandler + public void onPlayerInteract(PlayerInteractEvent event) { + if (event.getAction() != Action.RIGHT_CLICK_AIR && event.getAction() != Action.RIGHT_CLICK_BLOCK) { + return; + } + + Player player = event.getPlayer(); + int slot = player.getInventory().getHeldItemSlot(); + + if (plugin.getPlayerHiderManager().isPlayerHiderSlot(slot)) { + event.setCancelled(true); + + if (plugin.getCooldownManager().hasCooldown("player_hider", player.getUniqueId())) { + return; + } + + int cooldown = plugin.getConfig().getInt("player_hider.cooldown", 3); + plugin.getCooldownManager().setCooldown("player_hider", player.getUniqueId(), cooldown); + + plugin.getPlayerHiderManager().toggle(player); + } else if (plugin.getHotbarManager().isHotbarItem(slot)) { + event.setCancelled(true); + plugin.getHotbarManager().handleClick(player, slot); + } + } + + @EventHandler + public void onPlayerDropItem(PlayerDropItemEvent event) { + if (!plugin.getConfig().getBoolean("custom_join_items.disable_inventory_movement", true)) { + return; + } + + Player player = event.getPlayer(); + int slot = player.getInventory().getHeldItemSlot(); + + if (plugin.getHotbarManager().isHotbarItem(slot) || plugin.getPlayerHiderManager().isPlayerHiderSlot(slot)) { + 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 new file mode 100644 index 0000000..288ec27 --- /dev/null +++ b/lohub/src/main/java/com/loki/lohub/listeners/LaunchpadListener.java @@ -0,0 +1,68 @@ +package com.loki.lohub.listeners; + +import com.loki.lohub.LoHub; +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 final LoHub plugin; + + public LaunchpadListener(LoHub plugin) { + this.plugin = plugin; + } + + @EventHandler + public void onPlayerMove(PlayerMoveEvent event) { + if (!plugin.getConfig().getBoolean("launchpad.enabled", true)) { + return; + } + + if (event.getFrom().getBlockX() == event.getTo().getBlockX() + && event.getFrom().getBlockY() == event.getTo().getBlockY() + && event.getFrom().getBlockZ() == event.getTo().getBlockZ()) { + 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); + } + } + } + + 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); + + Vector velocity = player.getLocation().getDirection().multiply(power); + velocity.setY(powerY); + player.setVelocity(velocity); + + List actions = plugin.getConfig().getStringList("launchpad.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 ff5c775..7c6049d 100644 --- a/lohub/src/main/java/com/loki/lohub/listeners/PlayerJoinListener.java +++ b/lohub/src/main/java/com/loki/lohub/listeners/PlayerJoinListener.java @@ -65,6 +65,9 @@ public class PlayerJoinListener implements Listener { handleJoinSettings(player); handleJoinEvents(player); handleFirework(player); + + plugin.getScoreboardManager().setScoreboard(player, true); + plugin.getTablistManager().setTablist(player); } @EventHandler(priority = EventPriority.HIGHEST) @@ -75,6 +78,9 @@ public class PlayerJoinListener implements Listener { return; } + 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()) { @@ -144,6 +150,9 @@ public class PlayerJoinListener implements Listener { 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) { diff --git a/lohub/src/main/java/com/loki/lohub/managers/AnnouncementManager.java b/lohub/src/main/java/com/loki/lohub/managers/AnnouncementManager.java new file mode 100644 index 0000000..22b2485 --- /dev/null +++ b/lohub/src/main/java/com/loki/lohub/managers/AnnouncementManager.java @@ -0,0 +1,108 @@ +package com.loki.lohub.managers; + +import com.loki.lohub.LoHub; +import com.loki.lohub.utils.PlaceholderUtil; +import com.loki.lohub.utils.TextUtil; +import net.kyori.adventure.text.Component; +import org.bukkit.Bukkit; +import org.bukkit.Sound; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.List; + +public class AnnouncementManager { + + private final LoHub plugin; + private final List announcements = new ArrayList<>(); + private int currentIndex = 0; + private int taskId = -1; + + public AnnouncementManager(LoHub plugin) { + this.plugin = plugin; + loadAnnouncements(); + } + + private void loadAnnouncements() { + announcements.clear(); + ConfigurationSection section = plugin.getConfig().getConfigurationSection("announcements.announcements"); + if (section == null) { + return; + } + + for (String key : section.getKeys(false)) { + List messages = section.getStringList(key); + if (!messages.isEmpty()) { + announcements.add(new Announcement(key, messages)); + } + } + } + + public void start() { + if (!plugin.getConfig().getBoolean("announcements.enabled", false)) { + return; + } + + if (announcements.isEmpty()) { + return; + } + + int delay = plugin.getConfig().getInt("announcements.delay", 60) * 20; + taskId = Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, this::broadcast, delay, delay); + } + + public void stop() { + if (taskId != -1) { + Bukkit.getScheduler().cancelTask(taskId); + taskId = -1; + } + } + + private void broadcast() { + int requiredPlayers = plugin.getConfig().getInt("announcements.required_players", 1); + if (Bukkit.getOnlinePlayers().size() < requiredPlayers) { + return; + } + + if (announcements.isEmpty()) { + return; + } + + Announcement announcement = announcements.get(currentIndex); + currentIndex = (currentIndex + 1) % announcements.size(); + + for (Player player : Bukkit.getOnlinePlayers()) { + for (String message : announcement.messages()) { + String formatted = PlaceholderUtil.parse(message, player); + player.sendMessage(Component.text(TextUtil.colorize(formatted))); + } + + if (plugin.getConfig().getBoolean("announcements.sound.enabled", true)) { + playSound(player); + } + } + } + + 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); + + try { + Sound sound = Sound.valueOf(soundStr); + player.playSound(player.getLocation(), sound, volume, pitch); + } catch (IllegalArgumentException e) { + plugin.getLogger().warning("Invalid sound: " + soundStr); + } + } + + public void reload() { + stop(); + loadAnnouncements(); + start(); + } + + private record Announcement(String name, List messages) { + } +} diff --git a/lohub/src/main/java/com/loki/lohub/managers/HotbarManager.java b/lohub/src/main/java/com/loki/lohub/managers/HotbarManager.java new file mode 100644 index 0000000..eab448b --- /dev/null +++ b/lohub/src/main/java/com/loki/lohub/managers/HotbarManager.java @@ -0,0 +1,87 @@ +package com.loki.lohub.managers; + +import com.loki.lohub.LoHub; +import com.loki.lohub.utils.ItemBuilder; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class HotbarManager { + + private final LoHub plugin; + private final Map items = new HashMap<>(); + + public HotbarManager(LoHub plugin) { + this.plugin = plugin; + loadItems(); + } + + private void loadItems() { + items.clear(); + ConfigurationSection section = plugin.getConfig().getConfigurationSection("custom_join_items.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)); + } + } + + public void giveItems(Player player) { + if (!plugin.getConfig().getBoolean("custom_join_items.enabled", false)) { + return; + } + + for (Map.Entry entry : items.entrySet()) { + player.getInventory().setItem(entry.getKey(), entry.getValue().item()); + } + } + + public void handleClick(Player player, int slot) { + HotbarItem item = items.get(slot); + if (item == null) { + return; + } + + plugin.getActionManager().executeActions(player, item.actions(), false); + } + + public boolean isHotbarItem(int slot) { + return items.containsKey(slot); + } + + public void reload() { + loadItems(); + } + + 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 new file mode 100644 index 0000000..74cf01b --- /dev/null +++ b/lohub/src/main/java/com/loki/lohub/managers/PlayerHiderManager.java @@ -0,0 +1,94 @@ +package com.loki.lohub.managers; + +import com.loki.lohub.LoHub; +import com.loki.lohub.utils.ItemBuilder; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.UUID; + +public class PlayerHiderManager { + + private final LoHub plugin; + private final Set hiddenPlayers = new HashSet<>(); + + public PlayerHiderManager(LoHub plugin) { + this.plugin = plugin; + } + + public void giveItem(Player player) { + if (!plugin.getConfig().getBoolean("player_hider.enabled", true)) { + return; + } + + int slot = plugin.getConfig().getInt("player_hider.slot", 8); + player.getInventory().setItem(slot, 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; + } + + int amount = plugin.getConfig().getInt(path + ".amount", 1); + String displayName = plugin.getConfig().getString(path + ".display_name", ""); + List lore = plugin.getConfig().getStringList(path + ".lore"); + + return new ItemBuilder(material) + .amount(amount) + .name(displayName) + .lore(lore) + .build(); + } + + public void toggle(Player player) { + if (hiddenPlayers.contains(player.getUniqueId())) { + showPlayers(player); + } else { + hidePlayers(player); + } + + updateItem(player); + } + + private void hidePlayers(Player player) { + hiddenPlayers.add(player.getUniqueId()); + for (Player online : Bukkit.getOnlinePlayers()) { + if (!online.equals(player)) { + player.hidePlayer(plugin, online); + } + } + } + + private void showPlayers(Player player) { + hiddenPlayers.remove(player.getUniqueId()); + for (Player online : Bukkit.getOnlinePlayers()) { + if (!online.equals(player)) { + player.showPlayer(plugin, online); + } + } + } + + private void updateItem(Player player) { + int slot = plugin.getConfig().getInt("player_hider.slot", 8); + player.getInventory().setItem(slot, getItem(player)); + } + + public boolean isPlayerHiderSlot(int slot) { + return plugin.getConfig().getBoolean("player_hider.enabled", true) + && slot == plugin.getConfig().getInt("player_hider.slot", 8); + } + + public void removePlayer(Player player) { + hiddenPlayers.remove(player.getUniqueId()); + } +} diff --git a/lohub/src/main/java/com/loki/lohub/managers/ScoreboardManager.java b/lohub/src/main/java/com/loki/lohub/managers/ScoreboardManager.java new file mode 100644 index 0000000..29a114e --- /dev/null +++ b/lohub/src/main/java/com/loki/lohub/managers/ScoreboardManager.java @@ -0,0 +1,112 @@ +package com.loki.lohub.managers; + +import com.loki.lohub.LoHub; +import com.loki.lohub.utils.PlaceholderUtil; +import com.loki.lohub.utils.TextUtil; +import net.kyori.adventure.text.Component; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.scoreboard.DisplaySlot; +import org.bukkit.scoreboard.Objective; +import org.bukkit.scoreboard.Scoreboard; +import org.bukkit.scoreboard.Team; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public class ScoreboardManager { + + private final LoHub plugin; + private final Map scoreboards = new HashMap<>(); + private int taskId = -1; + + public ScoreboardManager(LoHub plugin) { + this.plugin = plugin; + } + + public void start() { + if (!plugin.getConfig().getBoolean("scoreboard.enabled", false)) { + return; + } + + if (plugin.getConfig().getBoolean("scoreboard.refresh.enabled", true)) { + int rate = plugin.getConfig().getInt("scoreboard.refresh.rate", 200); + taskId = Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, this::updateAll, 0L, rate); + } + } + + public void stop() { + if (taskId != -1) { + Bukkit.getScheduler().cancelTask(taskId); + taskId = -1; + } + scoreboards.clear(); + } + + public void setScoreboard(Player player, boolean delayed) { + if (!plugin.getConfig().getBoolean("scoreboard.enabled", false)) { + return; + } + + if (delayed) { + int delay = plugin.getConfig().getInt("scoreboard.display_delay.server_enter", 60); + Bukkit.getScheduler().runTaskLater(plugin, () -> createScoreboard(player), delay); + } else { + createScoreboard(player); + } + } + + private void createScoreboard(Player player) { + Scoreboard scoreboard = Bukkit.getScoreboardManager().getNewScoreboard(); + Objective objective = scoreboard.registerNewObjective("lohub", "dummy", Component.text("")); + + objective.setDisplaySlot(DisplaySlot.SIDEBAR); + updateScoreboard(player, scoreboard, objective); + + player.setScoreboard(scoreboard); + scoreboards.put(player.getUniqueId(), scoreboard); + } + + 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))); + + List lines = plugin.getConfig().getStringList("scoreboard.lines"); + int score = lines.size(); + + for (String line : lines) { + line = PlaceholderUtil.parse(line, player); + line = TextUtil.colorize(line); + + String teamName = "line_" + score; + Team team = scoreboard.getTeam(teamName); + if (team == null) { + team = scoreboard.registerNewTeam(teamName); + team.addEntry(teamName); + } + + team.prefix(Component.text(line)); + objective.getScore(teamName).setScore(score); + score--; + } + } + + private void updateAll() { + for (Player player : Bukkit.getOnlinePlayers()) { + Scoreboard scoreboard = scoreboards.get(player.getUniqueId()); + if (scoreboard != null) { + Objective objective = scoreboard.getObjective("lohub"); + if (objective != null) { + updateScoreboard(player, scoreboard, objective); + } + } + } + } + + public void removePlayer(Player player) { + scoreboards.remove(player.getUniqueId()); + } +} diff --git a/lohub/src/main/java/com/loki/lohub/managers/TablistManager.java b/lohub/src/main/java/com/loki/lohub/managers/TablistManager.java new file mode 100644 index 0000000..81c621a --- /dev/null +++ b/lohub/src/main/java/com/loki/lohub/managers/TablistManager.java @@ -0,0 +1,80 @@ +package com.loki.lohub.managers; + +import com.loki.lohub.LoHub; +import com.loki.lohub.utils.PlaceholderUtil; +import com.loki.lohub.utils.TextUtil; +import net.kyori.adventure.text.Component; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import java.util.List; + +public class TablistManager { + + private final LoHub plugin; + private int taskId = -1; + + public TablistManager(LoHub plugin) { + this.plugin = plugin; + } + + public void start() { + if (!plugin.getConfig().getBoolean("tablist.enabled", false)) { + return; + } + + if (plugin.getConfig().getBoolean("tablist.refresh.enabled", true)) { + int rate = plugin.getConfig().getInt("tablist.refresh.rate", 400); + taskId = Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, this::updateAll, 0L, rate); + } + } + + public void stop() { + if (taskId != -1) { + Bukkit.getScheduler().cancelTask(taskId); + taskId = -1; + } + } + + public void setTablist(Player player) { + if (!plugin.getConfig().getBoolean("tablist.enabled", false)) { + return; + } + + updateTablist(player); + } + + 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"); + } + } + + player.sendPlayerListHeaderAndFooter( + Component.text(header.toString()), + Component.text(footer.toString()) + ); + } + + private void updateAll() { + for (Player player : Bukkit.getOnlinePlayers()) { + updateTablist(player); + } + } +}