fix command and refactoring config
This commit is contained in:
parent
b922f588d0
commit
fe64b3d51f
109 changed files with 4103 additions and 5403 deletions
180
TODO.md
180
TODO.md
|
|
@ -1,180 +0,0 @@
|
||||||
# 🚀 Loki Plugins - TODO
|
|
||||||
|
|
||||||
## 📦 Проекты
|
|
||||||
|
|
||||||
### 1. LoChat - Чат плагин (Paper/Folia)
|
|
||||||
**Статус:** ✅ Готов к использованию
|
|
||||||
|
|
||||||
#### Функции
|
|
||||||
- ✅ Глобальный/локальный чат
|
|
||||||
- ✅ PM система с игнором
|
|
||||||
- ✅ Мут система с историей
|
|
||||||
- ✅ Фильтры (мат, спам, CAPS)
|
|
||||||
- ✅ Градиентные ники (LuckPerms интеграция)
|
|
||||||
- ✅ Смайлики (300+ эмодзи)
|
|
||||||
- ✅ PlaceholderAPI
|
|
||||||
- ✅ Markdown форматирование (**bold**, *italic*, ~~strike~~, `code`)
|
|
||||||
- ✅ Упоминания (@player, @everyone, @here, @role:permission)
|
|
||||||
- ✅ Фильтры URL/IP/повторов
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 2. LoHub - Hub плагин (Paper/Folia)
|
|
||||||
**Статус:** ✅ Готов к использованию (100% готово)
|
|
||||||
|
|
||||||
#### ✅ Готово
|
|
||||||
- ✅ Spawn система с телепортом
|
|
||||||
- ✅ WorldGuard регионы (авто-создание)
|
|
||||||
- ✅ Защита мира (блоки, 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 интеграция
|
|
||||||
|
|
||||||
#### 📋 Дополнительно
|
|
||||||
- Все основные функции реализованы
|
|
||||||
- Конфигурация полностью настраиваема через config.yml
|
|
||||||
- Поддержка PlaceholderAPI для всех текстовых элементов
|
|
||||||
- Команда /lohub reload для перезагрузки конфигурации
|
|
||||||
- [ ] Announcements модуль
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 3. LoVelocity - Velocity плагин
|
|
||||||
**Статус:** ✅ Готов
|
|
||||||
|
|
||||||
#### Функции
|
|
||||||
- ✅ Команда /hub для телепорта на lobby/hub сервер
|
|
||||||
- ✅ Кастомные сообщения
|
|
||||||
- ✅ Поддержка PlaceholderAPI
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🏗️ Структура проекта
|
|
||||||
|
|
||||||
```
|
|
||||||
LoChat/ # Root проекта
|
|
||||||
├── src/main/ # LoChat (основной модуль)
|
|
||||||
│ ├── java/com/loki/lochat/
|
|
||||||
│ │ ├── api/ # API интерфейсы
|
|
||||||
│ │ ├── commands/ # Команды
|
|
||||||
│ │ ├── config/ # Конфигурация
|
|
||||||
│ │ ├── core/ # Реализации
|
|
||||||
│ │ ├── gradient/ # Градиентные ники
|
|
||||||
│ │ ├── listener/ # Слушатели событий
|
|
||||||
│ │ ├── utils/ # Утилиты
|
|
||||||
│ │ └── LoChat.java # Главный класс
|
|
||||||
│ └── resources/ # Конфиги
|
|
||||||
│
|
|
||||||
├── lohub/ # LoHub модуль
|
|
||||||
│ ├── src/main/
|
|
||||||
│ │ ├── java/com/loki/lohub/
|
|
||||||
│ │ │ ├── actions/ # Action система
|
|
||||||
│ │ │ ├── commands/ # Команды
|
|
||||||
│ │ │ ├── config/ # Конфигурация
|
|
||||||
│ │ │ ├── listeners/ # Слушатели
|
|
||||||
│ │ │ ├── managers/ # Менеджеры
|
|
||||||
│ │ │ ├── utils/ # Утилиты
|
|
||||||
│ │ │ └── LoHub.java # Главный класс
|
|
||||||
│ │ └── resources/ # Конфиги
|
|
||||||
│ └── build.gradle.kts # Gradle конфиг
|
|
||||||
│
|
|
||||||
├── lovelocity/ # LoVelocity модуль
|
|
||||||
│ ├── src/main/
|
|
||||||
│ │ └── java/com/loki/lovelocity/
|
|
||||||
│ └── build.gradle.kts # Gradle конфиг
|
|
||||||
│
|
|
||||||
├── build.gradle.kts # Root Gradle (Kotlin DSL)
|
|
||||||
├── settings.gradle.kts # Настройки проектов
|
|
||||||
└── TODO.md # Этот файл
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 Текущий фокус
|
|
||||||
|
|
||||||
**LoHub - ЭТАП 2: Action система**
|
|
||||||
|
|
||||||
Создание гибкой системы действий для настройки поведения через конфиг:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
actions:
|
|
||||||
- "[MESSAGE] &aПривет, %player%!"
|
|
||||||
- "[SOUND] ENTITY_PLAYER_LEVELUP"
|
|
||||||
- "[TITLE] &b&lДобро пожаловать;&fНа сервер;1;3;1"
|
|
||||||
- "[COMMAND] spawn"
|
|
||||||
- "[CONSOLE] give %player% diamond 1"
|
|
||||||
- "[GAMEMODE] survival"
|
|
||||||
- "[EFFECT] SPEED;1"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 Правила разработки
|
|
||||||
|
|
||||||
1. **Никакого русского текста в Java файлах** - только в конфигах
|
|
||||||
2. **Цвета только в формате `&#RRGGBB`** - унифицированный стиль
|
|
||||||
3. **SOLID принципы** - чистая архитектура
|
|
||||||
4. **Классы до 100-150 строк** - читаемость кода
|
|
||||||
5. **Gradle Kotlin DSL** - современный подход
|
|
||||||
6. **Без лишних MD файлов** - только TODO.md и docs/
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔧 Технологии
|
|
||||||
|
|
||||||
- **Java 17+**
|
|
||||||
- **Paper API 1.20.1**
|
|
||||||
- **Velocity API 3.3.0**
|
|
||||||
- **Gradle 9.1+ (Kotlin DSL)**
|
|
||||||
- **WorldGuard 7.0.9**
|
|
||||||
- **PlaceholderAPI 2.11.6**
|
|
||||||
- **LuckPerms API**
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
plugins {
|
|
||||||
java
|
|
||||||
checkstyle
|
|
||||||
}
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
maven("https://repo.papermc.io/repository/maven-public/")
|
|
||||||
maven("https://repo.extendedclip.com/content/repositories/placeholderapi/")
|
|
||||||
maven("https://maven.enginehub.org/repo/")
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
compileOnly("io.papermc.paper:paper-api:1.21.4-R0.1-SNAPSHOT")
|
|
||||||
compileOnly("me.clip:placeholderapi:2.11.6")
|
|
||||||
compileOnly("com.sk89q.worldguard:worldguard-bukkit:7.0.9")
|
|
||||||
implementation("com.google.code.gson:gson:2.10.1")
|
|
||||||
|
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter-api:5.10.0")
|
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter-engine:5.10.0")
|
|
||||||
testImplementation("org.mockito:mockito-core:5.11.0")
|
|
||||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher:1.10.0")
|
|
||||||
}
|
|
||||||
|
|
||||||
java {
|
|
||||||
toolchain {
|
|
||||||
languageVersion.set(JavaLanguageVersion.of(21))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.jar {
|
|
||||||
archiveFileName.set("LoHub-1.5.5-1.21.8.jar")
|
|
||||||
from(configurations.runtimeClasspath.get().map { if (it.isDirectory) it else zipTree(it) })
|
|
||||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
|
||||||
}
|
|
||||||
|
|
||||||
checkstyle {
|
|
||||||
toolVersion = "10.12.5"
|
|
||||||
configFile = file("${rootProject.rootDir}/config/checkstyle/checkstyle.xml")
|
|
||||||
isIgnoreFailures = false
|
|
||||||
maxWarnings = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.withType<Checkstyle> {
|
|
||||||
reports {
|
|
||||||
xml.required.set(false)
|
|
||||||
html.required.set(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,150 +0,0 @@
|
||||||
package com.loki.lohub;
|
|
||||||
|
|
||||||
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.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;
|
|
||||||
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;
|
|
||||||
|
|
||||||
public class LoHub extends JavaPlugin {
|
|
||||||
|
|
||||||
private ConfigManager configManager;
|
|
||||||
private SpawnManager spawnManager;
|
|
||||||
private RegionManager regionManager;
|
|
||||||
private ActionManager actionManager;
|
|
||||||
private CooldownManager cooldownManager;
|
|
||||||
private HotbarManager hotbarManager;
|
|
||||||
private PlayerHiderManager playerHiderManager;
|
|
||||||
private ScoreboardManager scoreboardManager;
|
|
||||||
private TablistManager tablistManager;
|
|
||||||
private AnnouncementManager announcementManager;
|
|
||||||
private ChatLockManager chatLockManager;
|
|
||||||
private CustomCommandManager customCommandManager;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onEnable() {
|
|
||||||
getLogger().info("Loading LoHub v" + getDescription().getVersion());
|
|
||||||
|
|
||||||
saveDefaultConfig();
|
|
||||||
|
|
||||||
PlaceholderUtil.init();
|
|
||||||
|
|
||||||
this.configManager = new ConfigManager(this);
|
|
||||||
this.spawnManager = new SpawnManager(this);
|
|
||||||
this.regionManager = new RegionManager(this);
|
|
||||||
this.actionManager = new ActionManager(this);
|
|
||||||
this.cooldownManager = new CooldownManager();
|
|
||||||
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);
|
|
||||||
this.chatLockManager = new ChatLockManager(this);
|
|
||||||
this.customCommandManager = new CustomCommandManager(this);
|
|
||||||
|
|
||||||
registerListeners();
|
|
||||||
registerCommands();
|
|
||||||
registerPluginChannels();
|
|
||||||
|
|
||||||
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);
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void registerPluginChannels() {
|
|
||||||
getServer().getMessenger().registerIncomingPluginChannel(
|
|
||||||
this,
|
|
||||||
com.loki.lohub.listeners.ServerSwitchMessageListener.getChannel(),
|
|
||||||
new com.loki.lohub.listeners.ServerSwitchMessageListener(this)
|
|
||||||
);
|
|
||||||
getLogger().info("Plugin messaging channels registered");
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigManager getConfigManager() {
|
|
||||||
return configManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SpawnManager getSpawnManager() {
|
|
||||||
return spawnManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public RegionManager getRegionManager() {
|
|
||||||
return regionManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ActionManager getActionManager() {
|
|
||||||
return actionManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CooldownManager getCooldownManager() {
|
|
||||||
return cooldownManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChatLockManager getChatLockManager() {
|
|
||||||
return chatLockManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CustomCommandManager getCustomCommandManager() {
|
|
||||||
return customCommandManager;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
package com.loki.lohub.actions;
|
|
||||||
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
public interface Action {
|
|
||||||
|
|
||||||
void execute(Player player);
|
|
||||||
|
|
||||||
ActionType getType();
|
|
||||||
}
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
package com.loki.lohub.actions;
|
|
||||||
|
|
||||||
public enum ActionType {
|
|
||||||
MESSAGE,
|
|
||||||
BROADCAST,
|
|
||||||
TITLE,
|
|
||||||
ACTIONBAR,
|
|
||||||
SOUND,
|
|
||||||
COMMAND,
|
|
||||||
CONSOLE,
|
|
||||||
GAMEMODE,
|
|
||||||
EFFECT,
|
|
||||||
CLOSE,
|
|
||||||
UNKNOWN;
|
|
||||||
|
|
||||||
public static ActionType fromString(String type) {
|
|
||||||
try {
|
|
||||||
return valueOf(type.toUpperCase());
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
return UNKNOWN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
package com.loki.lohub.actions.impl;
|
|
||||||
|
|
||||||
import com.loki.lohub.actions.Action;
|
|
||||||
import com.loki.lohub.actions.ActionType;
|
|
||||||
import com.loki.lohub.utils.PlaceholderUtil;
|
|
||||||
import com.loki.lohub.utils.TextUtil;
|
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
public class ActionbarAction implements Action {
|
|
||||||
|
|
||||||
private final String message;
|
|
||||||
|
|
||||||
public ActionbarAction(String message) {
|
|
||||||
this.message = message;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(Player player) {
|
|
||||||
String parsed = PlaceholderUtil.parse(message, player);
|
|
||||||
player.sendActionBar(Component.text(TextUtil.colorize(parsed)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ActionType getType() {
|
|
||||||
return ActionType.ACTIONBAR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
package com.loki.lohub.actions.impl;
|
|
||||||
|
|
||||||
import com.loki.lohub.actions.Action;
|
|
||||||
import com.loki.lohub.actions.ActionType;
|
|
||||||
import com.loki.lohub.utils.PlaceholderUtil;
|
|
||||||
import com.loki.lohub.utils.TextUtil;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
public class BroadcastAction implements Action {
|
|
||||||
|
|
||||||
private final String message;
|
|
||||||
|
|
||||||
public BroadcastAction(String message) {
|
|
||||||
this.message = message;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(Player player) {
|
|
||||||
String parsed = PlaceholderUtil.parse(message, player);
|
|
||||||
Bukkit.broadcastMessage(TextUtil.colorize(parsed));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ActionType getType() {
|
|
||||||
return ActionType.BROADCAST;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
package com.loki.lohub.actions.impl;
|
|
||||||
|
|
||||||
import com.loki.lohub.actions.Action;
|
|
||||||
import com.loki.lohub.actions.ActionType;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
public class CloseAction implements Action {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(Player player) {
|
|
||||||
player.closeInventory();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ActionType getType() {
|
|
||||||
return ActionType.CLOSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
package com.loki.lohub.actions.impl;
|
|
||||||
|
|
||||||
import com.loki.lohub.actions.Action;
|
|
||||||
import com.loki.lohub.actions.ActionType;
|
|
||||||
import com.loki.lohub.utils.PlaceholderUtil;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
public class CommandAction implements Action {
|
|
||||||
|
|
||||||
private final String command;
|
|
||||||
|
|
||||||
public CommandAction(String command) {
|
|
||||||
this.command = command;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(Player player) {
|
|
||||||
String parsed = PlaceholderUtil.parse(command, player);
|
|
||||||
player.performCommand(parsed);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ActionType getType() {
|
|
||||||
return ActionType.COMMAND;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
package com.loki.lohub.actions.impl;
|
|
||||||
|
|
||||||
import com.loki.lohub.actions.Action;
|
|
||||||
import com.loki.lohub.actions.ActionType;
|
|
||||||
import com.loki.lohub.utils.PlaceholderUtil;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
public class ConsoleAction implements Action {
|
|
||||||
|
|
||||||
private final String command;
|
|
||||||
|
|
||||||
public ConsoleAction(String command) {
|
|
||||||
this.command = command;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(Player player) {
|
|
||||||
String parsed = PlaceholderUtil.parse(command, player);
|
|
||||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), parsed);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ActionType getType() {
|
|
||||||
return ActionType.CONSOLE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
package com.loki.lohub.actions.impl;
|
|
||||||
|
|
||||||
import com.loki.lohub.actions.Action;
|
|
||||||
import com.loki.lohub.actions.ActionType;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.potion.PotionEffect;
|
|
||||||
import org.bukkit.potion.PotionEffectType;
|
|
||||||
|
|
||||||
public class EffectAction implements Action {
|
|
||||||
|
|
||||||
private final PotionEffectType effectType;
|
|
||||||
private final int amplifier;
|
|
||||||
private final int duration;
|
|
||||||
|
|
||||||
public EffectAction(String effectData) {
|
|
||||||
String[] parts = effectData.split(";");
|
|
||||||
|
|
||||||
PotionEffectType parsed;
|
|
||||||
try {
|
|
||||||
parsed = PotionEffectType.getByName(parts[0].toUpperCase());
|
|
||||||
} catch (Exception e) {
|
|
||||||
parsed = PotionEffectType.SPEED;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.effectType = parsed != null ? parsed : PotionEffectType.SPEED;
|
|
||||||
this.amplifier = parts.length > 1 ? parseInt(parts[1], 0) : 0;
|
|
||||||
this.duration = parts.length > 2 ? parseInt(parts[2], 999999) : 999999;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(Player player) {
|
|
||||||
player.addPotionEffect(new PotionEffect(effectType, duration * 20, amplifier, false, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ActionType getType() {
|
|
||||||
return ActionType.EFFECT;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int parseInt(String value, int defaultValue) {
|
|
||||||
try {
|
|
||||||
return Integer.parseInt(value);
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
package com.loki.lohub.actions.impl;
|
|
||||||
|
|
||||||
import com.loki.lohub.actions.Action;
|
|
||||||
import com.loki.lohub.actions.ActionType;
|
|
||||||
import org.bukkit.GameMode;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
public class GamemodeAction implements Action {
|
|
||||||
|
|
||||||
private final GameMode gameMode;
|
|
||||||
|
|
||||||
public GamemodeAction(String mode) {
|
|
||||||
GameMode parsed;
|
|
||||||
try {
|
|
||||||
parsed = GameMode.valueOf(mode.toUpperCase());
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
parsed = switch (mode.toLowerCase()) {
|
|
||||||
case "0", "s" -> GameMode.SURVIVAL;
|
|
||||||
case "1", "c" -> GameMode.CREATIVE;
|
|
||||||
case "2", "a" -> GameMode.ADVENTURE;
|
|
||||||
case "3", "sp" -> GameMode.SPECTATOR;
|
|
||||||
default -> GameMode.SURVIVAL;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
this.gameMode = parsed;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(Player player) {
|
|
||||||
player.setGameMode(gameMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ActionType getType() {
|
|
||||||
return ActionType.GAMEMODE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
package com.loki.lohub.actions.impl;
|
|
||||||
|
|
||||||
import com.loki.lohub.actions.Action;
|
|
||||||
import com.loki.lohub.actions.ActionType;
|
|
||||||
import com.loki.lohub.utils.PlaceholderUtil;
|
|
||||||
import com.loki.lohub.utils.TextUtil;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
public class MessageAction implements Action {
|
|
||||||
|
|
||||||
private final String message;
|
|
||||||
|
|
||||||
public MessageAction(String message) {
|
|
||||||
this.message = message;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(Player player) {
|
|
||||||
String parsed = PlaceholderUtil.parse(message, player);
|
|
||||||
player.sendMessage(TextUtil.colorize(parsed));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ActionType getType() {
|
|
||||||
return ActionType.MESSAGE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
package com.loki.lohub.actions.impl;
|
|
||||||
|
|
||||||
import com.loki.lohub.actions.Action;
|
|
||||||
import com.loki.lohub.actions.ActionType;
|
|
||||||
import org.bukkit.Sound;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
public class SoundAction implements Action {
|
|
||||||
|
|
||||||
private final Sound sound;
|
|
||||||
private final float volume;
|
|
||||||
private final float pitch;
|
|
||||||
|
|
||||||
public SoundAction(String soundData) {
|
|
||||||
String[] parts = soundData.split(";");
|
|
||||||
|
|
||||||
Sound parsedSound;
|
|
||||||
try {
|
|
||||||
String soundName = parts[0].toUpperCase().trim();
|
|
||||||
parsedSound = Sound.valueOf(soundName);
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
try {
|
|
||||||
parsedSound = Sound.ENTITY_EXPERIENCE_ORB_PICKUP;
|
|
||||||
} catch (NoSuchFieldError ex) {
|
|
||||||
parsedSound = Sound.valueOf("ENTITY_EXPERIENCE_ORB_PICKUP");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.sound = parsedSound;
|
|
||||||
this.volume = parts.length > 1 ? parseFloat(parts[1], 1.0f) : 1.0f;
|
|
||||||
this.pitch = parts.length > 2 ? parseFloat(parts[2], 1.0f) : 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(Player player) {
|
|
||||||
if (player != null && sound != null) {
|
|
||||||
player.playSound(player.getLocation(), sound, volume, pitch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ActionType getType() {
|
|
||||||
return ActionType.SOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
private float parseFloat(String value, float defaultValue) {
|
|
||||||
try {
|
|
||||||
return Float.parseFloat(value);
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,61 +0,0 @@
|
||||||
package com.loki.lohub.actions.impl;
|
|
||||||
|
|
||||||
import com.loki.lohub.actions.Action;
|
|
||||||
import com.loki.lohub.actions.ActionType;
|
|
||||||
import com.loki.lohub.utils.PlaceholderUtil;
|
|
||||||
import com.loki.lohub.utils.TextUtil;
|
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import net.kyori.adventure.title.Title;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
|
|
||||||
public class TitleAction implements Action {
|
|
||||||
|
|
||||||
private final String title;
|
|
||||||
private final String subtitle;
|
|
||||||
private final int fadeIn;
|
|
||||||
private final int stay;
|
|
||||||
private final int fadeOut;
|
|
||||||
|
|
||||||
public TitleAction(String titleData) {
|
|
||||||
String[] parts = titleData.split(";");
|
|
||||||
|
|
||||||
this.title = parts.length > 0 ? parts[0] : "";
|
|
||||||
this.subtitle = parts.length > 1 ? parts[1] : "";
|
|
||||||
this.fadeIn = parts.length > 2 ? parseInt(parts[2], 10) : 10;
|
|
||||||
this.stay = parts.length > 3 ? parseInt(parts[3], 40) : 40;
|
|
||||||
this.fadeOut = parts.length > 4 ? parseInt(parts[4], 10) : 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(Player player) {
|
|
||||||
String parsedTitle = PlaceholderUtil.parse(title, player);
|
|
||||||
String parsedSubtitle = PlaceholderUtil.parse(subtitle, player);
|
|
||||||
|
|
||||||
Component titleComponent = Component.text(TextUtil.colorize(parsedTitle));
|
|
||||||
Component subtitleComponent = Component.text(TextUtil.colorize(parsedSubtitle));
|
|
||||||
|
|
||||||
Title.Times times = Title.Times.times(
|
|
||||||
Duration.ofMillis(fadeIn * 50L),
|
|
||||||
Duration.ofMillis(stay * 50L),
|
|
||||||
Duration.ofMillis(fadeOut * 50L)
|
|
||||||
);
|
|
||||||
|
|
||||||
Title title = Title.title(titleComponent, subtitleComponent, times);
|
|
||||||
player.showTitle(title);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ActionType getType() {
|
|
||||||
return ActionType.TITLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int parseInt(String value, int defaultValue) {
|
|
||||||
try {
|
|
||||||
return Integer.parseInt(value);
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
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.bukkit.entity.Player;
|
|
||||||
|
|
||||||
public class HubCommand implements CommandExecutor {
|
|
||||||
|
|
||||||
private final LoHub plugin;
|
|
||||||
|
|
||||||
public HubCommand(LoHub plugin) {
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
|
||||||
if (!(sender instanceof Player player)) {
|
|
||||||
sender.sendMessage(TextUtil.colorize(plugin.getConfigManager().getMessage("general.players-only")));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (plugin.getSpawnManager().getSpawn() == null) {
|
|
||||||
player.sendMessage(TextUtil.colorize(plugin.getConfigManager().getMessage("spawn.no-spawn")));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
plugin.getSpawnManager().teleportToSpawn(player);
|
|
||||||
player.sendMessage(TextUtil.colorize(plugin.getConfigManager().getMessage("spawn.teleport")));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
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;
|
|
||||||
|
|
||||||
public class LoHubCommand implements CommandExecutor {
|
|
||||||
|
|
||||||
private final LoHub plugin;
|
|
||||||
|
|
||||||
public LoHubCommand(LoHub plugin) {
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
|
||||||
if (!sender.hasPermission("lohub.admin")) {
|
|
||||||
sender.sendMessage(TextUtil.colorize(plugin.getConfigManager().getMessage("general.no-permission")));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.length == 0) {
|
|
||||||
sender.sendMessage(TextUtil.colorize("&7LoHub v" + plugin.getDescription().getVersion()));
|
|
||||||
sender.sendMessage(TextUtil.colorize(plugin.getConfigManager().getMessage("commands.usage-lohub")));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
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(plugin.getConfigManager().getMessage("general.config-reloaded")));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
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.bukkit.entity.Player;
|
|
||||||
|
|
||||||
public class SetHubCommand implements CommandExecutor {
|
|
||||||
|
|
||||||
private final LoHub plugin;
|
|
||||||
|
|
||||||
public SetHubCommand(LoHub plugin) {
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
|
||||||
if (!(sender instanceof Player player)) {
|
|
||||||
sender.sendMessage(TextUtil.colorize(plugin.getConfigManager().getMessage("general.players-only")));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!player.hasPermission("lohub.admin")) {
|
|
||||||
player.sendMessage(TextUtil.colorize(plugin.getConfigManager().getMessage("general.no-permission")));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
plugin.getSpawnManager().setSpawn(player.getLocation());
|
|
||||||
player.sendMessage(TextUtil.colorize(plugin.getConfigManager().getMessage("spawn.set")));
|
|
||||||
|
|
||||||
plugin.getRegionManager().deleteHubRegion();
|
|
||||||
plugin.getRegionManager().createHubRegion();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
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<String> lines, Player player, String separator) {
|
|
||||||
return lines.stream()
|
|
||||||
.map(line -> format(line, player))
|
|
||||||
.collect(Collectors.joining(separator));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,185 +0,0 @@
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isBlockBreakProtected() {
|
|
||||||
return config.getBoolean("protection.block-break", true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isBlockPlaceProtected() {
|
|
||||||
return config.getBoolean("protection.block-place", true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isPvPProtected() {
|
|
||||||
return config.getBoolean("protection.pvp", true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isItemDropProtected() {
|
|
||||||
return config.getBoolean("protection.item-drop", true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isItemPickupProtected() {
|
|
||||||
return config.getBoolean("protection.item-pickup", true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isFoodLevelProtected() {
|
|
||||||
return config.getBoolean("protection.food-level", true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isMobSpawningProtected() {
|
|
||||||
return config.getBoolean("protection.mob-spawning", true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,104 +0,0 @@
|
||||||
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<String, Color> 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<Color> 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<Color> getColors(FileConfiguration config) {
|
|
||||||
List<Color> 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,68 +0,0 @@
|
||||||
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<String> 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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,91 +0,0 @@
|
||||||
package com.loki.lohub.listeners;
|
|
||||||
|
|
||||||
import com.loki.lohub.LoHub;
|
|
||||||
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 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) {
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onPlayerMove(PlayerMoveEvent event) {
|
|
||||||
if (!ConfigHelper.isEnabled(plugin.getConfig(), CONFIG_PATH)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Player player = event.getPlayer();
|
|
||||||
|
|
||||||
if (GameModeHelper.isCreativeOrSpectator(player)) {
|
|
||||||
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 (!ConfigHelper.isEnabled(plugin.getConfig(), CONFIG_PATH)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Player player = event.getPlayer();
|
|
||||||
|
|
||||||
if (GameModeHelper.isCreativeOrSpectator(player)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
LaunchHelper.launch(player, power, powerY);
|
|
||||||
|
|
||||||
int cooldown = ConfigHelper.getCooldown(plugin.getConfig(), CONFIG_PATH, 3);
|
|
||||||
plugin.getCooldownManager().setCooldown(COOLDOWN_KEY, player.getUniqueId(), cooldown);
|
|
||||||
|
|
||||||
executeActions(player);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void executeActions(Player player) {
|
|
||||||
List<String> actions = plugin.getConfig().getStringList(CONFIG_PATH + ".actions");
|
|
||||||
if (!actions.isEmpty()) {
|
|
||||||
plugin.getActionManager().executeActions(player, actions, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,58 +0,0 @@
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,170 +0,0 @@
|
||||||
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.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 {
|
|
||||||
|
|
||||||
private final LoHub plugin;
|
|
||||||
|
|
||||||
public HubProtectionListener(LoHub plugin) {
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
|
||||||
if (plugin.getConfig().getBoolean("spawn.teleport-on-join", true)) {
|
|
||||||
plugin.getSpawnManager().teleportToSpawn(event.getPlayer());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onBlockBreak(BlockBreakEvent event) {
|
|
||||||
if (!plugin.getConfigManager().isProtectionEnabled()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Player player = event.getPlayer();
|
|
||||||
if (player.hasPermission("lohub.bypass.protection")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (plugin.getConfigManager().isBlockBreakProtected()) {
|
|
||||||
event.setCancelled(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onBlockPlace(BlockPlaceEvent event) {
|
|
||||||
if (!plugin.getConfigManager().isProtectionEnabled()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Player player = event.getPlayer();
|
|
||||||
if (player.hasPermission("lohub.bypass.protection")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (plugin.getConfigManager().isBlockPlaceProtected()) {
|
|
||||||
event.setCancelled(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onPvP(EntityDamageByEntityEvent event) {
|
|
||||||
if (!plugin.getConfigManager().isProtectionEnabled()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!(event.getDamager() instanceof Player)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!(event.getEntity() instanceof Player)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Player damager = (Player) event.getDamager();
|
|
||||||
if (damager.hasPermission("lohub.bypass.protection")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (plugin.getConfigManager().isPvPProtected()) {
|
|
||||||
event.setCancelled(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onItemDrop(PlayerDropItemEvent event) {
|
|
||||||
if (!plugin.getConfigManager().isProtectionEnabled()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Player player = event.getPlayer();
|
|
||||||
if (player.hasPermission("lohub.bypass.protection")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (plugin.getConfigManager().isItemDropProtected()) {
|
|
||||||
event.setCancelled(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onItemPickup(PlayerPickupItemEvent event) {
|
|
||||||
if (!plugin.getConfigManager().isProtectionEnabled()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Player player = event.getPlayer();
|
|
||||||
if (player.hasPermission("lohub.bypass.protection")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (plugin.getConfigManager().isItemPickupProtected()) {
|
|
||||||
event.setCancelled(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onFoodLevelChange(FoodLevelChangeEvent event) {
|
|
||||||
if (!plugin.getConfigManager().isProtectionEnabled()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!(event.getEntity() instanceof Player)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Player player = (Player) event.getEntity();
|
|
||||||
if (player.hasPermission("lohub.bypass.protection")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (plugin.getConfigManager().isFoodLevelProtected()) {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,84 +0,0 @@
|
||||||
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 java.util.List;
|
|
||||||
|
|
||||||
public class LaunchpadListener implements Listener {
|
|
||||||
|
|
||||||
private static final String CONFIG_PATH = "launchpad";
|
|
||||||
|
|
||||||
private final LoHub plugin;
|
|
||||||
|
|
||||||
public LaunchpadListener(LoHub plugin) {
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onPlayerMove(PlayerMoveEvent event) {
|
|
||||||
if (!ConfigHelper.isEnabled(plugin.getConfig(), CONFIG_PATH)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasMoved(event)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Player player = event.getPlayer();
|
|
||||||
Block block = player.getLocation().getBlock();
|
|
||||||
|
|
||||||
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 = ConfigHelper.getPower(plugin.getConfig(), CONFIG_PATH, "launch_power", 3.0);
|
|
||||||
double powerY = ConfigHelper.getPower(plugin.getConfig(), CONFIG_PATH, "launch_power_y", 1.0);
|
|
||||||
|
|
||||||
LaunchHelper.launch(player, power, powerY);
|
|
||||||
executeActions(player);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void executeActions(Player player) {
|
|
||||||
List<String> actions = plugin.getConfig().getStringList(CONFIG_PATH + ".actions");
|
|
||||||
if (!actions.isEmpty()) {
|
|
||||||
plugin.getActionManager().executeActions(player, actions, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,99 +0,0 @@
|
||||||
package com.loki.lohub.listeners;
|
|
||||||
|
|
||||||
import com.loki.lohub.LoHub;
|
|
||||||
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.Player;
|
|
||||||
import org.bukkit.event.EventHandler;
|
|
||||||
import org.bukkit.event.EventPriority;
|
|
||||||
import org.bukkit.event.Listener;
|
|
||||||
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 java.util.List;
|
|
||||||
|
|
||||||
public class PlayerJoinListener implements Listener {
|
|
||||||
|
|
||||||
private final LoHub plugin;
|
|
||||||
|
|
||||||
public PlayerJoinListener(LoHub plugin) {
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGHEST)
|
|
||||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
|
||||||
Player player = event.getPlayer();
|
|
||||||
|
|
||||||
if (isWorldDisabled(player.getWorld().getName())) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGHEST)
|
|
||||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
|
||||||
Player player = event.getPlayer();
|
|
||||||
|
|
||||||
if (isWorldDisabled(player.getWorld().getName())) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
plugin.getPlayerHiderManager().removePlayer(player);
|
|
||||||
plugin.getScoreboardManager().removePlayer(player);
|
|
||||||
|
|
||||||
JoinMessageHandler.handleQuit(event, player, plugin.getConfig());
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGHEST)
|
|
||||||
public void onPlayerRespawn(PlayerRespawnEvent event) {
|
|
||||||
Player player = event.getPlayer();
|
|
||||||
|
|
||||||
if (isWorldDisabled(player.getWorld().getName())) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (plugin.getConfig().getBoolean("spawn.teleport-on-respawn", true)) {
|
|
||||||
Location spawn = plugin.getSpawnManager().getSpawn();
|
|
||||||
if (spawn != null) {
|
|
||||||
event.setRespawnLocation(spawn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.LOWEST)
|
|
||||||
public void onPlayerDeath(PlayerDeathEvent event) {
|
|
||||||
if (isWorldDisabled(event.getPlayer().getWorld().getName())) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (plugin.getConfig().getBoolean("world_settings.disable_death_message", true)) {
|
|
||||||
event.deathMessage(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void executeJoinActions(Player player) {
|
|
||||||
List<String> actions = plugin.getConfig().getStringList("join_events");
|
|
||||||
if (!actions.isEmpty()) {
|
|
||||||
plugin.getActionManager().executeActions(player, actions, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isWorldDisabled(String worldName) {
|
|
||||||
List<String> disabledWorlds = plugin.getConfig().getStringList("disabled-worlds.worlds");
|
|
||||||
boolean invert = plugin.getConfig().getBoolean("disabled-worlds.invert", false);
|
|
||||||
boolean isInList = disabledWorlds.contains(worldName);
|
|
||||||
|
|
||||||
return invert ? !isInList : isInList;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,65 +0,0 @@
|
||||||
package com.loki.lohub.listeners;
|
|
||||||
|
|
||||||
import com.google.common.io.ByteArrayDataInput;
|
|
||||||
import com.google.common.io.ByteStreams;
|
|
||||||
import com.loki.lohub.LoHub;
|
|
||||||
import com.loki.lohub.utils.TextUtil;
|
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.plugin.messaging.PluginMessageListener;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
public class ServerSwitchMessageListener implements PluginMessageListener {
|
|
||||||
|
|
||||||
private final LoHub plugin;
|
|
||||||
private static final String CHANNEL = "lohub:switch";
|
|
||||||
|
|
||||||
public ServerSwitchMessageListener(LoHub plugin) {
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPluginMessageReceived(@NotNull String channel, @NotNull Player player, byte @NotNull [] message) {
|
|
||||||
if (!channel.equals(CHANNEL)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteArrayDataInput in = ByteStreams.newDataInput(message);
|
|
||||||
String subChannel = in.readUTF();
|
|
||||||
|
|
||||||
if (subChannel.equals("ServerSwitch")) {
|
|
||||||
String playerName = in.readUTF();
|
|
||||||
String fromServer = in.readUTF();
|
|
||||||
String toServer = in.readUTF();
|
|
||||||
|
|
||||||
handleServerSwitch(playerName, fromServer, toServer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleServerSwitch(String playerName, String fromServer, String toServer) {
|
|
||||||
if (!plugin.getConfig().getBoolean("server_switch_messages.enabled", true)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String messageTemplate = plugin.getConfig().getString("server_switch_messages.switch_message",
|
|
||||||
"&#FFD700%player% &#AAAAAA connected to BCB77%server%");
|
|
||||||
|
|
||||||
String serverDisplayName = getServerDisplayName(toServer);
|
|
||||||
String formattedMessage = messageTemplate
|
|
||||||
.replace("%player%", playerName)
|
|
||||||
.replace("%server%", serverDisplayName);
|
|
||||||
|
|
||||||
Component component = Component.text(TextUtil.colorize(formattedMessage));
|
|
||||||
Bukkit.broadcast(component);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getServerDisplayName(String serverName) {
|
|
||||||
String path = "server_switch_messages.server_names." + serverName;
|
|
||||||
return plugin.getConfig().getString(path, serverName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getChannel() {
|
|
||||||
return CHANNEL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,107 +0,0 @@
|
||||||
package com.loki.lohub.managers;
|
|
||||||
|
|
||||||
import com.loki.lohub.LoHub;
|
|
||||||
import com.loki.lohub.actions.Action;
|
|
||||||
import com.loki.lohub.actions.ActionType;
|
|
||||||
import com.loki.lohub.actions.impl.ActionbarAction;
|
|
||||||
import com.loki.lohub.actions.impl.BroadcastAction;
|
|
||||||
import com.loki.lohub.actions.impl.CloseAction;
|
|
||||||
import com.loki.lohub.actions.impl.CommandAction;
|
|
||||||
import com.loki.lohub.actions.impl.ConsoleAction;
|
|
||||||
import com.loki.lohub.actions.impl.EffectAction;
|
|
||||||
import com.loki.lohub.actions.impl.GamemodeAction;
|
|
||||||
import com.loki.lohub.actions.impl.MessageAction;
|
|
||||||
import com.loki.lohub.actions.impl.SoundAction;
|
|
||||||
import com.loki.lohub.actions.impl.TitleAction;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
public class ActionManager {
|
|
||||||
|
|
||||||
private static final Pattern ACTION_PATTERN = Pattern.compile("\\[([A-Z]+)]\\s*(.*)");
|
|
||||||
private final LoHub plugin;
|
|
||||||
|
|
||||||
public ActionManager(LoHub plugin) {
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Action> parseActions(List<String> actionStrings) {
|
|
||||||
List<Action> actions = new ArrayList<>();
|
|
||||||
|
|
||||||
for (String actionString : actionStrings) {
|
|
||||||
Action action = parseAction(actionString);
|
|
||||||
if (action != null) {
|
|
||||||
actions.add(action);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return actions;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Action parseAction(String actionString) {
|
|
||||||
if (actionString == null || actionString.isEmpty()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Matcher matcher = ACTION_PATTERN.matcher(actionString);
|
|
||||||
if (!matcher.matches()) {
|
|
||||||
plugin.getLogger().warning("Invalid action format: " + actionString);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
String typeStr = matcher.group(1);
|
|
||||||
String data = matcher.group(2);
|
|
||||||
|
|
||||||
ActionType type = ActionType.fromString(typeStr);
|
|
||||||
|
|
||||||
return switch (type) {
|
|
||||||
case MESSAGE -> new MessageAction(data);
|
|
||||||
case BROADCAST -> new BroadcastAction(data);
|
|
||||||
case TITLE -> new TitleAction(data);
|
|
||||||
case ACTIONBAR -> new ActionbarAction(data);
|
|
||||||
case SOUND -> new SoundAction(data);
|
|
||||||
case COMMAND -> new CommandAction(data);
|
|
||||||
case CONSOLE -> new ConsoleAction(data);
|
|
||||||
case GAMEMODE -> new GamemodeAction(data);
|
|
||||||
case EFFECT -> new EffectAction(data);
|
|
||||||
case CLOSE -> new CloseAction();
|
|
||||||
default -> {
|
|
||||||
plugin.getLogger().warning("Unknown action type: " + typeStr);
|
|
||||||
yield null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public void executeActions(Player player, List<Action> actions) {
|
|
||||||
for (Action action : actions) {
|
|
||||||
try {
|
|
||||||
action.execute(player);
|
|
||||||
} catch (Exception e) {
|
|
||||||
plugin.getLogger().severe("Error executing action " + action.getType() + ": " + e.getMessage());
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void executeActions(Player player, List<String> actionStrings, boolean parse) {
|
|
||||||
if (parse) {
|
|
||||||
List<Action> actions = parseActions(actionStrings);
|
|
||||||
executeActions(player, actions);
|
|
||||||
} else {
|
|
||||||
for (String actionString : actionStrings) {
|
|
||||||
Action action = parseAction(actionString);
|
|
||||||
if (action != null) {
|
|
||||||
try {
|
|
||||||
action.execute(player);
|
|
||||||
} catch (Exception e) {
|
|
||||||
plugin.getLogger().severe("Error executing action: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,124 +0,0 @@
|
||||||
package com.loki.lohub.managers;
|
|
||||||
|
|
||||||
import com.loki.lohub.LoHub;
|
|
||||||
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;
|
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class AnnouncementManager {
|
|
||||||
|
|
||||||
private static final String CONFIG_PATH = "announcements";
|
|
||||||
|
|
||||||
private final LoHub plugin;
|
|
||||||
private final List<Announcement> 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(CONFIG_PATH + ".announcements");
|
|
||||||
if (section == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
section.getKeys(false).forEach(key -> {
|
|
||||||
List<String> messages = section.getStringList(key);
|
|
||||||
if (!messages.isEmpty()) {
|
|
||||||
announcements.add(new Announcement(key, messages));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void start() {
|
|
||||||
if (!ConfigHelper.isEnabled(plugin.getConfig(), CONFIG_PATH)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (announcements.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int delay = plugin.getConfig().getInt(CONFIG_PATH + ".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() {
|
|
||||||
if (!hasEnoughPlayers()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (announcements.isEmpty()) {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendAnnouncement(Player player, Announcement announcement) {
|
|
||||||
announcement.messages().forEach(message -> {
|
|
||||||
String formatted = TextFormatter.format(message, player);
|
|
||||||
player.sendMessage(Component.text(formatted));
|
|
||||||
});
|
|
||||||
|
|
||||||
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(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);
|
|
||||||
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<String> messages) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,60 +0,0 @@
|
||||||
package com.loki.lohub.managers;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class CooldownManager {
|
|
||||||
|
|
||||||
private final Map<String, Map<UUID, Long>> cooldowns = new HashMap<>();
|
|
||||||
|
|
||||||
public void setCooldown(String key, UUID playerId, int seconds) {
|
|
||||||
cooldowns.computeIfAbsent(key, k -> new HashMap<>())
|
|
||||||
.put(playerId, System.currentTimeMillis() + (seconds * 1000L));
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasCooldown(String key, UUID playerId) {
|
|
||||||
Map<UUID, Long> keyCooldowns = cooldowns.get(key);
|
|
||||||
if (keyCooldowns == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Long expireTime = keyCooldowns.get(playerId);
|
|
||||||
if (expireTime == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (System.currentTimeMillis() >= expireTime) {
|
|
||||||
keyCooldowns.remove(playerId);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getRemainingSeconds(String key, UUID playerId) {
|
|
||||||
Map<UUID, Long> keyCooldowns = cooldowns.get(key);
|
|
||||||
if (keyCooldowns == null) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Long expireTime = keyCooldowns.get(playerId);
|
|
||||||
if (expireTime == null) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
long remaining = expireTime - System.currentTimeMillis();
|
|
||||||
return remaining > 0 ? (int) (remaining / 1000) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeCooldown(String key, UUID playerId) {
|
|
||||||
Map<UUID, Long> keyCooldowns = cooldowns.get(key);
|
|
||||||
if (keyCooldowns != null) {
|
|
||||||
keyCooldowns.remove(playerId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clearAll() {
|
|
||||||
cooldowns.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
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<String, CustomCommand> 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<String> aliases = cmdSection.getStringList("aliases");
|
|
||||||
String permission = cmdSection.getString("permission");
|
|
||||||
List<String> 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<String> aliases, String permission, List<String> actions) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,103 +0,0 @@
|
||||||
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 static final String CONFIG_PATH = "custom_join_items";
|
|
||||||
|
|
||||||
private final LoHub plugin;
|
|
||||||
private final Map<Integer, HotbarItem> items = new HashMap<>();
|
|
||||||
|
|
||||||
public HotbarManager(LoHub plugin) {
|
|
||||||
this.plugin = plugin;
|
|
||||||
loadItems();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadItems() {
|
|
||||||
items.clear();
|
|
||||||
ConfigurationSection section = plugin.getConfig().getConfigurationSection(CONFIG_PATH + ".items");
|
|
||||||
if (section == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (String key : section.getKeys(false)) {
|
|
||||||
loadItem(section.getConfigurationSection(key));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadItem(ConfigurationSection itemSection) {
|
|
||||||
if (itemSection == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Material material = getMaterial(itemSection);
|
|
||||||
if (material == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int slot = itemSection.getInt("slot", 0);
|
|
||||||
ItemStack item = buildItem(itemSection, material);
|
|
||||||
List<String> 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<String> 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) {
|
|
||||||
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 boolean isEnabled() {
|
|
||||||
return plugin.getConfig().getBoolean(CONFIG_PATH + ".enabled", false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private record HotbarItem(ItemStack item, List<String> actions) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,113 +0,0 @@
|
||||||
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 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<UUID> hiddenPlayers = new HashSet<>();
|
|
||||||
|
|
||||||
public PlayerHiderManager(LoHub plugin) {
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void giveItem(Player player) {
|
|
||||||
if (!isEnabled()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
player.getInventory().setItem(getSlot(), getItem(player));
|
|
||||||
}
|
|
||||||
|
|
||||||
public ItemStack getItem(Player player) {
|
|
||||||
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<String> lore = plugin.getConfig().getStringList(path + ".lore");
|
|
||||||
|
|
||||||
return new ItemBuilder(material)
|
|
||||||
.amount(amount)
|
|
||||||
.name(displayName)
|
|
||||||
.lore(lore)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void toggle(Player player) {
|
|
||||||
if (isHidden(player)) {
|
|
||||||
showPlayers(player);
|
|
||||||
} else {
|
|
||||||
hidePlayers(player);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateItem(player);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void hidePlayers(Player player) {
|
|
||||||
hiddenPlayers.add(player.getUniqueId());
|
|
||||||
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)) {
|
|
||||||
if (visible) {
|
|
||||||
player.showPlayer(plugin, online);
|
|
||||||
} else {
|
|
||||||
player.hidePlayer(plugin, online);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateItem(Player player) {
|
|
||||||
player.getInventory().setItem(getSlot(), getItem(player));
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isPlayerHiderSlot(int slot) {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,127 +0,0 @@
|
||||||
package com.loki.lohub.managers;
|
|
||||||
|
|
||||||
import com.loki.lohub.LoHub;
|
|
||||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
|
||||||
import com.sk89q.worldguard.WorldGuard;
|
|
||||||
import com.sk89q.worldguard.protection.flags.Flags;
|
|
||||||
import com.sk89q.worldguard.protection.flags.StateFlag;
|
|
||||||
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
|
|
||||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
|
||||||
import com.sk89q.worldguard.protection.regions.RegionContainer;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.World;
|
|
||||||
|
|
||||||
public class RegionManager {
|
|
||||||
|
|
||||||
private static final String HUB_REGION_NAME = "lohub_spawn";
|
|
||||||
private final LoHub plugin;
|
|
||||||
|
|
||||||
public RegionManager(LoHub plugin) {
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void createHubRegion() {
|
|
||||||
if (!plugin.getConfig().getBoolean("worldguard.auto-create-region", true)) {
|
|
||||||
plugin.getLogger().info("WorldGuard region auto-creation is disabled");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isWorldGuardAvailable()) {
|
|
||||||
plugin.getLogger().warning("WorldGuard not found! Region will not be created.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Location spawn = plugin.getSpawnManager().getSpawn();
|
|
||||||
if (spawn == null || spawn.getWorld() == null) {
|
|
||||||
plugin.getLogger().warning("Spawn not set! Use /sethub");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
World world = spawn.getWorld();
|
|
||||||
int radius = plugin.getConfig().getInt("worldguard.region-radius", 100);
|
|
||||||
|
|
||||||
try {
|
|
||||||
RegionContainer container = WorldGuard.getInstance().getPlatform().getRegionContainer();
|
|
||||||
com.sk89q.worldguard.protection.managers.RegionManager wgRegionManager = container.get(BukkitAdapter.adapt(world));
|
|
||||||
|
|
||||||
if (wgRegionManager == null) {
|
|
||||||
plugin.getLogger().warning("Failed to get RegionManager for world " + world.getName());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProtectedRegion existingRegion = wgRegionManager.getRegion(HUB_REGION_NAME);
|
|
||||||
if (existingRegion != null) {
|
|
||||||
plugin.getLogger().info("Region '" + HUB_REGION_NAME + "' already exists");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockVector3 min = BlockVector3.at(
|
|
||||||
spawn.getBlockX() - radius,
|
|
||||||
world.getMinHeight(),
|
|
||||||
spawn.getBlockZ() - radius
|
|
||||||
);
|
|
||||||
|
|
||||||
BlockVector3 max = BlockVector3.at(
|
|
||||||
spawn.getBlockX() + radius,
|
|
||||||
world.getMaxHeight(),
|
|
||||||
spawn.getBlockZ() + radius
|
|
||||||
);
|
|
||||||
|
|
||||||
ProtectedCuboidRegion region = new ProtectedCuboidRegion(HUB_REGION_NAME, min, max);
|
|
||||||
setRegionFlags(region);
|
|
||||||
|
|
||||||
wgRegionManager.addRegion(region);
|
|
||||||
|
|
||||||
plugin.getLogger().info("Region '" + HUB_REGION_NAME + "' created around spawn (radius: " + radius + " blocks)");
|
|
||||||
plugin.getLogger().info("Coordinates: " + min + " -> " + max);
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
plugin.getLogger().severe("Error creating WorldGuard region: " + e.getMessage());
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setRegionFlags(ProtectedCuboidRegion region) {
|
|
||||||
region.setFlag(Flags.PVP, StateFlag.State.DENY);
|
|
||||||
region.setFlag(Flags.BLOCK_BREAK, StateFlag.State.DENY);
|
|
||||||
region.setFlag(Flags.BLOCK_PLACE, StateFlag.State.DENY);
|
|
||||||
region.setFlag(Flags.DAMAGE_ANIMALS, StateFlag.State.DENY);
|
|
||||||
region.setFlag(Flags.MOB_SPAWNING, StateFlag.State.DENY);
|
|
||||||
region.setFlag(Flags.LEAF_DECAY, StateFlag.State.DENY);
|
|
||||||
region.setFlag(Flags.ITEM_DROP, StateFlag.State.DENY);
|
|
||||||
region.setFlag(Flags.ITEM_PICKUP, StateFlag.State.DENY);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void deleteHubRegion() {
|
|
||||||
if (!isWorldGuardAvailable()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Location spawn = plugin.getSpawnManager().getSpawn();
|
|
||||||
if (spawn == null || spawn.getWorld() == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
RegionContainer container = WorldGuard.getInstance().getPlatform().getRegionContainer();
|
|
||||||
com.sk89q.worldguard.protection.managers.RegionManager wgRegionManager = container.get(BukkitAdapter.adapt(spawn.getWorld()));
|
|
||||||
|
|
||||||
if (wgRegionManager != null) {
|
|
||||||
wgRegionManager.removeRegion(HUB_REGION_NAME);
|
|
||||||
plugin.getLogger().info("Region '" + HUB_REGION_NAME + "' deleted");
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
plugin.getLogger().severe("Error deleting region: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isWorldGuardAvailable() {
|
|
||||||
try {
|
|
||||||
Class.forName("com.sk89q.worldguard.WorldGuard");
|
|
||||||
return plugin.getServer().getPluginManager().isPluginEnabled("WorldGuard");
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,130 +0,0 @@
|
||||||
package com.loki.lohub.managers;
|
|
||||||
|
|
||||||
import com.loki.lohub.LoHub;
|
|
||||||
import com.loki.lohub.common.ConfigHelper;
|
|
||||||
import com.loki.lohub.common.TextFormatter;
|
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
|
||||||
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 static final String CONFIG_PATH = "scoreboard";
|
|
||||||
private static final String OBJECTIVE_NAME = "lohub";
|
|
||||||
private static final LegacyComponentSerializer SERIALIZER = LegacyComponentSerializer.legacySection();
|
|
||||||
|
|
||||||
private final LoHub plugin;
|
|
||||||
private final Map<UUID, Scoreboard> scoreboards = new HashMap<>();
|
|
||||||
private int taskId = -1;
|
|
||||||
|
|
||||||
public ScoreboardManager(LoHub plugin) {
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void start() {
|
|
||||||
if (!ConfigHelper.isEnabled(plugin.getConfig(), CONFIG_PATH)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shouldRefresh()) {
|
|
||||||
int rate = plugin.getConfig().getInt(CONFIG_PATH + ".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 (!ConfigHelper.isEnabled(plugin.getConfig(), CONFIG_PATH)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (delayed) {
|
|
||||||
int delay = plugin.getConfig().getInt(CONFIG_PATH + ".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(OBJECTIVE_NAME, "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) {
|
|
||||||
updateTitle(player, objective);
|
|
||||||
updateLines(player, scoreboard, objective);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateTitle(Player player, Objective objective) {
|
|
||||||
String title = plugin.getConfig().getString(CONFIG_PATH + ".title", "");
|
|
||||||
objective.displayName(SERIALIZER.deserialize(TextFormatter.format(title, player)));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateLines(Player player, Scoreboard scoreboard, Objective objective) {
|
|
||||||
List<String> lines = plugin.getConfig().getStringList(CONFIG_PATH + ".lines");
|
|
||||||
int score = lines.size();
|
|
||||||
|
|
||||||
for (String line : lines) {
|
|
||||||
String formatted = TextFormatter.format(line, player);
|
|
||||||
String teamName = "line_" + score;
|
|
||||||
|
|
||||||
Team team = getOrCreateTeam(scoreboard, teamName);
|
|
||||||
team.prefix(SERIALIZER.deserialize(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() {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,59 +0,0 @@
|
||||||
package com.loki.lohub.managers;
|
|
||||||
|
|
||||||
import com.loki.lohub.LoHub;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.World;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
public class SpawnManager {
|
|
||||||
|
|
||||||
private final LoHub plugin;
|
|
||||||
|
|
||||||
public SpawnManager(LoHub plugin) {
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Location getSpawn() {
|
|
||||||
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) {
|
|
||||||
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();
|
|
||||||
|
|
||||||
plugin.getLogger().info("Spawn set: " + location.getWorld().getName() +
|
|
||||||
" (" + location.getBlockX() + ", " + location.getBlockY() + ", " + location.getBlockZ() + ")");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void teleportToSpawn(Player player) {
|
|
||||||
Location spawn = getSpawn();
|
|
||||||
if (spawn == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
player.teleport(spawn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
package com.loki.lohub.managers;
|
|
||||||
|
|
||||||
import com.loki.lohub.LoHub;
|
|
||||||
import com.loki.lohub.common.ConfigHelper;
|
|
||||||
import com.loki.lohub.common.TextFormatter;
|
|
||||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class TablistManager {
|
|
||||||
|
|
||||||
private static final String CONFIG_PATH = "tablist";
|
|
||||||
private static final LegacyComponentSerializer SERIALIZER = LegacyComponentSerializer.legacySection();
|
|
||||||
|
|
||||||
private final LoHub plugin;
|
|
||||||
private int taskId = -1;
|
|
||||||
|
|
||||||
public TablistManager(LoHub plugin) {
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void start() {
|
|
||||||
if (!ConfigHelper.isEnabled(plugin.getConfig(), CONFIG_PATH)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shouldRefresh()) {
|
|
||||||
int rate = plugin.getConfig().getInt(CONFIG_PATH + ".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 (!ConfigHelper.isEnabled(plugin.getConfig(), CONFIG_PATH)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
updateTablist(player);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateTablist(Player player) {
|
|
||||||
String header = formatLines(CONFIG_PATH + ".header", player);
|
|
||||||
String footer = formatLines(CONFIG_PATH + ".footer", player);
|
|
||||||
|
|
||||||
player.sendPlayerListHeaderAndFooter(
|
|
||||||
SERIALIZER.deserialize(header),
|
|
||||||
SERIALIZER.deserialize(footer)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String formatLines(String path, Player player) {
|
|
||||||
List<String> lines = plugin.getConfig().getStringList(path);
|
|
||||||
return TextFormatter.joinLines(lines, player, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateAll() {
|
|
||||||
Bukkit.getOnlinePlayers().forEach(this::updateTablist);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean shouldRefresh() {
|
|
||||||
return plugin.getConfig().getBoolean(CONFIG_PATH + ".refresh.enabled", true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,158 +0,0 @@
|
||||||
package com.loki.lohub.utils;
|
|
||||||
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
|
||||||
import org.bukkit.enchantments.Enchantment;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.inventory.ItemFlag;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
import org.bukkit.inventory.meta.ItemMeta;
|
|
||||||
import org.bukkit.inventory.meta.SkullMeta;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class ItemBuilder {
|
|
||||||
|
|
||||||
private final ItemStack itemStack;
|
|
||||||
|
|
||||||
public ItemBuilder(Material material) {
|
|
||||||
this.itemStack = new ItemStack(material);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ItemBuilder(ItemStack itemStack) {
|
|
||||||
this.itemStack = itemStack.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ItemBuilder fromConfig(ConfigurationSection section) {
|
|
||||||
return fromConfig(section, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ItemBuilder fromConfig(ConfigurationSection section, Player player) {
|
|
||||||
String materialName = section.getString("material", "STONE").toUpperCase();
|
|
||||||
Material material;
|
|
||||||
|
|
||||||
try {
|
|
||||||
material = Material.valueOf(materialName);
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
material = Material.STONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ItemBuilder builder = new ItemBuilder(material);
|
|
||||||
|
|
||||||
if (section.contains("amount")) {
|
|
||||||
builder.amount(section.getInt("amount", 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (section.contains("display_name")) {
|
|
||||||
String name = section.getString("display_name");
|
|
||||||
builder.name(player != null ? PlaceholderUtil.parse(name, player) : name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (section.contains("lore")) {
|
|
||||||
List<String> lore = section.getStringList("lore");
|
|
||||||
builder.lore(player != null ?
|
|
||||||
lore.stream().map(line -> PlaceholderUtil.parse(line, player)).collect(Collectors.toList()) :
|
|
||||||
lore);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (section.contains("glow") && section.getBoolean("glow")) {
|
|
||||||
builder.glow();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (section.contains("custom_model_data")) {
|
|
||||||
builder.customModelData(section.getInt("custom_model_data"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (section.contains("item_flags")) {
|
|
||||||
section.getStringList("item_flags").forEach(flagName -> {
|
|
||||||
try {
|
|
||||||
builder.flag(ItemFlag.valueOf(flagName.toUpperCase()));
|
|
||||||
} catch (IllegalArgumentException ignored) {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (material == Material.PLAYER_HEAD && section.contains("skull_owner")) {
|
|
||||||
String owner = section.getString("skull_owner");
|
|
||||||
builder.skullOwner(player != null ? owner.replace("%player%", player.getName()) : owner);
|
|
||||||
}
|
|
||||||
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ItemBuilder amount(int amount) {
|
|
||||||
itemStack.setAmount(Math.max(1, amount));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ItemBuilder name(String name) {
|
|
||||||
ItemMeta meta = itemStack.getItemMeta();
|
|
||||||
if (meta != null) {
|
|
||||||
meta.displayName(net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection()
|
|
||||||
.deserialize(TextUtil.colorize(name)));
|
|
||||||
itemStack.setItemMeta(meta);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ItemBuilder lore(List<String> lore) {
|
|
||||||
ItemMeta meta = itemStack.getItemMeta();
|
|
||||||
if (meta != null) {
|
|
||||||
List<net.kyori.adventure.text.Component> coloredLore = lore.stream()
|
|
||||||
.map(line -> net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection()
|
|
||||||
.deserialize(TextUtil.colorize(line)))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
meta.lore(coloredLore);
|
|
||||||
itemStack.setItemMeta(meta);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ItemBuilder lore(String... lines) {
|
|
||||||
return lore(List.of(lines));
|
|
||||||
}
|
|
||||||
|
|
||||||
public ItemBuilder flag(ItemFlag... flags) {
|
|
||||||
ItemMeta meta = itemStack.getItemMeta();
|
|
||||||
if (meta != null) {
|
|
||||||
meta.addItemFlags(flags);
|
|
||||||
itemStack.setItemMeta(meta);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ItemBuilder glow() {
|
|
||||||
ItemMeta meta = itemStack.getItemMeta();
|
|
||||||
if (meta != null) {
|
|
||||||
meta.addEnchant(Enchantment.UNBREAKING, 1, true);
|
|
||||||
meta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
|
|
||||||
itemStack.setItemMeta(meta);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ItemBuilder customModelData(int data) {
|
|
||||||
ItemMeta meta = itemStack.getItemMeta();
|
|
||||||
if (meta != null) {
|
|
||||||
meta.setCustomModelData(data);
|
|
||||||
itemStack.setItemMeta(meta);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ItemBuilder skullOwner(String owner) {
|
|
||||||
if (itemStack.getType() == Material.PLAYER_HEAD) {
|
|
||||||
SkullMeta meta = (SkullMeta) itemStack.getItemMeta();
|
|
||||||
if (meta != null) {
|
|
||||||
meta.setOwner(owner);
|
|
||||||
itemStack.setItemMeta(meta);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ItemStack build() {
|
|
||||||
return itemStack;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,59 +0,0 @@
|
||||||
package com.loki.lohub.utils;
|
|
||||||
|
|
||||||
import me.clip.placeholderapi.PlaceholderAPI;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
public class PlaceholderUtil {
|
|
||||||
|
|
||||||
private static boolean placeholderAPIEnabled = false;
|
|
||||||
|
|
||||||
private PlaceholderUtil() {
|
|
||||||
// Utility class - prevent instantiation
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void init() {
|
|
||||||
placeholderAPIEnabled = Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String parse(String text, Player player) {
|
|
||||||
if (text == null) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
text = parseInternalPlaceholders(text, player);
|
|
||||||
|
|
||||||
if (placeholderAPIEnabled && player != null) {
|
|
||||||
text = PlaceholderAPI.setPlaceholders(player, text);
|
|
||||||
}
|
|
||||||
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String parseInternalPlaceholders(String text, Player player) {
|
|
||||||
if (player != null) {
|
|
||||||
text = text.replace("%player%", player.getName());
|
|
||||||
text = text.replace("%player_displayname%", player.getDisplayName());
|
|
||||||
|
|
||||||
if (text.contains("%location%")) {
|
|
||||||
Location loc = player.getLocation();
|
|
||||||
text = text.replace("%location%",
|
|
||||||
loc.getBlockX() + ", " + loc.getBlockY() + ", " + loc.getBlockZ());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (text.contains("%world%")) {
|
|
||||||
text = text.replace("%world%", player.getWorld().getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
text = text.replace("%online%", String.valueOf(Bukkit.getOnlinePlayers().size()));
|
|
||||||
text = text.replace("%online_max%", String.valueOf(Bukkit.getMaxPlayers()));
|
|
||||||
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isPlaceholderAPIEnabled() {
|
|
||||||
return placeholderAPIEnabled;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
package com.loki.lohub.utils;
|
|
||||||
|
|
||||||
import net.md_5.bungee.api.ChatColor;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class TextUtil {
|
|
||||||
|
|
||||||
private static final Pattern HEX_PATTERN = Pattern.compile("&#([A-Fa-f0-9]{6})");
|
|
||||||
|
|
||||||
private TextUtil() {
|
|
||||||
// Utility class - prevent instantiation
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String colorize(String text) {
|
|
||||||
if (text == null || text.isEmpty()) {
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
text = translateHexCodes(text);
|
|
||||||
text = ChatColor.translateAlternateColorCodes('&', text);
|
|
||||||
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<String> colorize(List<String> lines) {
|
|
||||||
return lines.stream()
|
|
||||||
.map(TextUtil::colorize)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String translateHexCodes(String text) {
|
|
||||||
Matcher matcher = HEX_PATTERN.matcher(text);
|
|
||||||
StringBuffer buffer = new StringBuffer();
|
|
||||||
|
|
||||||
while (matcher.find()) {
|
|
||||||
String hexCode = matcher.group(1);
|
|
||||||
String replacement = ChatColor.of("#" + hexCode).toString();
|
|
||||||
matcher.appendReplacement(buffer, replacement);
|
|
||||||
}
|
|
||||||
|
|
||||||
matcher.appendTail(buffer);
|
|
||||||
return buffer.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String strip(String text) {
|
|
||||||
return ChatColor.stripColor(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String joinFrom(int startIndex, String[] args) {
|
|
||||||
if (args == null || startIndex >= args.length) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
for (int i = startIndex; i < args.length; i++) {
|
|
||||||
builder.append(args[i]);
|
|
||||||
if (i < args.length - 1) {
|
|
||||||
builder.append(" ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return builder.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String listToString(List<String> list) {
|
|
||||||
if (list == null || list.isEmpty()) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
return String.join("\n", list);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,105 +0,0 @@
|
||||||
# ╔══════════════════════════════════════════════════════════════════════════════╗
|
|
||||||
# ║ 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"
|
|
||||||
|
|
@ -1,366 +0,0 @@
|
||||||
# ╔══════════════════════════════════════════════════════════════════════════════╗
|
|
||||||
# ║ LoHub Configuration ║
|
|
||||||
# ║ Hub plugin for Paper/Folia 1.20.1+ ║
|
|
||||||
# ║ Version: 1.5.5-1.20.1 ║
|
|
||||||
# ║ Compatible with DeluxeHub config format ║
|
|
||||||
# ╚══════════════════════════════════════════════════════════════════════════════╝
|
|
||||||
#
|
|
||||||
# BUILT-IN PLACEHOLDERS:
|
|
||||||
# %player% - Player name
|
|
||||||
# %player_displayname% - Player display name
|
|
||||||
# %location% - Player location (x, y, z)
|
|
||||||
# %world% - World name
|
|
||||||
# %online% - Online players count
|
|
||||||
# %online_max% - Max players
|
|
||||||
#
|
|
||||||
# ACTIONS (for join_events, custom_join_items, etc):
|
|
||||||
# [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 (survival/creative/adventure/spectator)
|
|
||||||
# [EFFECT] effect;level - Give potion effect
|
|
||||||
# [CLOSE] - Close inventory
|
|
||||||
#
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# | GENERAL SETTINGS |
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
|
|
||||||
# Check for updates (recommended)
|
|
||||||
check-updates: false
|
|
||||||
|
|
||||||
# Disable plugin in specific worlds
|
|
||||||
disabled-worlds:
|
|
||||||
invert: false
|
|
||||||
worlds:
|
|
||||||
- world_nether
|
|
||||||
- world_the_end
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# | SPAWN SETTINGS |
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
|
|
||||||
spawn:
|
|
||||||
# Teleport players to spawn on join
|
|
||||||
teleport-on-join: true
|
|
||||||
|
|
||||||
# Teleport players to spawn on respawn
|
|
||||||
teleport-on-respawn: true
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# | WORLDGUARD INTEGRATION |
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
|
|
||||||
worldguard:
|
|
||||||
# Auto-create WorldGuard region around spawn
|
|
||||||
auto-create-region: true
|
|
||||||
|
|
||||||
# Region radius in blocks
|
|
||||||
region-radius: 100
|
|
||||||
|
|
||||||
# Region name (don't change unless you know what you're doing)
|
|
||||||
region-name: "lohub_spawn"
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# | WORLD PROTECTION |
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
|
|
||||||
world_settings:
|
|
||||||
# Player
|
|
||||||
disable_hunger_loss: true
|
|
||||||
disable_fall_damage: true
|
|
||||||
disable_player_pvp: true
|
|
||||||
disable_void_death: true
|
|
||||||
disable_fire_damage: true
|
|
||||||
disable_drowning: true
|
|
||||||
disable_off_hand_swap: true
|
|
||||||
|
|
||||||
# Misc
|
|
||||||
disable_weather_change: true
|
|
||||||
disable_death_message: true
|
|
||||||
disable_mob_spawning: true
|
|
||||||
|
|
||||||
# Item entities
|
|
||||||
disable_item_drop: true
|
|
||||||
disable_item_pickup: true
|
|
||||||
|
|
||||||
# Blocks
|
|
||||||
disable_block_break: true
|
|
||||||
disable_block_place: true
|
|
||||||
disable_block_interact: true
|
|
||||||
disable_block_burn: true
|
|
||||||
disable_block_fire_spread: true
|
|
||||||
disable_block_leaf_decay: true
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# | LAUNCHPAD |
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
|
|
||||||
launchpad:
|
|
||||||
enabled: true
|
|
||||||
launch_power: 3.0
|
|
||||||
launch_power_y: 1.0
|
|
||||||
|
|
||||||
# Blocks required: pressure plate on top of redstone block
|
|
||||||
top_block: STONE_PRESSURE_PLATE
|
|
||||||
bottom_block: REDSTONE_BLOCK
|
|
||||||
|
|
||||||
actions:
|
|
||||||
- '[SOUND] ENTITY_BAT_TAKEOFF'
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# | DOUBLE JUMP |
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
|
|
||||||
double_jump:
|
|
||||||
enabled: true
|
|
||||||
launch_power: 1.0
|
|
||||||
launch_power_y: 0.9
|
|
||||||
cooldown: 3
|
|
||||||
|
|
||||||
actions:
|
|
||||||
- '[SOUND] ENTITY_BAT_TAKEOFF'
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# | COMMAND BLOCKER |
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
|
|
||||||
command_block:
|
|
||||||
enabled: true
|
|
||||||
blocked_commands:
|
|
||||||
- /pl
|
|
||||||
- /plugins
|
|
||||||
- /?
|
|
||||||
- /bukkit:?
|
|
||||||
- /bukkit:plugins
|
|
||||||
- /bukkit:pl
|
|
||||||
- /bukkit:help
|
|
||||||
- /ver
|
|
||||||
- /version
|
|
||||||
- /bukkit:version
|
|
||||||
- /bukkit:ver
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# | ANTI-SWEAR |
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
|
|
||||||
anti_swear:
|
|
||||||
enabled: false
|
|
||||||
blocked_words:
|
|
||||||
- fuck
|
|
||||||
- shit
|
|
||||||
- bitch
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# | PLAYER JOIN |
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
|
|
||||||
join_leave_messages:
|
|
||||||
enabled: true
|
|
||||||
# Сообщение при подключении к хабу
|
|
||||||
# Пустая строка '' = не показывать сообщение
|
|
||||||
join_message: "BCB77+ &#FFD700%player% &#AAAAAAподключился к хабу"
|
|
||||||
# Сообщение при выходе с сервера (не при переключении на другой сервер)
|
|
||||||
quit_message: "&#FF6B6B- &#FFD700%player% &#AAAAAAвышел"
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# | SERVER SWITCH MESSAGES |
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
|
|
||||||
server_switch_messages:
|
|
||||||
# Показывать сообщения о переключении между серверами
|
|
||||||
enabled: true
|
|
||||||
|
|
||||||
# Шаблон сообщения при переключении
|
|
||||||
# %player% - имя игрока
|
|
||||||
# %server% - название сервера
|
|
||||||
switch_message: "&#FFD700%player% &#AAAAAAподключился к BCB77%server%"
|
|
||||||
|
|
||||||
# Отображаемые названия серверов
|
|
||||||
# Если сервер не указан, будет использовано его техническое имя
|
|
||||||
server_names:
|
|
||||||
hub: "Хабу"
|
|
||||||
grief: "Грифу"
|
|
||||||
survival: "Выживанию"
|
|
||||||
creative: "Креативу"
|
|
||||||
minigames: "Мини-играм"
|
|
||||||
|
|
||||||
join_events:
|
|
||||||
- "[MESSAGE] &#FFD700╔═══════════════════════════════╗"
|
|
||||||
- "[MESSAGE] &r"
|
|
||||||
- "[MESSAGE] &r BCB77Welcome, &#FFD700%player%BCB77!"
|
|
||||||
- "[MESSAGE] &r"
|
|
||||||
- "[MESSAGE] &r �D4FFWebsite: &#FFFFFFwww.example.net"
|
|
||||||
- "[MESSAGE] &r &#FF6B6BStore: &#FFFFFFstore.example.net"
|
|
||||||
- "[MESSAGE] &r 	B59B6Discord: &#FFFFFFdiscord.example.net"
|
|
||||||
- "[MESSAGE] &r"
|
|
||||||
- "[MESSAGE] &#FFD700╚═══════════════════════════════╝"
|
|
||||||
- "[TITLE] BCB77W>C973EAC76FL3C56BC1C367O(C163M&BF5FE;&#FFD700%player%;10;40;10"
|
|
||||||
- "[SOUND] ENTITY_PLAYER_LEVELUP"
|
|
||||||
- "[GAMEMODE] survival"
|
|
||||||
|
|
||||||
join_settings:
|
|
||||||
spawn_join: true
|
|
||||||
heal: true
|
|
||||||
extinguish: true
|
|
||||||
clear_inventory: false
|
|
||||||
|
|
||||||
firework:
|
|
||||||
enabled: true
|
|
||||||
first_join_only: true
|
|
||||||
type: BALL_LARGE
|
|
||||||
power: 1
|
|
||||||
flicker: true
|
|
||||||
trail: true
|
|
||||||
colors:
|
|
||||||
- AQUA
|
|
||||||
- RED
|
|
||||||
- TEAL
|
|
||||||
- WHITE
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# | CUSTOM JOIN ITEMS |
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
|
|
||||||
custom_join_items:
|
|
||||||
enabled: true
|
|
||||||
disable_inventory_movement: true
|
|
||||||
|
|
||||||
items:
|
|
||||||
info:
|
|
||||||
material: BOOK
|
|
||||||
amount: 1
|
|
||||||
slot: 0
|
|
||||||
display_name: "&#FFD700I&#FFC700n&#FFB700f&#FFA700o&#FF9700r&#FF8700m&#FF7700a&#FF6700t&#FF5700i&#FF4700o&#FF3700n"
|
|
||||||
lore:
|
|
||||||
- "&#AAAAAARight-click for server info!"
|
|
||||||
actions:
|
|
||||||
- "[MESSAGE] &r"
|
|
||||||
- "[MESSAGE] &#FFD700╔═══ Server Information ═══╗"
|
|
||||||
- "[MESSAGE] &r"
|
|
||||||
- "[MESSAGE] �D4FFWebsite: &#FFFFFFwww.example.net"
|
|
||||||
- "[MESSAGE] &#FF6B6BStore: &#FFFFFFstore.example.net"
|
|
||||||
- "[MESSAGE] 	B59B6Discord: &#FFFFFFdiscord.example.net"
|
|
||||||
- "[MESSAGE] &r"
|
|
||||||
- "[MESSAGE] &#FFD700╚═══════════════════════════╝"
|
|
||||||
- "[SOUND] BLOCK_NOTE_BLOCK_PLING"
|
|
||||||
|
|
||||||
compass:
|
|
||||||
material: COMPASS
|
|
||||||
amount: 1
|
|
||||||
slot: 4
|
|
||||||
display_name: "BCB77S>C973eAC76Fr3C56Bv1C367e(C163r &BF5FSFBD5BeBB57lEB953eB74Fc�DB54BtB347oB347r"
|
|
||||||
lore:
|
|
||||||
- "&#AAAAAARight-click to choose server!"
|
|
||||||
actions:
|
|
||||||
- "[MESSAGE] &#FF6B6BServer selector not implemented yet!"
|
|
||||||
- "[SOUND] ENTITY_VILLAGER_NO"
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# | PLAYER HIDER |
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
|
|
||||||
player_hider:
|
|
||||||
enabled: true
|
|
||||||
slot: 8
|
|
||||||
disable_inventory_movement: true
|
|
||||||
cooldown: 3
|
|
||||||
|
|
||||||
not_hidden:
|
|
||||||
material: LIME_DYE
|
|
||||||
amount: 1
|
|
||||||
display_name: 'BCB77Players &#AAAAAA> BCB77Shown 󙀸(Right-Click)'
|
|
||||||
lore:
|
|
||||||
- '&#AAAAAAClick to hide all players!'
|
|
||||||
|
|
||||||
hidden:
|
|
||||||
material: GRAY_DYE
|
|
||||||
amount: 1
|
|
||||||
display_name: '&#FF6B6BPlayers &#AAAAAA> &#FF6B6BHidden 󙀸(Right-Click)'
|
|
||||||
lore:
|
|
||||||
- '&#AAAAAAClick to show all players!'
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# | SCOREBOARD |
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
|
|
||||||
scoreboard:
|
|
||||||
enabled: false
|
|
||||||
|
|
||||||
display_delay:
|
|
||||||
server_enter: 60
|
|
||||||
world_change: 40
|
|
||||||
|
|
||||||
refresh:
|
|
||||||
enabled: true
|
|
||||||
rate: 200
|
|
||||||
|
|
||||||
title: "&#FFD700L&#FFC700o&#FFB700H&#FFA700u&#FF9700b 󙀸(%online%/%online_max%)"
|
|
||||||
lines:
|
|
||||||
- "&#AAAAAA━━━━━━━━━━━━━━━━━━━━━"
|
|
||||||
- "BCB77Player:"
|
|
||||||
- " &#FFFFFF%player%"
|
|
||||||
- ""
|
|
||||||
- "BCB77Rank:"
|
|
||||||
- " &#FFFFFF%vault_rank%"
|
|
||||||
- "&#AAAAAA━━━━━━━━━━━━━━━━━━━━━"
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# | TABLIST |
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
|
|
||||||
tablist:
|
|
||||||
enabled: false
|
|
||||||
|
|
||||||
refresh:
|
|
||||||
enabled: true
|
|
||||||
rate: 400
|
|
||||||
|
|
||||||
header:
|
|
||||||
- ""
|
|
||||||
- "&#FFD700L&#FFC700o&#FFB700H&#FFA700u&#FF9700b 󙀸(%online%/%online_max%)"
|
|
||||||
- ""
|
|
||||||
|
|
||||||
footer:
|
|
||||||
- ""
|
|
||||||
- "�D4FFWebsite &#FFFFFFwww.example.net"
|
|
||||||
- "&#FF6B6BStore &#FFFFFFstore.example.net"
|
|
||||||
- ""
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# | ANNOUNCEMENTS |
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
|
|
||||||
announcements:
|
|
||||||
enabled: false
|
|
||||||
delay: 60
|
|
||||||
required_players: 1
|
|
||||||
|
|
||||||
sound:
|
|
||||||
enabled: true
|
|
||||||
value: BLOCK_NOTE_BLOCK_PLING
|
|
||||||
volume: 1.0
|
|
||||||
pitch: 1.0
|
|
||||||
|
|
||||||
announcements:
|
|
||||||
welcome:
|
|
||||||
- "&r"
|
|
||||||
- "&#FFD700╔═══ Announcement ═══╗"
|
|
||||||
- "&#AAAAAAWelcome to our server!"
|
|
||||||
- "&#FFD700╚═══════════════════════╝"
|
|
||||||
- "&r"
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# | CUSTOM COMMANDS |
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# All custom commands are now in commands.yml
|
|
||||||
# You can create custom commands with actions there
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# | MESSAGES |
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# All messages are now in messages.yml
|
|
||||||
# You can customize the plugin prefix and all messages there
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
# ╔══════════════════════════════════════════════════════════════════════════════╗
|
|
||||||
# ║ 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
|
|
||||||
|
|
@ -1,84 +0,0 @@
|
||||||
# ╔══════════════════════════════════════════════════════════════════════════════╗
|
|
||||||
# ║ 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%"
|
|
||||||
|
|
@ -1,52 +0,0 @@
|
||||||
name: LoHub
|
|
||||||
version: '1.5.5-1.20.1'
|
|
||||||
main: com.loki.lohub.LoHub
|
|
||||||
api-version: '1.20'
|
|
||||||
folia-supported: true
|
|
||||||
author: loki
|
|
||||||
description: Hub plugin for Paper/Folia with WorldGuard integration
|
|
||||||
|
|
||||||
softdepend:
|
|
||||||
- WorldGuard
|
|
||||||
- WorldEdit
|
|
||||||
|
|
||||||
commands:
|
|
||||||
hub:
|
|
||||||
description: Teleport to spawn
|
|
||||||
usage: /hub
|
|
||||||
permission: lohub.hub
|
|
||||||
aliases: [ spawn, хаб, спавн ]
|
|
||||||
|
|
||||||
sethub:
|
|
||||||
description: Set hub spawn location
|
|
||||||
usage: /sethub
|
|
||||||
permission: lohub.admin
|
|
||||||
aliases: [ setspawn, установитьспавн ]
|
|
||||||
|
|
||||||
lohub:
|
|
||||||
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:
|
|
||||||
description: Can use /hub command
|
|
||||||
default: true
|
|
||||||
lohub.admin:
|
|
||||||
description: Admin permissions
|
|
||||||
default: op
|
|
||||||
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
|
|
||||||
|
|
@ -1,139 +0,0 @@
|
||||||
# ╔══════════════════════════════════════════════════════════════════════════════╗
|
|
||||||
# ║ 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: <player_name> # OR
|
|
||||||
# base64: <base64_texture>
|
|
||||||
#
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# | 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"
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
plugins {
|
|
||||||
java
|
|
||||||
checkstyle
|
|
||||||
}
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
maven("https://repo.papermc.io/repository/maven-public/")
|
|
||||||
maven("https://repo.velocitypowered.com/snapshots/")
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
compileOnly("com.velocitypowered:velocity-api:3.3.0-SNAPSHOT")
|
|
||||||
annotationProcessor("com.velocitypowered:velocity-api:3.3.0-SNAPSHOT")
|
|
||||||
implementation("com.google.code.gson:gson:2.10.1")
|
|
||||||
|
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter-api:5.10.0")
|
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter-engine:5.10.0")
|
|
||||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher:1.10.0")
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.jar {
|
|
||||||
archiveFileName.set("LoVelocity-1.5.5.jar")
|
|
||||||
from(configurations.runtimeClasspath.get().map { if (it.isDirectory) it else zipTree(it) })
|
|
||||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
|
||||||
}
|
|
||||||
|
|
||||||
checkstyle {
|
|
||||||
toolVersion = "10.12.5"
|
|
||||||
configFile = file("${rootProject.rootDir}/config/checkstyle/checkstyle.xml")
|
|
||||||
isIgnoreFailures = false
|
|
||||||
maxWarnings = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.withType<Checkstyle> {
|
|
||||||
reports {
|
|
||||||
xml.required.set(false)
|
|
||||||
html.required.set(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,71 +0,0 @@
|
||||||
package com.loki.lovelocity;
|
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
|
||||||
import com.loki.lovelocity.commands.HubCommand;
|
|
||||||
import com.velocitypowered.api.command.CommandMeta;
|
|
||||||
import com.velocitypowered.api.event.Subscribe;
|
|
||||||
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
|
|
||||||
import com.velocitypowered.api.plugin.Plugin;
|
|
||||||
import com.velocitypowered.api.plugin.annotation.DataDirectory;
|
|
||||||
import com.velocitypowered.api.proxy.ProxyServer;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
|
|
||||||
import java.nio.file.Path;
|
|
||||||
|
|
||||||
@Plugin(
|
|
||||||
id = "lovelocity",
|
|
||||||
name = "LoVelocity",
|
|
||||||
version = "1.5.5",
|
|
||||||
description = "Velocity integration for LoNetwork",
|
|
||||||
authors = {"loki"}
|
|
||||||
)
|
|
||||||
public class LoVelocity {
|
|
||||||
|
|
||||||
private final ProxyServer server;
|
|
||||||
private final Logger logger;
|
|
||||||
private final Path dataDirectory;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public LoVelocity(ProxyServer server, Logger logger, @DataDirectory Path dataDirectory) {
|
|
||||||
this.server = server;
|
|
||||||
this.logger = logger;
|
|
||||||
this.dataDirectory = dataDirectory;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Subscribe
|
|
||||||
public void onProxyInitialization(ProxyInitializeEvent event) {
|
|
||||||
logger.info("LoVelocity loaded!");
|
|
||||||
logger.info("Version: 1.5.5");
|
|
||||||
|
|
||||||
registerCommands();
|
|
||||||
registerListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void registerCommands() {
|
|
||||||
CommandMeta hubMeta = server.getCommandManager().metaBuilder("hub")
|
|
||||||
.aliases("lobby")
|
|
||||||
.plugin(this)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
server.getCommandManager().register(hubMeta, new HubCommand(this));
|
|
||||||
|
|
||||||
logger.info("Commands registered: /hub, /lobby");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void registerListeners() {
|
|
||||||
server.getEventManager().register(this, new com.loki.lovelocity.listeners.ServerSwitchListener(this));
|
|
||||||
logger.info("Listeners registered");
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyServer getServer() {
|
|
||||||
return server;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Logger getLogger() {
|
|
||||||
return logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Path getDataDirectory() {
|
|
||||||
return dataDirectory;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,79 +0,0 @@
|
||||||
package com.loki.lovelocity.commands;
|
|
||||||
|
|
||||||
import com.loki.lovelocity.LoVelocity;
|
|
||||||
import com.velocitypowered.api.command.SimpleCommand;
|
|
||||||
import com.velocitypowered.api.proxy.Player;
|
|
||||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
|
|
||||||
public class HubCommand implements SimpleCommand {
|
|
||||||
|
|
||||||
private final LoVelocity plugin;
|
|
||||||
private final List<String> hubServers = List.of("hub", "lobby");
|
|
||||||
|
|
||||||
public HubCommand(LoVelocity plugin) {
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(Invocation invocation) {
|
|
||||||
if (!(invocation.source() instanceof Player player)) {
|
|
||||||
invocation.source().sendMessage(Component.text("This command is only for players!", NamedTextColor.RED));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Optional<RegisteredServer> currentServer = player.getCurrentServer().map(s -> s.getServer());
|
|
||||||
|
|
||||||
if (currentServer.isEmpty()) {
|
|
||||||
player.sendMessage(Component.text("Failed to determine current server!", NamedTextColor.RED));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String currentServerName = currentServer.get().getServerInfo().getName().toLowerCase();
|
|
||||||
|
|
||||||
if (isHubServer(currentServerName)) {
|
|
||||||
player.sendMessage(Component.text("You are already on the hub!", NamedTextColor.YELLOW));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Optional<RegisteredServer> hubServer = findHubServer();
|
|
||||||
|
|
||||||
if (hubServer.isEmpty()) {
|
|
||||||
player.sendMessage(Component.text("Hub server not found!", NamedTextColor.RED));
|
|
||||||
plugin.getLogger().warn("Hub server not found! Available servers: " +
|
|
||||||
plugin.getServer().getAllServers().stream()
|
|
||||||
.map(s -> s.getServerInfo().getName())
|
|
||||||
.toList());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
player.sendMessage(Component.text("Teleporting to hub...", NamedTextColor.GREEN));
|
|
||||||
|
|
||||||
player.createConnectionRequest(hubServer.get()).fireAndForget();
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isHubServer(String serverName) {
|
|
||||||
return hubServers.stream().anyMatch(hub -> serverName.contains(hub));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Optional<RegisteredServer> findHubServer() {
|
|
||||||
return plugin.getServer().getAllServers().stream()
|
|
||||||
.filter(server -> isHubServer(server.getServerInfo().getName().toLowerCase()))
|
|
||||||
.findFirst();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompletableFuture<List<String>> suggestAsync(Invocation invocation) {
|
|
||||||
return CompletableFuture.completedFuture(List.of());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasPermission(Invocation invocation) {
|
|
||||||
return invocation.source().hasPermission("lovelocity.hub");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
package com.loki.lovelocity.listeners;
|
|
||||||
|
|
||||||
import com.google.common.io.ByteArrayDataOutput;
|
|
||||||
import com.google.common.io.ByteStreams;
|
|
||||||
import com.loki.lovelocity.LoVelocity;
|
|
||||||
import com.velocitypowered.api.event.PostOrder;
|
|
||||||
import com.velocitypowered.api.event.Subscribe;
|
|
||||||
import com.velocitypowered.api.event.connection.DisconnectEvent;
|
|
||||||
import com.velocitypowered.api.event.player.ServerConnectedEvent;
|
|
||||||
import com.velocitypowered.api.proxy.Player;
|
|
||||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
public class ServerSwitchListener {
|
|
||||||
|
|
||||||
private final LoVelocity plugin;
|
|
||||||
private static final String CHANNEL = "lohub:switch";
|
|
||||||
|
|
||||||
public ServerSwitchListener(LoVelocity plugin) {
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Subscribe(order = PostOrder.LAST)
|
|
||||||
public void onServerConnected(ServerConnectedEvent event) {
|
|
||||||
Player player = event.getPlayer();
|
|
||||||
RegisteredServer toServer = event.getServer();
|
|
||||||
Optional<RegisteredServer> previousServer = event.getPreviousServer();
|
|
||||||
|
|
||||||
// If player is switching from another server (not first join)
|
|
||||||
if (previousServer.isPresent()) {
|
|
||||||
String fromServerName = previousServer.get().getServerInfo().getName();
|
|
||||||
String toServerName = toServer.getServerInfo().getName();
|
|
||||||
|
|
||||||
// Send plugin message to hub server about server switch
|
|
||||||
sendServerSwitchMessage(player, fromServerName, toServerName);
|
|
||||||
|
|
||||||
plugin.getLogger().info(player.getUsername() + " switched from " + fromServerName + " to " + toServerName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Subscribe(order = PostOrder.LAST)
|
|
||||||
public void onDisconnect(DisconnectEvent event) {
|
|
||||||
// Player left the network - handled by backend server
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendServerSwitchMessage(Player player, String fromServer, String toServer) {
|
|
||||||
// Create plugin message
|
|
||||||
ByteArrayDataOutput out = ByteStreams.newDataOutput();
|
|
||||||
out.writeUTF("ServerSwitch");
|
|
||||||
out.writeUTF(player.getUsername());
|
|
||||||
out.writeUTF(fromServer);
|
|
||||||
out.writeUTF(toServer);
|
|
||||||
|
|
||||||
byte[] data = out.toByteArray();
|
|
||||||
|
|
||||||
// Send to hub server (assuming hub server name is "hub")
|
|
||||||
plugin.getServer().getServer("hub").ifPresent(hubServer -> {
|
|
||||||
hubServer.sendPluginMessage(() -> CHANNEL, data);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
rootProject.name = "LoNetwork"
|
rootProject.name = "LoNetwork"
|
||||||
|
|
||||||
include("lohub")
|
include("lohub")
|
||||||
include("lovelocity")
|
|
||||||
|
|
|
||||||
|
|
@ -1,344 +0,0 @@
|
||||||
# ╔══════════════════════════════════════════════════════════════════════════════╗
|
|
||||||
# ║ LoHub Configuration - SpaceLegacy ║
|
|
||||||
# ║ Hub plugin for Paper/Folia 1.20.1+ ║
|
|
||||||
# ╚══════════════════════════════════════════════════════════════════════════════╝
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# | GENERAL SETTINGS |
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
|
|
||||||
check-updates: true
|
|
||||||
|
|
||||||
# Disabled worlds (plugin won't work there)
|
|
||||||
disabled-worlds:
|
|
||||||
invert: false
|
|
||||||
worlds:
|
|
||||||
- world_nether
|
|
||||||
- witp
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# | SPAWN SETTINGS |
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
|
|
||||||
spawn:
|
|
||||||
teleport-on-join: true
|
|
||||||
teleport-on-respawn: true
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# | WORLDGUARD INTEGRATION |
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
|
|
||||||
worldguard:
|
|
||||||
auto-create-region: true
|
|
||||||
region-radius: 100
|
|
||||||
region-name: "lohub_spawn"
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# | WORLD PROTECTION |
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
|
|
||||||
world_settings:
|
|
||||||
disable_hunger_loss: true
|
|
||||||
disable_fall_damage: true
|
|
||||||
disable_player_pvp: true
|
|
||||||
disable_void_death: true
|
|
||||||
disable_fire_damage: true
|
|
||||||
disable_drowning: true
|
|
||||||
disable_off_hand_swap: true
|
|
||||||
disable_weather_change: true
|
|
||||||
disable_death_message: true
|
|
||||||
disable_mob_spawning: true
|
|
||||||
disable_item_drop: true
|
|
||||||
disable_item_pickup: false
|
|
||||||
disable_block_break: true
|
|
||||||
disable_block_place: true
|
|
||||||
disable_block_interact: true
|
|
||||||
disable_block_burn: true
|
|
||||||
disable_block_fire_spread: true
|
|
||||||
disable_block_leaf_decay: true
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# | LAUNCHPAD |
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
|
|
||||||
launchpad:
|
|
||||||
enabled: true
|
|
||||||
launch_power: 3.0
|
|
||||||
launch_power_y: 1.0
|
|
||||||
top_block: STONE_PRESSURE_PLATE
|
|
||||||
bottom_block: REDSTONE_BLOCK
|
|
||||||
actions:
|
|
||||||
- '[SOUND] ENTITY_BAT_TAKEOFF'
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# | DOUBLE JUMP |
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
|
|
||||||
double_jump:
|
|
||||||
enabled: false
|
|
||||||
launch_power: 1.0
|
|
||||||
launch_power_y: 0.9
|
|
||||||
cooldown: 3
|
|
||||||
actions:
|
|
||||||
- '[SOUND] ENTITY_BAT_TAKEOFF'
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# | COMMAND BLOCKER |
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
|
|
||||||
command_block:
|
|
||||||
enabled: true
|
|
||||||
blocked_commands:
|
|
||||||
- /pl
|
|
||||||
- /plugins
|
|
||||||
- /?
|
|
||||||
- /bukkit:?
|
|
||||||
- /bukkit:plugins
|
|
||||||
- /bukkit:pl
|
|
||||||
- /bukkit:help
|
|
||||||
- /ver
|
|
||||||
- /version
|
|
||||||
- /bukkit:version
|
|
||||||
- /bukkit:ver
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# | ANTI-SWEAR |
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
|
|
||||||
anti_swear:
|
|
||||||
enabled: true
|
|
||||||
blocked_words:
|
|
||||||
- блять
|
|
||||||
- сука
|
|
||||||
- пизда
|
|
||||||
- хуй
|
|
||||||
- ебать
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# | PLAYER JOIN |
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
|
|
||||||
join_leave_messages:
|
|
||||||
enabled: true
|
|
||||||
join_message: "&#B798A8&l▶ ẲE9%player% &7присоединился"
|
|
||||||
quit_message: "&c&l◀ &#B798A8%player% &7вышел"
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# | SERVER SWITCH MESSAGES |
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
|
|
||||||
server_switch_messages:
|
|
||||||
enabled: true
|
|
||||||
switch_message: "&#B798A8&l▶ ẲE9%player% &7подключился к &#B798A8%server%"
|
|
||||||
server_names:
|
|
||||||
hub: "Хабу"
|
|
||||||
vanilla: "Ванилле"
|
|
||||||
grif: "Грифу"
|
|
||||||
darktown: "Даркауну"
|
|
||||||
|
|
||||||
join_events:
|
|
||||||
- "[CONSOLE] effect clear %player%"
|
|
||||||
- "[MESSAGE] &#B798A8&m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
||||||
- "[MESSAGE] &r"
|
|
||||||
- "[MESSAGE] &7Добро пожаловать, ẲE9&n%player%&r&7!"
|
|
||||||
- "[MESSAGE] &r"
|
|
||||||
- "[MESSAGE] &#B798A8&l♦ &#B798A8s&#B192AFp&#AA8BB5a&#A485BCc	E7EC2e⚖C9l⏔CFeB6BD6gⅵDCaE5EE3cẲE9y"
|
|
||||||
- "[MESSAGE] &#B798A8&l♦ САЙТ ẲE9spacelegacy.ru"
|
|
||||||
- "[MESSAGE] &#B798A8&l♦ DISCORD &f/discord"
|
|
||||||
- "[MESSAGE] &r"
|
|
||||||
- "[MESSAGE] &7&oЖелаем приятной игры!"
|
|
||||||
- "[MESSAGE] &#B798A8&m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
||||||
- "[TITLE] &#B798A8s&#B192AFp&#AA8BB5a&#A485BCc	E7EC2e⚖C9l⏔CFeB6BD6gⅵDCaE5EE3cẲE9y;&fДобро пожаловать!;1;3;1"
|
|
||||||
- "[SOUND] ENTITY_PLAYER_LEVELUP"
|
|
||||||
- "[GAMEMODE] survival"
|
|
||||||
|
|
||||||
join_settings:
|
|
||||||
spawn_join: true
|
|
||||||
heal: true
|
|
||||||
extinguish: true
|
|
||||||
clear_inventory: false
|
|
||||||
|
|
||||||
firework:
|
|
||||||
enabled: true
|
|
||||||
first_join_only: true
|
|
||||||
type: BALL_LARGE
|
|
||||||
power: 1
|
|
||||||
flicker: true
|
|
||||||
trail: true
|
|
||||||
colors:
|
|
||||||
- PURPLE
|
|
||||||
- WHITE
|
|
||||||
- BLUE
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# | CUSTOM JOIN ITEMS |
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
|
|
||||||
custom_join_items:
|
|
||||||
enabled: true
|
|
||||||
disable_inventory_movement: true
|
|
||||||
|
|
||||||
items:
|
|
||||||
parkour:
|
|
||||||
material: FEATHER
|
|
||||||
amount: 1
|
|
||||||
slot: 0
|
|
||||||
display_name: "&#B798A8&l♦ ẲE9Паркур"
|
|
||||||
lore:
|
|
||||||
- "&7Нажми ПКМ, чтобы перейти на паркур"
|
|
||||||
actions:
|
|
||||||
- "[MESSAGE] &#B798A8&m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
||||||
- "[MESSAGE] &#B798A8&l♦ &fТелепортация на ẲE9Паркур&f..."
|
|
||||||
- "[MESSAGE] &#B798A8&m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
||||||
- "[CONSOLE] ip forcejoin %player%"
|
|
||||||
- "[SOUND] ENTITY_ENDERMAN_TELEPORT"
|
|
||||||
|
|
||||||
server_selector:
|
|
||||||
material: NETHER_STAR
|
|
||||||
amount: 1
|
|
||||||
slot: 4
|
|
||||||
display_name: "&#B798A8&l♦ ẲE9Выбор Режима"
|
|
||||||
lore:
|
|
||||||
- "&7Нажми ПКМ, чтобы выбрать режим"
|
|
||||||
actions:
|
|
||||||
- "[MENU] serverselector"
|
|
||||||
|
|
||||||
player_hider:
|
|
||||||
material: LIME_DYE
|
|
||||||
amount: 1
|
|
||||||
slot: 8
|
|
||||||
display_name: '&a&l♦ ẲE9Игроки видны &7(ПКМ)'
|
|
||||||
lore:
|
|
||||||
- '&7Скрыть лишних игроков'
|
|
||||||
actions:
|
|
||||||
- "[PLAYER_HIDER]"
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# | PLAYER HIDER |
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
|
|
||||||
player_hider:
|
|
||||||
enabled: true
|
|
||||||
slot: 8
|
|
||||||
disable_inventory_movement: true
|
|
||||||
cooldown: 3
|
|
||||||
|
|
||||||
not_hidden:
|
|
||||||
material: LIME_DYE
|
|
||||||
amount: 1
|
|
||||||
display_name: '&a&l♦ ẲE9Игроки видны &7(ПКМ)'
|
|
||||||
lore:
|
|
||||||
- '&7Нажми, чтобы скрыть'
|
|
||||||
|
|
||||||
hidden:
|
|
||||||
material: GRAY_DYE
|
|
||||||
amount: 1
|
|
||||||
display_name: '&c&l♦ &#B798A8Игроки скрыты &7(ПКМ)'
|
|
||||||
lore:
|
|
||||||
- '&7Нажми, чтобы показать'
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# | SCOREBOARD |
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
|
|
||||||
scoreboard:
|
|
||||||
enabled: false
|
|
||||||
|
|
||||||
display_delay:
|
|
||||||
server_enter: 60
|
|
||||||
world_change: 40
|
|
||||||
|
|
||||||
refresh:
|
|
||||||
enabled: true
|
|
||||||
rate: 200
|
|
||||||
|
|
||||||
title: "&#B798A8s&#B192AFp&#AA8BB5a&#A485BCc	E7EC2e⚖C9l⏔CFeB6BD6gⅵDCaE5EE3cẲE9y"
|
|
||||||
lines:
|
|
||||||
- "&#B798A8&m━━━━━━━━━━━━━━━━━━━━━━"
|
|
||||||
- "&#B798A8◆ &fИгрокẲE9:"
|
|
||||||
- " &7%player%"
|
|
||||||
- ""
|
|
||||||
- "&#B798A8◆ &fРангẲE9:"
|
|
||||||
- " ẲE9%vault_rank%"
|
|
||||||
- ""
|
|
||||||
- "&#B798A8◆ &fОнлайнẲE9:"
|
|
||||||
- " &f%online% игроков"
|
|
||||||
- "&#B798A8&m━━━━━━━━━━━━━━━━━━━━━━"
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# | TABLIST |
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
|
|
||||||
tablist:
|
|
||||||
enabled: true
|
|
||||||
|
|
||||||
refresh:
|
|
||||||
enabled: true
|
|
||||||
rate: 400
|
|
||||||
|
|
||||||
header:
|
|
||||||
- ""
|
|
||||||
- " &#B798A8s&#B192AFp&#AA8BB5a&#A485BCc	E7EC2e⚖C9l⏔CFeB6BD6gⅵDCaE5EE3cẲE9y "
|
|
||||||
- "&fСервер: &#B798A8s&#B192AFp&#AA8BB5a&#A485BCc	E7EC2e⚖C9l⏔CFeB6BD6gⅵDCaE5EE3cẲE9y.ru &7| &fОнлайн: ẲE9%online%"
|
|
||||||
- ""
|
|
||||||
|
|
||||||
footer:
|
|
||||||
- ""
|
|
||||||
- "&#B798A8▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬"
|
|
||||||
- "&#B798A8◆ &fНаш DiscordẲE9: &7/discord"
|
|
||||||
- "&#B798A8◆ &fСайтẲE9: &fspacelegacy.ru"
|
|
||||||
- "&#B798A8▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬"
|
|
||||||
- ""
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# | ANNOUNCEMENTS |
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
|
|
||||||
announcements:
|
|
||||||
enabled: true
|
|
||||||
delay: 120
|
|
||||||
required_players: 1
|
|
||||||
|
|
||||||
sound:
|
|
||||||
enabled: true
|
|
||||||
value: BLOCK_NOTE_BLOCK_PLING
|
|
||||||
volume: 1.0
|
|
||||||
pitch: 1.5
|
|
||||||
|
|
||||||
announcements:
|
|
||||||
announce1:
|
|
||||||
- "&r"
|
|
||||||
- "&#B798A8▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬"
|
|
||||||
- "&#B798A8&l♦ ОБЪЯВЛЕНИЕ"
|
|
||||||
- "&7Добро пожаловать на &#B798A8s&#B192AFp&#AA8BB5a&#A485BCc	E7EC2e⚖C9l⏔CFeB6BD6gⅵDCaE5EE3cẲE9y&7!"
|
|
||||||
- "&7Приятной игры и честных сражений!"
|
|
||||||
- "&#B798A8▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬"
|
|
||||||
- "&r"
|
|
||||||
announce2:
|
|
||||||
- "&r"
|
|
||||||
- "&#B798A8▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬"
|
|
||||||
- "&#B798A8&l♦ ОБЪЯВЛЕНИЕ"
|
|
||||||
- "&7Наш Discord для связи с тех-поддержкой:"
|
|
||||||
- "ẲE9/discord или /links"
|
|
||||||
- "&#B798A8▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬"
|
|
||||||
- "&r"
|
|
||||||
announce3:
|
|
||||||
- "&r"
|
|
||||||
- "&#B798A8▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬"
|
|
||||||
- "&#B798A8&l♦ ОБЪЯВЛЕНИЕ"
|
|
||||||
- "&7Наш сайт: ẲE9spacelegacy.ru"
|
|
||||||
- "&7Следи за обновлениями сервера!"
|
|
||||||
- "&#B798A8▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬"
|
|
||||||
- "&r"
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# | CUSTOM COMMANDS |
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# All custom commands are now in commands.yml
|
|
||||||
# You can create custom commands with actions there
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# | MESSAGES |
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
|
|
||||||
# All messages are now in messages.yml
|
|
||||||
# You can customize the plugin prefix and all messages there
|
|
||||||
|
|
@ -59,6 +59,7 @@ public final class LoChat extends JavaPlugin {
|
||||||
// Команды и слушатели
|
// Команды и слушатели
|
||||||
registerCommands();
|
registerCommands();
|
||||||
registerListeners();
|
registerListeners();
|
||||||
|
registerPluginChannels();
|
||||||
|
|
||||||
// Автосообщения
|
// Автосообщения
|
||||||
autoMessageManager.start();
|
autoMessageManager.start();
|
||||||
|
|
@ -108,9 +109,11 @@ public final class LoChat extends JavaPlugin {
|
||||||
getCommand("reply").setExecutor(new ReplyCommand(this));
|
getCommand("reply").setExecutor(new ReplyCommand(this));
|
||||||
getCommand("ignore").setExecutor(new IgnoreCommand(this));
|
getCommand("ignore").setExecutor(new IgnoreCommand(this));
|
||||||
getCommand("unignore").setExecutor(new UnignoreCommand(this));
|
getCommand("unignore").setExecutor(new UnignoreCommand(this));
|
||||||
|
getCommand("ignorelist").setExecutor(new IgnoreListCommand(this));
|
||||||
getCommand("announce").setExecutor(new AnnounceCommand(this));
|
getCommand("announce").setExecutor(new AnnounceCommand(this));
|
||||||
getCommand("chatspy").setExecutor(new ChatSpyCommand(this));
|
getCommand("chatspy").setExecutor(new ChatSpyCommand(this));
|
||||||
getCommand("clearchat").setExecutor(new ClearChatCommand(this));
|
getCommand("clearchat").setExecutor(new ClearChatCommand(this));
|
||||||
|
getCommand("hub").setExecutor(new HubCommand(this));
|
||||||
|
|
||||||
NickCommand nickCmd = new NickCommand(this);
|
NickCommand nickCmd = new NickCommand(this);
|
||||||
getCommand("nick").setExecutor(nickCmd);
|
getCommand("nick").setExecutor(nickCmd);
|
||||||
|
|
@ -149,6 +152,11 @@ public final class LoChat extends JavaPlugin {
|
||||||
getLogger().info("Слушатели зарегистрированы (новая архитектура)");
|
getLogger().info("Слушатели зарегистрированы (новая архитектура)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void registerPluginChannels() {
|
||||||
|
getServer().getMessenger().registerOutgoingPluginChannel(this, "BungeeCord");
|
||||||
|
getLogger().info("BungeeCord plugin messaging channel registered");
|
||||||
|
}
|
||||||
|
|
||||||
public void reload() {
|
public void reload() {
|
||||||
configManager.reload();
|
configManager.reload();
|
||||||
messageConfig.reload();
|
messageConfig.reload();
|
||||||
|
|
|
||||||
107
src/main/java/com/loki/lochat/commands/CustomCommandManager.java
Normal file
107
src/main/java/com/loki/lochat/commands/CustomCommandManager.java
Normal file
|
|
@ -0,0 +1,107 @@
|
||||||
|
package com.loki.lochat.commands;
|
||||||
|
|
||||||
|
import com.loki.lochat.LoChat;
|
||||||
|
import com.loki.lochat.commands.custom.*;
|
||||||
|
import org.bukkit.command.CommandExecutor;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Менеджер кастомных команд
|
||||||
|
*/
|
||||||
|
public class CustomCommandManager {
|
||||||
|
|
||||||
|
private final LoChat plugin;
|
||||||
|
private final Map<String, CommandExecutor> commands;
|
||||||
|
|
||||||
|
public CustomCommandManager(LoChat plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.commands = new HashMap<>();
|
||||||
|
registerCommands();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Регистрирует все кастомные команды
|
||||||
|
*/
|
||||||
|
private void registerCommands() {
|
||||||
|
// Информационные команды
|
||||||
|
commands.put("help", new HelpCommand(plugin));
|
||||||
|
commands.put("rules", new RulesCommand(plugin));
|
||||||
|
commands.put("discord", new DiscordCommand(plugin));
|
||||||
|
|
||||||
|
// Утилиты
|
||||||
|
commands.put("coords", new CoordsCommand(plugin));
|
||||||
|
commands.put("ping", new PingCommand(plugin));
|
||||||
|
commands.put("stats", new StatsCommand(plugin));
|
||||||
|
|
||||||
|
// Чат команды
|
||||||
|
commands.put("me", new MeCommand(plugin));
|
||||||
|
commands.put("sounds", new SoundsCommand(plugin));
|
||||||
|
|
||||||
|
// TODO: Добавить остальные команды
|
||||||
|
// commands.put("website", new WebsiteCommand(plugin));
|
||||||
|
// commands.put("time", new TimeCommand(plugin));
|
||||||
|
// commands.put("list", new ListCommand(plugin));
|
||||||
|
// commands.put("top", new TopCommand(plugin));
|
||||||
|
// commands.put("afk", new AfkCommand(plugin));
|
||||||
|
// commands.put("back", new BackCommand(plugin));
|
||||||
|
// commands.put("broadcast", new BroadcastCommand(plugin));
|
||||||
|
// commands.put("maintenance", new MaintenanceCommand(plugin));
|
||||||
|
// commands.put("motd", new MotdCommand(plugin));
|
||||||
|
// commands.put("tps", new TpsCommand(plugin));
|
||||||
|
// commands.put("memory", new MemoryCommand(plugin));
|
||||||
|
// commands.put("version", new VersionCommand(plugin));
|
||||||
|
// commands.put("reload", new ReloadCommand(plugin));
|
||||||
|
// commands.put("automessage", new AutoMessageCommand(plugin));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Регистрирует команды в Bukkit
|
||||||
|
*/
|
||||||
|
public void registerBukkitCommands() {
|
||||||
|
for (Map.Entry<String, CommandExecutor> entry : commands.entrySet()) {
|
||||||
|
String commandName = entry.getKey();
|
||||||
|
CommandExecutor executor = entry.getValue();
|
||||||
|
|
||||||
|
if (plugin.getCommand(commandName) != null) {
|
||||||
|
plugin.getCommand(commandName).setExecutor(executor);
|
||||||
|
plugin.getLogger().info("Зарегистрирована кастомная команда: /" + commandName);
|
||||||
|
} else {
|
||||||
|
plugin.getLogger().warning("Не удалось зарегистрировать команду: /" + commandName +
|
||||||
|
" (не найдена в plugin.yml)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Получить исполнителя команды
|
||||||
|
*/
|
||||||
|
public CommandExecutor getCommandExecutor(String command) {
|
||||||
|
return commands.get(command.toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Проверить, является ли команда кастомной
|
||||||
|
*/
|
||||||
|
public boolean isCustomCommand(String command) {
|
||||||
|
return commands.containsKey(command.toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Получить все зарегистрированные команды
|
||||||
|
*/
|
||||||
|
public Map<String, CommandExecutor> getCommands() {
|
||||||
|
return new HashMap<>(commands);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Перезагрузить команды
|
||||||
|
*/
|
||||||
|
public void reload() {
|
||||||
|
commands.clear();
|
||||||
|
registerCommands();
|
||||||
|
registerBukkitCommands();
|
||||||
|
plugin.getLogger().info("Кастомные команды перезагружены!");
|
||||||
|
}
|
||||||
|
}
|
||||||
52
src/main/java/com/loki/lochat/commands/HubCommand.java
Normal file
52
src/main/java/com/loki/lochat/commands/HubCommand.java
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
package com.loki.lochat.commands;
|
||||||
|
|
||||||
|
import com.google.common.io.ByteArrayDataOutput;
|
||||||
|
import com.google.common.io.ByteStreams;
|
||||||
|
import com.loki.lochat.LoChat;
|
||||||
|
import com.loki.lochat.utils.ChatFormatter;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandExecutor;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public class HubCommand implements CommandExecutor {
|
||||||
|
|
||||||
|
private final LoChat plugin;
|
||||||
|
|
||||||
|
public HubCommand(LoChat plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||||
|
if (!(sender instanceof Player player)) {
|
||||||
|
sender.sendMessage(ChatFormatter.parse(plugin.getMessageConfig().get("general.players-only")));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if hub command is enabled
|
||||||
|
if (!plugin.getConfigManager().getBoolean("hub_command.enabled", true)) {
|
||||||
|
player.sendMessage(ChatFormatter.parse(plugin.getMessageConfig().get("general.command-disabled")));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
String hubServer = plugin.getConfigManager().getString("hub_command.server", "hub");
|
||||||
|
|
||||||
|
// Send player to hub server via BungeeCord
|
||||||
|
sendToServer(player, hubServer);
|
||||||
|
|
||||||
|
String message = plugin.getMessageConfig().get("hub.connecting")
|
||||||
|
.replace("%server%", hubServer);
|
||||||
|
player.sendMessage(ChatFormatter.parse(message));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendToServer(Player player, String server) {
|
||||||
|
ByteArrayDataOutput out = ByteStreams.newDataOutput();
|
||||||
|
out.writeUTF("Connect");
|
||||||
|
out.writeUTF(server);
|
||||||
|
|
||||||
|
player.sendPluginMessage(plugin, "BungeeCord", out.toByteArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
package com.loki.lochat.commands;
|
||||||
|
|
||||||
|
import com.loki.lochat.LoChat;
|
||||||
|
import com.loki.lochat.api.service.IgnoreService;
|
||||||
|
import com.loki.lochat.utils.ChatFormatter;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandExecutor;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Команда /ignorelist - показывает список игнорируемых игроков
|
||||||
|
*/
|
||||||
|
public class IgnoreListCommand implements CommandExecutor {
|
||||||
|
|
||||||
|
private final LoChat plugin;
|
||||||
|
private final IgnoreService ignoreService;
|
||||||
|
|
||||||
|
public IgnoreListCommand(LoChat plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.ignoreService = plugin.getServiceRegistry().get(IgnoreService.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command,
|
||||||
|
@NotNull String label, @NotNull String[] args) {
|
||||||
|
if (!(sender instanceof Player player)) {
|
||||||
|
sender.sendMessage("Только для игроков!");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<UUID> ignoredPlayers = ignoreService.getIgnoredPlayers(player.getUniqueId());
|
||||||
|
|
||||||
|
if (ignoredPlayers.isEmpty()) {
|
||||||
|
player.sendMessage(ChatFormatter.parse(plugin.getMessageConfig().get("ignore.list-empty")));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
player.sendMessage(ChatFormatter.parse(plugin.getMessageConfig().get("ignore.list-header")));
|
||||||
|
|
||||||
|
for (UUID ignoredUuid : ignoredPlayers) {
|
||||||
|
String playerName = com.loki.lochat.utils.PlayerUtil.getPlayerName(ignoredUuid);
|
||||||
|
if (playerName != null) {
|
||||||
|
player.sendMessage(ChatFormatter.parse("WCEEB• &#FFFFFF" + playerName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
player.sendMessage(ChatFormatter.parse(
|
||||||
|
plugin.getMessageConfig().get("ignore.list-footer")
|
||||||
|
.replace("{count}", String.valueOf(ignoredPlayers.size()))
|
||||||
|
));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
package com.loki.lochat.commands.custom;
|
||||||
|
|
||||||
|
import com.loki.lochat.LoChat;
|
||||||
|
import com.loki.lochat.utils.ChatFormatter;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandExecutor;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Команда координат игрока
|
||||||
|
*/
|
||||||
|
public class CoordsCommand implements CommandExecutor {
|
||||||
|
|
||||||
|
private final LoChat plugin;
|
||||||
|
|
||||||
|
public CoordsCommand(LoChat plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||||
|
if (!(sender instanceof Player player)) {
|
||||||
|
sender.sendMessage(ChatFormatter.parse("<red>Эта команда только для игроков!</red>"));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int x = (int) player.getLocation().getX();
|
||||||
|
int y = (int) player.getLocation().getY();
|
||||||
|
int z = (int) player.getLocation().getZ();
|
||||||
|
String world = player.getWorld().getName();
|
||||||
|
|
||||||
|
String message = String.format("""
|
||||||
|
<gradient:#FFA726:#FF9800>Ваши координаты:</gradient>
|
||||||
|
<gradient:#87CEEB:#4682B4>X:</gradient> <white>%d</white>
|
||||||
|
<gradient:#87CEEB:#4682B4>Y:</gradient> <white>%d</white>
|
||||||
|
<gradient:#87CEEB:#4682B4>Z:</gradient> <white>%d</white>
|
||||||
|
<gradient:#87CEEB:#4682B4>Мир:</gradient> <white>%s</white>
|
||||||
|
""", x, y, z, world);
|
||||||
|
|
||||||
|
player.sendMessage(ChatFormatter.parse(message));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
package com.loki.lochat.commands.custom;
|
||||||
|
|
||||||
|
import com.loki.lochat.LoChat;
|
||||||
|
import com.loki.lochat.utils.ChatFormatter;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandExecutor;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Команда Discord сервера
|
||||||
|
*/
|
||||||
|
public class DiscordCommand implements CommandExecutor {
|
||||||
|
|
||||||
|
private final LoChat plugin;
|
||||||
|
|
||||||
|
public DiscordCommand(LoChat plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||||
|
String discordLink = plugin.getConfig().getString("discord.invite-link", "discord.gg/example");
|
||||||
|
|
||||||
|
String message = String.format("""
|
||||||
|
<gradient:#7289DA:#5865F2>═══════ Наш Discord ═══════</gradient>
|
||||||
|
<gray>Присоединяйтесь к нашему сообществу!</gray>
|
||||||
|
|
||||||
|
<click:open_url:'https://%s'><gradient:#87CEEB:#4682B4>🔗 %s</gradient></click>
|
||||||
|
|
||||||
|
<gray>В Discord вы можете:</gray>
|
||||||
|
<white>•</white> <gray>Общаться с игроками</gray>
|
||||||
|
<white>•</white> <gray>Получать новости сервера</gray>
|
||||||
|
<white>•</white> <gray>Участвовать в событиях</gray>
|
||||||
|
<white>•</white> <gray>Получать поддержку</gray>
|
||||||
|
""", discordLink, discordLink);
|
||||||
|
|
||||||
|
sender.sendMessage(ChatFormatter.parse(message));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
package com.loki.lochat.commands.custom;
|
||||||
|
|
||||||
|
import com.loki.lochat.LoChat;
|
||||||
|
import com.loki.lochat.utils.ChatFormatter;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandExecutor;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Команда помощи сервера
|
||||||
|
*/
|
||||||
|
public class HelpCommand implements CommandExecutor {
|
||||||
|
|
||||||
|
private final LoChat plugin;
|
||||||
|
|
||||||
|
public HelpCommand(LoChat plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||||
|
String message = """
|
||||||
|
<gradient:#FFD700:#FFA500>═══════ Помощь по серверу ═══════</gradient>
|
||||||
|
<gradient:#87CEEB:#4682B4>/rules</gradient> <gray>- правила сервера</gray>
|
||||||
|
<gradient:#87CEEB:#4682B4>/discord</gradient> <gray>- наш Discord</gray>
|
||||||
|
<gradient:#87CEEB:#4682B4>/website</gradient> <gray>- официальный сайт</gray>
|
||||||
|
<gradient:#87CEEB:#4682B4>/coords</gradient> <gray>- ваши координаты</gray>
|
||||||
|
<gradient:#87CEEB:#4682B4>/time</gradient> <gray>- время на сервере</gray>
|
||||||
|
<gradient:#87CEEB:#4682B4>/ping</gradient> <gray>- ваш пинг</gray>
|
||||||
|
<gradient:#87CEEB:#4682B4>/list</gradient> <gray>- список игроков</gray>
|
||||||
|
<gradient:#87CEEB:#4682B4>/me <действие></gradient> <gray>- действие от третьего лица</gray>
|
||||||
|
<gradient:#87CEEB:#4682B4>/msg <игрок> <сообщение></gradient> <gray>- личное сообщение</gray>
|
||||||
|
<gradient:#87CEEB:#4682B4>/reply <сообщение></gradient> <gray>- ответить на ЛС</gray>
|
||||||
|
<gradient:#87CEEB:#4682B4>/ignore <игрок></gradient> <gray>- игнорировать игрока</gray>
|
||||||
|
<gradient:#87CEEB:#4682B4>/color <цвета></gradient> <gray>- градиентный ник</gray>
|
||||||
|
<gradient:#87CEEB:#4682B4>/prefix <текст></gradient> <gray>- кастомный префикс</gray>
|
||||||
|
""";
|
||||||
|
|
||||||
|
sender.sendMessage(ChatFormatter.parse(message));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
75
src/main/java/com/loki/lochat/commands/custom/MeCommand.java
Normal file
75
src/main/java/com/loki/lochat/commands/custom/MeCommand.java
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
package com.loki.lochat.commands.custom;
|
||||||
|
|
||||||
|
import com.loki.lochat.LoChat;
|
||||||
|
import com.loki.lochat.utils.ChatFormatter;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandExecutor;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Команда действия от третьего лица
|
||||||
|
*/
|
||||||
|
public class MeCommand implements CommandExecutor {
|
||||||
|
|
||||||
|
private final LoChat plugin;
|
||||||
|
|
||||||
|
public MeCommand(LoChat plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||||
|
if (!(sender instanceof Player player)) {
|
||||||
|
sender.sendMessage(ChatFormatter.parse("<red>Эта команда только для игроков!</red>"));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!player.hasPermission("chat.me")) {
|
||||||
|
player.sendMessage(ChatFormatter.parse("<red>У вас нет прав для использования этой команды!</red>"));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.length == 0) {
|
||||||
|
player.sendMessage(ChatFormatter.parse("<red>Использование: /me <действие></red>"));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверяем мут
|
||||||
|
if (plugin.getMuteService() != null && plugin.getMuteService().isMuted(player.getUniqueId())) {
|
||||||
|
String muteMessage = plugin.getMessagesConfig().getString("mute.you-muted",
|
||||||
|
"<red>Вы замучены!</red>");
|
||||||
|
player.sendMessage(ChatFormatter.parse(muteMessage));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Собираем действие из аргументов
|
||||||
|
String action = String.join(" ", args);
|
||||||
|
|
||||||
|
// Получаем отображаемое имя игрока (с градиентом если есть)
|
||||||
|
String displayName = player.getDisplayName();
|
||||||
|
if (plugin.getGradientModule() != null) {
|
||||||
|
displayName = plugin.getGradientModule().getFormattedName(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Форматируем сообщение действия
|
||||||
|
String message = String.format("<gray>* %s %s</gray>", displayName, action);
|
||||||
|
|
||||||
|
// Отправляем всем игрокам в радиусе (как локальный чат)
|
||||||
|
int radius = plugin.getConfig().getInt("chat.local.radius", 100);
|
||||||
|
|
||||||
|
for (Player onlinePlayer : Bukkit.getOnlinePlayers()) {
|
||||||
|
if (onlinePlayer.getWorld().equals(player.getWorld()) &&
|
||||||
|
onlinePlayer.getLocation().distance(player.getLocation()) <= radius) {
|
||||||
|
onlinePlayer.sendMessage(ChatFormatter.parse(message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Логируем действие
|
||||||
|
plugin.getLogger().info(String.format("[ME] %s: %s", player.getName(), action));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
package com.loki.lochat.commands.custom;
|
||||||
|
|
||||||
|
import com.loki.lochat.LoChat;
|
||||||
|
import com.loki.lochat.utils.ChatFormatter;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandExecutor;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Команда пинга игрока
|
||||||
|
*/
|
||||||
|
public class PingCommand implements CommandExecutor {
|
||||||
|
|
||||||
|
private final LoChat plugin;
|
||||||
|
|
||||||
|
public PingCommand(LoChat plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||||
|
if (!(sender instanceof Player player)) {
|
||||||
|
sender.sendMessage(ChatFormatter.parse("<red>Эта команда только для игроков!</red>"));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Если указан аргумент - показать пинг другого игрока
|
||||||
|
if (args.length > 0) {
|
||||||
|
if (!player.hasPermission("lochat.ping.others")) {
|
||||||
|
player.sendMessage(ChatFormatter.parse("<red>У вас нет прав для просмотра пинга других игроков!</red>"));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Player target = Bukkit.getPlayer(args[0]);
|
||||||
|
if (target == null || !target.isOnline()) {
|
||||||
|
player.sendMessage(ChatFormatter.parse("<red>Игрок не найден или не в сети!</red>"));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ping = target.getPing();
|
||||||
|
String color = getPingColor(ping);
|
||||||
|
|
||||||
|
String message = String.format(
|
||||||
|
"<gradient:#87CEEB:#4682B4>Пинг игрока %s:</gradient> <%s>%dмс</%s>",
|
||||||
|
target.getName(), color, ping, color
|
||||||
|
);
|
||||||
|
|
||||||
|
player.sendMessage(ChatFormatter.parse(message));
|
||||||
|
} else {
|
||||||
|
// Показать свой пинг
|
||||||
|
int ping = player.getPing();
|
||||||
|
String color = getPingColor(ping);
|
||||||
|
|
||||||
|
String message = String.format(
|
||||||
|
"<gradient:#87CEEB:#4682B4>Ваш пинг:</gradient> <%s>%dмс</%s>",
|
||||||
|
color, ping, color
|
||||||
|
);
|
||||||
|
|
||||||
|
player.sendMessage(ChatFormatter.parse(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getPingColor(int ping) {
|
||||||
|
if (ping < 50) return "green";
|
||||||
|
if (ping < 100) return "yellow";
|
||||||
|
if (ping < 200) return "gold";
|
||||||
|
return "red";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
package com.loki.lochat.commands.custom;
|
||||||
|
|
||||||
|
import com.loki.lochat.LoChat;
|
||||||
|
import com.loki.lochat.utils.ChatFormatter;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandExecutor;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Команда правил сервера
|
||||||
|
*/
|
||||||
|
public class RulesCommand implements CommandExecutor {
|
||||||
|
|
||||||
|
private final LoChat plugin;
|
||||||
|
|
||||||
|
public RulesCommand(LoChat plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||||
|
String message = """
|
||||||
|
<gradient:#FF6B6B:#FF4757>═══════ Правила сервера ═══════</gradient>
|
||||||
|
<white>1.</white> <gray>Не используйте читы и моды</gray>
|
||||||
|
<white>2.</white> <gray>Уважайте других игроков</gray>
|
||||||
|
<white>3.</white> <gray>Не спамьте в чате</gray>
|
||||||
|
<white>4.</white> <gray>Не стройте рядом с чужими постройками</gray>
|
||||||
|
<white>5.</white> <gray>Не используйте мат и оскорбления</gray>
|
||||||
|
<white>6.</white> <gray>Не рекламируйте другие серверы</gray>
|
||||||
|
<white>7.</white> <gray>Слушайтесь администрацию</gray>
|
||||||
|
<white>8.</white> <gray>Не злоупотребляйте багами</gray>
|
||||||
|
|
||||||
|
<gradient:#FFA726:#FF9800>Нарушение правил карается мутом или баном!</gradient>
|
||||||
|
<gradient:#87CEEB:#4682B4>За помощью обращайтесь к администрации</gradient>
|
||||||
|
""";
|
||||||
|
|
||||||
|
sender.sendMessage(ChatFormatter.parse(message));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
package com.loki.lochat.commands.custom;
|
||||||
|
|
||||||
|
import com.loki.lochat.LoChat;
|
||||||
|
import com.loki.lochat.utils.ChatFormatter;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandExecutor;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Команда управления звуками
|
||||||
|
*/
|
||||||
|
public class SoundsCommand implements CommandExecutor {
|
||||||
|
|
||||||
|
private final LoChat plugin;
|
||||||
|
|
||||||
|
public SoundsCommand(LoChat plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||||
|
if (!(sender instanceof Player player)) {
|
||||||
|
sender.sendMessage(ChatFormatter.parse("<red>Эта команда только для игроков!</red>"));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
String playerUUID = player.getUniqueId().toString();
|
||||||
|
boolean currentState = plugin.getPlayerData().getBoolean("players." + playerUUID + ".settings.sounds-enabled", true);
|
||||||
|
|
||||||
|
if (args.length == 0) {
|
||||||
|
// Показать текущее состояние
|
||||||
|
String status = currentState ? "<green>включены</green>" : "<red>отключены</red>";
|
||||||
|
String message = String.format(
|
||||||
|
"<gradient:#87CEEB:#4682B4>Звуки сейчас %s</gradient>\n" +
|
||||||
|
"<gray>Используйте /sounds on или /sounds off для изменения</gray>",
|
||||||
|
status
|
||||||
|
);
|
||||||
|
player.sendMessage(ChatFormatter.parse(message));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
String action = args[0].toLowerCase();
|
||||||
|
boolean newState;
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case "on", "включить", "вкл" -> {
|
||||||
|
newState = true;
|
||||||
|
player.sendMessage(ChatFormatter.parse("<green>Звуки включены!</green>"));
|
||||||
|
}
|
||||||
|
case "off", "отключить", "выкл" -> {
|
||||||
|
newState = false;
|
||||||
|
player.sendMessage(ChatFormatter.parse("<red>Звуки отключены!</red>"));
|
||||||
|
}
|
||||||
|
case "toggle", "переключить" -> {
|
||||||
|
newState = !currentState;
|
||||||
|
String status = newState ? "<green>включены</green>" : "<red>отключены</red>";
|
||||||
|
player.sendMessage(ChatFormatter.parse(String.format("Звуки %s!", status)));
|
||||||
|
}
|
||||||
|
default -> {
|
||||||
|
player.sendMessage(ChatFormatter.parse("""
|
||||||
|
<red>Неверное использование!</red>
|
||||||
|
<gray>Доступные команды:</gray>
|
||||||
|
<white>/sounds on</white> <gray>- включить звуки</gray>
|
||||||
|
<white>/sounds off</white> <gray>- отключить звуки</gray>
|
||||||
|
<white>/sounds toggle</white> <gray>- переключить</gray>
|
||||||
|
"""));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Сохраняем настройку
|
||||||
|
plugin.getPlayerData().set("players." + playerUUID + ".settings.sounds-enabled", newState);
|
||||||
|
plugin.savePlayerData();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
114
src/main/java/com/loki/lochat/commands/custom/StatsCommand.java
Normal file
114
src/main/java/com/loki/lochat/commands/custom/StatsCommand.java
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
package com.loki.lochat.commands.custom;
|
||||||
|
|
||||||
|
import com.loki.lochat.LoChat;
|
||||||
|
import com.loki.lochat.utils.ChatFormatter;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandExecutor;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Команда статистики чата
|
||||||
|
*/
|
||||||
|
public class StatsCommand implements CommandExecutor {
|
||||||
|
|
||||||
|
private final LoChat plugin;
|
||||||
|
|
||||||
|
public StatsCommand(LoChat plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||||
|
if (!sender.hasPermission("lochat.stats")) {
|
||||||
|
sender.sendMessage(ChatFormatter.parse("<red>У вас нет прав для просмотра статистики!</red>"));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.length > 0) {
|
||||||
|
// Статистика конкретного игрока
|
||||||
|
Player target = Bukkit.getPlayer(args[0]);
|
||||||
|
if (target == null) {
|
||||||
|
sender.sendMessage(ChatFormatter.parse("<red>Игрок не найден!</red>"));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
showPlayerStats(sender, target);
|
||||||
|
} else {
|
||||||
|
// Общая статистика сервера
|
||||||
|
showServerStats(sender);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showPlayerStats(CommandSender sender, Player target) {
|
||||||
|
// Получаем статистику игрока из конфига или базы данных
|
||||||
|
int messagesSent = plugin.getPlayerData().getInt("players." + target.getUniqueId() + ".messages-sent", 0);
|
||||||
|
int commandsUsed = plugin.getPlayerData().getInt("players." + target.getUniqueId() + ".commands-used", 0);
|
||||||
|
long playtime = plugin.getPlayerData().getLong("players." + target.getUniqueId() + ".total-playtime", 0);
|
||||||
|
|
||||||
|
String playtimeFormatted = formatTime(playtime);
|
||||||
|
|
||||||
|
String message = String.format("""
|
||||||
|
<gradient:#FFD700:#FFA500>═══ Статистика игрока %s ═══</gradient>
|
||||||
|
<gradient:#87CEEB:#4682B4>Сообщений отправлено:</gradient> <white>%d</white>
|
||||||
|
<gradient:#87CEEB:#4682B4>Команд использовано:</gradient> <white>%d</white>
|
||||||
|
<gradient:#87CEEB:#4682B4>Время в игре:</gradient> <white>%s</white>
|
||||||
|
<gradient:#87CEEB:#4682B4>Статус:</gradient> <green>В сети</green>
|
||||||
|
<gradient:#87CEEB:#4682B4>Пинг:</gradient> <yellow>%dмс</yellow>
|
||||||
|
""", target.getName(), messagesSent, commandsUsed, playtimeFormatted, target.getPing());
|
||||||
|
|
||||||
|
sender.sendMessage(ChatFormatter.parse(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showServerStats(CommandSender sender) {
|
||||||
|
// Получаем общую статистику сервера
|
||||||
|
int totalMessages = plugin.getStatisticsData().getInt("global.total-messages", 0);
|
||||||
|
int messagesToday = plugin.getStatisticsData().getInt("global.messages-today", 0);
|
||||||
|
int onlinePlayers = Bukkit.getOnlinePlayers().size();
|
||||||
|
int maxPlayers = Bukkit.getMaxPlayers();
|
||||||
|
|
||||||
|
String message = String.format("""
|
||||||
|
<gradient:#FFD700:#FFA500>═══ Статистика сервера ═══</gradient>
|
||||||
|
<gradient:#87CEEB:#4682B4>Всего сообщений:</gradient> <white>%d</white>
|
||||||
|
<gradient:#87CEEB:#4682B4>Сообщений сегодня:</gradient> <white>%d</white>
|
||||||
|
<gradient:#87CEEB:#4682B4>Игроков онлайн:</gradient> <white>%d/%d</white>
|
||||||
|
<gradient:#87CEEB:#4682B4>Активных мутов:</gradient> <white>%d</white>
|
||||||
|
<gradient:#87CEEB:#4682B4>TPS:</gradient> <green>%.1f</green>
|
||||||
|
""", totalMessages, messagesToday, onlinePlayers, maxPlayers,
|
||||||
|
getActiveMutesCount(), getCurrentTPS());
|
||||||
|
|
||||||
|
sender.sendMessage(ChatFormatter.parse(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String formatTime(long milliseconds) {
|
||||||
|
long seconds = milliseconds / 1000;
|
||||||
|
long minutes = seconds / 60;
|
||||||
|
long hours = minutes / 60;
|
||||||
|
long days = hours / 24;
|
||||||
|
|
||||||
|
if (days > 0) {
|
||||||
|
return String.format("%dд %dч %dм", days, hours % 24, minutes % 60);
|
||||||
|
} else if (hours > 0) {
|
||||||
|
return String.format("%dч %dм", hours, minutes % 60);
|
||||||
|
} else {
|
||||||
|
return String.format("%dм", minutes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getActiveMutesCount() {
|
||||||
|
return plugin.getMuteData().getConfigurationSection("active-mutes") != null ?
|
||||||
|
plugin.getMuteData().getConfigurationSection("active-mutes").getKeys(false).size() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private double getCurrentTPS() {
|
||||||
|
try {
|
||||||
|
return Bukkit.getTPS()[0];
|
||||||
|
} catch (Exception e) {
|
||||||
|
return 20.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -22,25 +22,69 @@ public class AdvancedMessageFilter {
|
||||||
"(.)\\1{3,}"
|
"(.)\\1{3,}"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Паттерн для скрытых ссылок (h t t p, w w w и т.д.)
|
||||||
|
private static final Pattern HIDDEN_URL_PATTERN = Pattern.compile(
|
||||||
|
"(?i)(h\\s*t\\s*t\\s*p|w\\s*w\\s*w|d\\s*o\\s*t\\s*c\\s*o\\s*m)",
|
||||||
|
Pattern.CASE_INSENSITIVE
|
||||||
|
);
|
||||||
|
|
||||||
|
// Паттерн для доменов без http
|
||||||
|
private static final Pattern DOMAIN_PATTERN = Pattern.compile(
|
||||||
|
"\\b([a-zA-Z0-9-]+\\.(com|net|org|ru|gg|me|io|xyz|tk|ml|ga|cf|gq))\\b",
|
||||||
|
Pattern.CASE_INSENSITIVE
|
||||||
|
);
|
||||||
|
|
||||||
private final FileConfiguration config;
|
private final FileConfiguration config;
|
||||||
private final List<String> whitelistedDomains;
|
private final List<String> whitelistedDomains;
|
||||||
private final List<String> blacklistedDomains;
|
private final List<String> blacklistedDomains;
|
||||||
|
private final CapsFilter capsFilter;
|
||||||
|
|
||||||
public AdvancedMessageFilter(FileConfiguration config) {
|
public AdvancedMessageFilter(FileConfiguration config) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.whitelistedDomains = config.getStringList("filters.url.whitelist");
|
this.whitelistedDomains = config.getStringList("filters.advertising.whitelist");
|
||||||
this.blacklistedDomains = config.getStringList("filters.url.blacklist");
|
this.blacklistedDomains = config.getStringList("filters.advertising.blacklist");
|
||||||
|
|
||||||
|
// Инициализация капс фильтра
|
||||||
|
int maxCapsPercent = config.getInt("filters.caps.max-percent", 70);
|
||||||
|
int minLength = config.getInt("filters.caps.min-length", 5);
|
||||||
|
boolean autoLowercase = config.getBoolean("filters.caps.auto-lowercase", true);
|
||||||
|
boolean blockMessage = config.getBoolean("filters.caps.block", false);
|
||||||
|
this.capsFilter = new CapsFilter(maxCapsPercent, minLength, autoLowercase, blockMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FilterResult filterMessage(Player player, String message) {
|
public FilterResult filterMessage(Player player, String message) {
|
||||||
if (config.getBoolean("filters.url.enabled", true)) {
|
// Капс фильтр
|
||||||
|
if (config.getBoolean("filters.caps.enabled", true)) {
|
||||||
|
String filtered = capsFilter.filter(player, message);
|
||||||
|
if (filtered == null) {
|
||||||
|
return new FilterResult(false, message, "&#FF6B6BНе кричите в чате!");
|
||||||
|
}
|
||||||
|
message = filtered;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Анти-реклама (объединенная проверка)
|
||||||
|
if (config.getBoolean("filters.advertising.enabled", true)) {
|
||||||
|
// URL фильтр
|
||||||
FilterResult urlResult = filterUrls(player, message);
|
FilterResult urlResult = filterUrls(player, message);
|
||||||
if (!urlResult.allowed()) {
|
if (!urlResult.allowed()) {
|
||||||
return urlResult;
|
return urlResult;
|
||||||
}
|
}
|
||||||
message = urlResult.filteredMessage();
|
message = urlResult.filteredMessage();
|
||||||
|
|
||||||
|
// Скрытые ссылки
|
||||||
|
FilterResult hiddenResult = filterHiddenUrls(player, message);
|
||||||
|
if (!hiddenResult.allowed()) {
|
||||||
|
return hiddenResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Домены без http
|
||||||
|
FilterResult domainResult = filterDomains(player, message);
|
||||||
|
if (!domainResult.allowed()) {
|
||||||
|
return domainResult;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IP фильтр
|
||||||
if (config.getBoolean("filters.ip.enabled", true)) {
|
if (config.getBoolean("filters.ip.enabled", true)) {
|
||||||
FilterResult ipResult = filterIPs(player, message);
|
FilterResult ipResult = filterIPs(player, message);
|
||||||
if (!ipResult.allowed()) {
|
if (!ipResult.allowed()) {
|
||||||
|
|
@ -49,6 +93,7 @@ public class AdvancedMessageFilter {
|
||||||
message = ipResult.filteredMessage();
|
message = ipResult.filteredMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Повторяющиеся символы
|
||||||
if (config.getBoolean("filters.repeat.enabled", true)) {
|
if (config.getBoolean("filters.repeat.enabled", true)) {
|
||||||
message = filterRepeatingChars(message);
|
message = filterRepeatingChars(message);
|
||||||
}
|
}
|
||||||
|
|
@ -138,6 +183,70 @@ public class AdvancedMessageFilter {
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Фильтрует скрытые ссылки (h t t p, w w w и т.д.)
|
||||||
|
*/
|
||||||
|
private FilterResult filterHiddenUrls(Player player, String message) {
|
||||||
|
if (!config.getBoolean("filters.advertising.block-hidden-urls", true)) {
|
||||||
|
return new FilterResult(true, message, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.hasPermission("lochat.bypass.hiddenurls")) {
|
||||||
|
return new FilterResult(true, message, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
Matcher matcher = HIDDEN_URL_PATTERN.matcher(message);
|
||||||
|
if (matcher.find()) {
|
||||||
|
return new FilterResult(false, message,
|
||||||
|
config.getString("filters.advertising.blocked-message", "&#FF6B6BРеклама запрещена!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new FilterResult(true, message, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Фильтрует домены без http (example.com, discord.gg и т.д.)
|
||||||
|
*/
|
||||||
|
private FilterResult filterDomains(Player player, String message) {
|
||||||
|
if (!config.getBoolean("filters.advertising.block-domains", true)) {
|
||||||
|
return new FilterResult(true, message, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.hasPermission("lochat.bypass.domains")) {
|
||||||
|
return new FilterResult(true, message, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
Matcher matcher = DOMAIN_PATTERN.matcher(message);
|
||||||
|
|
||||||
|
while (matcher.find()) {
|
||||||
|
String domain = matcher.group();
|
||||||
|
|
||||||
|
// Проверяем whitelist
|
||||||
|
if (!whitelistedDomains.isEmpty()) {
|
||||||
|
boolean isWhitelisted = whitelistedDomains.stream()
|
||||||
|
.anyMatch(d -> domain.toLowerCase().contains(d.toLowerCase()));
|
||||||
|
|
||||||
|
if (!isWhitelisted) {
|
||||||
|
return new FilterResult(false, message,
|
||||||
|
config.getString("filters.advertising.blocked-message", "&#FF6B6BРеклама запрещена!"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверяем blacklist
|
||||||
|
if (!blacklistedDomains.isEmpty()) {
|
||||||
|
boolean isBlacklisted = blacklistedDomains.stream()
|
||||||
|
.anyMatch(d -> domain.toLowerCase().contains(d.toLowerCase()));
|
||||||
|
|
||||||
|
if (isBlacklisted) {
|
||||||
|
return new FilterResult(false, message,
|
||||||
|
config.getString("filters.advertising.blocked-message", "&#FF6B6BРеклама запрещена!"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new FilterResult(true, message, null);
|
||||||
|
}
|
||||||
|
|
||||||
public record FilterResult(boolean allowed, String filteredMessage, String blockReason) {
|
public record FilterResult(boolean allowed, String filteredMessage, String blockReason) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
83
src/main/java/com/loki/lochat/core/filter/CapsFilter.java
Normal file
83
src/main/java/com/loki/lochat/core/filter/CapsFilter.java
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
package com.loki.lochat.core.filter;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Фильтр капса (заглавных букв)
|
||||||
|
*/
|
||||||
|
public class CapsFilter {
|
||||||
|
private final int maxCapsPercent;
|
||||||
|
private final int minLength;
|
||||||
|
private final boolean autoLowercase;
|
||||||
|
private final boolean blockMessage;
|
||||||
|
|
||||||
|
public CapsFilter(int maxCapsPercent, int minLength, boolean autoLowercase, boolean blockMessage) {
|
||||||
|
this.maxCapsPercent = maxCapsPercent;
|
||||||
|
this.minLength = minLength;
|
||||||
|
this.autoLowercase = autoLowercase;
|
||||||
|
this.blockMessage = blockMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Проверяет и обрабатывает сообщение с капсом
|
||||||
|
*
|
||||||
|
* @return обработанное сообщение или null если заблокировано
|
||||||
|
*/
|
||||||
|
public String filter(Player player, String message) {
|
||||||
|
// Bypass для админов
|
||||||
|
if (player.hasPermission("lochat.bypass.caps")) {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Игнорируем короткие сообщения
|
||||||
|
if (message.length() < minLength) {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Подсчитываем процент заглавных букв
|
||||||
|
int totalLetters = 0;
|
||||||
|
int capsLetters = 0;
|
||||||
|
|
||||||
|
for (char c : message.toCharArray()) {
|
||||||
|
if (Character.isLetter(c)) {
|
||||||
|
totalLetters++;
|
||||||
|
if (Character.isUpperCase(c)) {
|
||||||
|
capsLetters++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Если букв мало, пропускаем
|
||||||
|
if (totalLetters < 3) {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
int capsPercent = (capsLetters * 100) / totalLetters;
|
||||||
|
|
||||||
|
// Если капса больше лимита
|
||||||
|
if (capsPercent > maxCapsPercent) {
|
||||||
|
if (blockMessage) {
|
||||||
|
return null; // Блокируем сообщение
|
||||||
|
} else if (autoLowercase) {
|
||||||
|
// Понижаем регистр (первая буква заглавная)
|
||||||
|
return capitalizeFirst(message.toLowerCase());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Делает первую букву заглавной
|
||||||
|
*/
|
||||||
|
private String capitalizeFirst(String text) {
|
||||||
|
if (text == null || text.isEmpty()) {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
return Character.toUpperCase(text.charAt(0)) + text.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxCapsPercent() {
|
||||||
|
return maxCapsPercent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -32,20 +32,40 @@ public class MuteServiceImpl implements MuteService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mute(UUID uuid, String playerName, long duration, String reason, String mutedBy) {
|
public void mute(UUID uuid, String playerName, long duration, String reason, String mutedBy) {
|
||||||
|
if (uuid == null) {
|
||||||
|
plugin.getLogger().warning("Attempted to mute player with null UUID");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (playerName == null || playerName.isEmpty()) {
|
||||||
|
plugin.getLogger().warning("Attempted to mute player with null or empty name");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
long endTime = duration > 0 ? System.currentTimeMillis() + duration : 0;
|
long endTime = duration > 0 ? System.currentTimeMillis() + duration : 0;
|
||||||
MuteData data = new MuteData(uuid, playerName, endTime, reason, mutedBy);
|
MuteData data = new MuteData(uuid, playerName, endTime, reason, mutedBy);
|
||||||
mutes.put(uuid, data);
|
mutes.put(uuid, data);
|
||||||
|
|
||||||
historyManager.addEntry(uuid, playerName, duration, reason, mutedBy);
|
historyManager.addEntry(uuid, playerName, duration, reason, mutedBy);
|
||||||
saveAsync();
|
saveAsync();
|
||||||
|
|
||||||
|
plugin.getLogger().info("Player " + playerName + " muted by " + mutedBy +
|
||||||
|
" for " + (duration > 0 ? formatTime(duration) : "permanent") +
|
||||||
|
(reason != null ? " (reason: " + reason + ")" : ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean unmute(UUID uuid, String unmutedBy) {
|
public boolean unmute(UUID uuid, String unmutedBy) {
|
||||||
|
if (uuid == null) {
|
||||||
|
plugin.getLogger().warning("Attempted to unmute player with null UUID");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
MuteData removed = mutes.remove(uuid);
|
MuteData removed = mutes.remove(uuid);
|
||||||
if (removed != null) {
|
if (removed != null) {
|
||||||
historyManager.updateUnmute(uuid, unmutedBy);
|
historyManager.updateUnmute(uuid, unmutedBy);
|
||||||
saveAsync();
|
saveAsync();
|
||||||
|
plugin.getLogger().info("Player " + removed.getPlayerName() + " unmuted by " + unmutedBy);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -53,6 +73,10 @@ public class MuteServiceImpl implements MuteService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isMuted(UUID uuid) {
|
public boolean isMuted(UUID uuid) {
|
||||||
|
if (uuid == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
MuteData data = mutes.get(uuid);
|
MuteData data = mutes.get(uuid);
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -61,6 +85,7 @@ public class MuteServiceImpl implements MuteService {
|
||||||
if (isExpired(data)) {
|
if (isExpired(data)) {
|
||||||
mutes.remove(uuid);
|
mutes.remove(uuid);
|
||||||
saveAsync();
|
saveAsync();
|
||||||
|
plugin.getLogger().info("Mute expired for player " + data.getPlayerName());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,9 @@ public class ChatMessage {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ChatMessage create(Player sender, String rawMessage) {
|
public static ChatMessage create(Player sender, String rawMessage) {
|
||||||
// Определяем тип чата
|
// С "!" = глобальный чат
|
||||||
boolean isGlobal = rawMessage.startsWith("!") &&
|
// Без "!" = локальный чат
|
||||||
sender.hasPermission("chat.global.use");
|
boolean isGlobal = rawMessage.startsWith("!");
|
||||||
|
|
||||||
String content = isGlobal ?
|
String content = isGlobal ?
|
||||||
rawMessage.substring(1).trim() :
|
rawMessage.substring(1).trim() :
|
||||||
|
|
|
||||||
|
|
@ -28,100 +28,88 @@ public class GradientConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadConfig() {
|
private void loadConfig() {
|
||||||
configFile = new File(plugin.getDataFolder(), "gradient-config.yml");
|
// Читаем из главного config.yml вместо отдельного файла
|
||||||
if (!configFile.exists()) {
|
config = plugin.getConfig();
|
||||||
plugin.saveResource("gradient-config.yml", false);
|
plugin.getLogger().info("Gradient конфиг загружен из config.yml");
|
||||||
}
|
|
||||||
config = YamlConfiguration.loadConfiguration(configFile);
|
|
||||||
|
|
||||||
// Загружаем дефолты
|
|
||||||
InputStream defStream = plugin.getResource("gradient-config.yml");
|
|
||||||
if (defStream != null) {
|
|
||||||
YamlConfiguration defConfig = YamlConfiguration.loadConfiguration(
|
|
||||||
new InputStreamReader(defStream, StandardCharsets.UTF_8));
|
|
||||||
config.setDefaults(defConfig);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reload() {
|
public void reload() {
|
||||||
|
plugin.reloadConfig();
|
||||||
this.mainConfig = plugin.getConfig();
|
this.mainConfig = plugin.getConfig();
|
||||||
loadConfig();
|
this.config = plugin.getConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void save() {
|
public void save() {
|
||||||
try {
|
// Сохранение не требуется, используем главный конфиг
|
||||||
config.save(configFile);
|
plugin.saveConfig();
|
||||||
} catch (IOException e) {
|
|
||||||
plugin.getLogger().warning("Ошибка сохранения gradient-config.yml: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEnabled() {
|
public boolean isEnabled() {
|
||||||
return config.getBoolean("enabled", true);
|
return config.getBoolean("gradient.enabled", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getMaxColors() {
|
public int getMaxColors() {
|
||||||
return config.getInt("max-colors", 7);
|
return config.getInt("gradient.max-colors", 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getMinColors() {
|
public int getMinColors() {
|
||||||
return config.getInt("min-colors", 1);
|
return config.getInt("gradient.min-colors", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getPricePerColor() {
|
public int getPricePerColor() {
|
||||||
return config.getInt("price-per-color", 50);
|
return config.getInt("gradient.price-per-color", 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getPrefixPrice() {
|
public int getPrefixPrice() {
|
||||||
return config.getInt("prefix-price", 500);
|
return config.getInt("gradient.prefix-price", 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPrefixOneTimePurchase() {
|
public boolean isPrefixOneTimePurchase() {
|
||||||
return config.getBoolean("prefix-one-time-purchase", true);
|
return config.getBoolean("gradient.prefix-one-time-purchase", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getColorCooldown() {
|
public int getColorCooldown() {
|
||||||
return config.getInt("color-cooldown", 60);
|
return config.getInt("gradient.color-cooldown", 60);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getPrefixCooldown() {
|
public int getPrefixCooldown() {
|
||||||
return config.getInt("prefix-cooldown", 300);
|
return config.getInt("gradient.prefix-cooldown", 120);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getMaxPrefixLength() {
|
public int getMaxPrefixLength() {
|
||||||
return config.getInt("max-prefix-length", 7);
|
return config.getInt("gradient.max-prefix-length", 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPrefixFormat() {
|
public String getPrefixFormat() {
|
||||||
return config.getString("prefix-format", "[{prefix}] ");
|
return config.getString("gradient.prefix-format", "[{prefix}] ");
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isGradientOnPrefix() {
|
public boolean isGradientOnPrefix() {
|
||||||
return config.getBoolean("gradient-on-prefix", true);
|
return config.getBoolean("gradient.gradient-on-prefix", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isGradientOnLuckPermsPrefix() {
|
public boolean isGradientOnLuckPermsPrefix() {
|
||||||
return config.getBoolean("gradient-on-luckperms-prefix", true);
|
return config.getBoolean("gradient.gradient-on-luckperms-prefix", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isContinuousGradient() {
|
public boolean isContinuousGradient() {
|
||||||
return config.getBoolean("continuous-gradient", true);
|
return config.getBoolean("gradient.continuous-gradient", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isUseLegacyRgbFormat() {
|
public boolean isUseLegacyRgbFormat() {
|
||||||
return config.getBoolean("use-legacy-rgb-format", true);
|
return config.getBoolean("gradient.use-legacy-rgb-format", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getStorageType() {
|
public String getStorageType() {
|
||||||
return config.getString("storage-type", "YAML");
|
return config.getString("gradient.storage-type", "file");
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSqliteFile() {
|
public String getSqliteFile() {
|
||||||
return config.getString("sqlite-file", "gradient-data.db");
|
return config.getString("gradient.sqlite-file", "gradient-data.db");
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getPrefixBlacklist() {
|
public List<String> getPrefixBlacklist() {
|
||||||
return config.getStringList("prefix-blacklist");
|
return config.getStringList("gradient.prefix-blacklist");
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPrefixBlacklisted(String prefix) {
|
public boolean isPrefixBlacklisted(String prefix) {
|
||||||
|
|
|
||||||
|
|
@ -27,13 +27,13 @@ public class GradientMessages {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadMessages() {
|
private void loadMessages() {
|
||||||
messagesFile = new File(plugin.getDataFolder(), "gradient-messages.yml");
|
messagesFile = new File(plugin.getDataFolder(), "messages.yml");
|
||||||
if (!messagesFile.exists()) {
|
if (!messagesFile.exists()) {
|
||||||
plugin.saveResource("gradient-messages.yml", false);
|
plugin.saveResource("messages.yml", false);
|
||||||
}
|
}
|
||||||
messages = YamlConfiguration.loadConfiguration(messagesFile);
|
messages = YamlConfiguration.loadConfiguration(messagesFile);
|
||||||
|
|
||||||
InputStream defStream = plugin.getResource("gradient-messages.yml");
|
InputStream defStream = plugin.getResource("messages.yml");
|
||||||
if (defStream != null) {
|
if (defStream != null) {
|
||||||
YamlConfiguration defConfig = YamlConfiguration.loadConfiguration(
|
YamlConfiguration defConfig = YamlConfiguration.loadConfiguration(
|
||||||
new InputStreamReader(defStream, StandardCharsets.UTF_8));
|
new InputStreamReader(defStream, StandardCharsets.UTF_8));
|
||||||
|
|
@ -49,7 +49,7 @@ public class GradientMessages {
|
||||||
* Получает сообщение как строку с MiniMessage тегами
|
* Получает сообщение как строку с MiniMessage тегами
|
||||||
*/
|
*/
|
||||||
public String get(String key) {
|
public String get(String key) {
|
||||||
String message = messages.getString(key, "&#FF0000Сообщение не найдено: " + key);
|
String message = messages.getString("gradient." + key, "&#FF0000Сообщение не найдено: " + key);
|
||||||
return ChatFormatter.convertAllColors(message);
|
return ChatFormatter.convertAllColors(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -57,7 +57,7 @@ public class GradientMessages {
|
||||||
* Получает сообщение как строку с заменами
|
* Получает сообщение как строку с заменами
|
||||||
*/
|
*/
|
||||||
public String get(String key, String... replacements) {
|
public String get(String key, String... replacements) {
|
||||||
String message = messages.getString(key, "&#FF0000Сообщение не найдено: " + key);
|
String message = messages.getString("gradient." + key, "&#FF0000Сообщение не найдено: " + key);
|
||||||
for (int i = 0; i < replacements.length; i += 2) {
|
for (int i = 0; i < replacements.length; i += 2) {
|
||||||
if (i + 1 < replacements.length) {
|
if (i + 1 < replacements.length) {
|
||||||
message = message.replace("{" + replacements[i] + "}", replacements[i + 1]);
|
message = message.replace("{" + replacements[i] + "}", replacements[i + 1]);
|
||||||
|
|
|
||||||
|
|
@ -54,23 +54,44 @@ public class ChatEventListener implements Listener {
|
||||||
}
|
}
|
||||||
|
|
||||||
String filteredMessage = filterResult.filteredMessage();
|
String filteredMessage = filterResult.filteredMessage();
|
||||||
event.message(Component.text(filteredMessage));
|
|
||||||
|
|
||||||
event.renderer(new EnhancedChatRenderer(sender, event.message()));
|
// Определяем тип чата
|
||||||
|
boolean isGlobal = message.startsWith("!");
|
||||||
|
|
||||||
|
event.message(com.loki.lochat.utils.ChatFormatter.parse(filteredMessage));
|
||||||
|
|
||||||
|
event.renderer(new EnhancedChatRenderer(sender, event.message(), isGlobal));
|
||||||
}
|
}
|
||||||
|
|
||||||
private class EnhancedChatRenderer implements ChatRenderer {
|
private class EnhancedChatRenderer implements ChatRenderer {
|
||||||
private final Player sender;
|
private final Player sender;
|
||||||
private final Component originalMessage;
|
private final Component originalMessage;
|
||||||
|
private final boolean isGlobal;
|
||||||
|
|
||||||
public EnhancedChatRenderer(Player sender, Component originalMessage) {
|
public EnhancedChatRenderer(Player sender, Component originalMessage, boolean isGlobal) {
|
||||||
this.sender = sender;
|
this.sender = sender;
|
||||||
this.originalMessage = originalMessage;
|
this.originalMessage = originalMessage;
|
||||||
|
this.isGlobal = isGlobal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Component render(Player source, Component sourceDisplayName, Component message, Audience viewer) {
|
public Component render(Player source, Component sourceDisplayName, Component message, Audience viewer) {
|
||||||
String prefix = plugin.getConfig().getString("chat.global.prefix", "[G]");
|
// Префикс в зависимости от типа чата
|
||||||
|
Component prefixComponent;
|
||||||
|
if (isGlobal) {
|
||||||
|
// [G] с желтой буквой G
|
||||||
|
prefixComponent = Component.text("[")
|
||||||
|
.color(net.kyori.adventure.text.format.NamedTextColor.GRAY)
|
||||||
|
.append(Component.text("G").color(net.kyori.adventure.text.format.NamedTextColor.GOLD))
|
||||||
|
.append(Component.text("]").color(net.kyori.adventure.text.format.NamedTextColor.GRAY));
|
||||||
|
} else {
|
||||||
|
// [L] с голубой буквой L
|
||||||
|
prefixComponent = Component.text("[")
|
||||||
|
.color(net.kyori.adventure.text.format.NamedTextColor.GRAY)
|
||||||
|
.append(Component.text("L").color(net.kyori.adventure.text.format.NamedTextColor.AQUA))
|
||||||
|
.append(Component.text("]").color(net.kyori.adventure.text.format.NamedTextColor.GRAY));
|
||||||
|
}
|
||||||
|
|
||||||
Component playerComponent = createPlayerComponent(source, sourceDisplayName);
|
Component playerComponent = createPlayerComponent(source, sourceDisplayName);
|
||||||
Component processedMessage = message;
|
Component processedMessage = message;
|
||||||
|
|
||||||
|
|
@ -82,9 +103,10 @@ public class ChatEventListener implements Listener {
|
||||||
processedMessage = mentionHandler.processMentions(processedMessage, source, viewerPlayer);
|
processedMessage = mentionHandler.processMentions(processedMessage, source, viewerPlayer);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Component.text(prefix + " ")
|
return prefixComponent
|
||||||
|
.append(Component.text(" "))
|
||||||
.append(playerComponent)
|
.append(playerComponent)
|
||||||
.append(Component.text(": "))
|
.append(Component.text(": ").color(net.kyori.adventure.text.format.NamedTextColor.GRAY))
|
||||||
.append(processedMessage);
|
.append(processedMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -129,7 +151,8 @@ public class ChatEventListener implements Listener {
|
||||||
|
|
||||||
private Component processUrls(Component message) {
|
private Component processUrls(Component message) {
|
||||||
String plainText = PlainTextComponentSerializer.plainText().serialize(message);
|
String plainText = PlainTextComponentSerializer.plainText().serialize(message);
|
||||||
String urlPattern = "(https?://[\\w\\-._~:/?#\\[\\]@!35538117-c5a8-4bfe-b9f2-b0dcf9374222'()*+,;=%]+)";
|
// Fixed regex: escape the dash in character class to avoid illegal range
|
||||||
|
String urlPattern = "(https?://[\\w\\-._~:/?#\\[\\]@!$&'()*+,;=%]+)";
|
||||||
java.util.regex.Pattern pattern = java.util.regex.Pattern.compile(urlPattern);
|
java.util.regex.Pattern pattern = java.util.regex.Pattern.compile(urlPattern);
|
||||||
java.util.regex.Matcher matcher = pattern.matcher(plainText);
|
java.util.regex.Matcher matcher = pattern.matcher(plainText);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,20 +31,15 @@ public class AutoMessageManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadMessages() {
|
private void loadMessages() {
|
||||||
File file = new File(plugin.getDataFolder(), "automessages.yml");
|
FileConfiguration config = plugin.getConfig();
|
||||||
if (!file.exists()) {
|
|
||||||
plugin.saveResource("automessages.yml", false);
|
|
||||||
}
|
|
||||||
|
|
||||||
FileConfiguration config = YamlConfiguration.loadConfiguration(file);
|
|
||||||
|
|
||||||
// Настройки
|
// Настройки
|
||||||
prefix = config.getString("settings.prefix", "&6[&eINFO&6]&r");
|
prefix = plugin.getConfigManager().getString("prefix", "�D4FF[LoChat]");
|
||||||
mode = config.getString("settings.mode", "sequential").toLowerCase();
|
mode = "sequential"; // Всегда последовательно
|
||||||
|
|
||||||
// Загружаем сообщения
|
// Загружаем сообщения из config.yml
|
||||||
messages = new LinkedHashMap<>();
|
messages = new LinkedHashMap<>();
|
||||||
ConfigurationSection msgSection = config.getConfigurationSection("messages");
|
ConfigurationSection msgSection = config.getConfigurationSection("automessages-list");
|
||||||
|
|
||||||
if (msgSection != null) {
|
if (msgSection != null) {
|
||||||
for (String key : msgSection.getKeys(false)) {
|
for (String key : msgSection.getKeys(false)) {
|
||||||
|
|
@ -65,32 +60,7 @@ public class AutoMessageManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Определяем порядок
|
messageOrder = new ArrayList<>(messages.keySet());
|
||||||
messageOrder = new ArrayList<>();
|
|
||||||
|
|
||||||
if (mode.equals("custom")) {
|
|
||||||
String orderStr = config.getString("settings.order", "");
|
|
||||||
for (String item : orderStr.split(",")) {
|
|
||||||
String trimmed = item.trim();
|
|
||||||
if (!trimmed.isEmpty()) {
|
|
||||||
try {
|
|
||||||
int index = Integer.parseInt(trimmed) - 1;
|
|
||||||
List<String> keys = new ArrayList<>(messages.keySet());
|
|
||||||
if (index >= 0 && index < keys.size()) {
|
|
||||||
messageOrder.add(keys.get(index));
|
|
||||||
}
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
if (messages.containsKey(trimmed)) {
|
|
||||||
messageOrder.add(trimmed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (messageOrder.isEmpty()) {
|
|
||||||
messageOrder.addAll(messages.keySet());
|
|
||||||
}
|
|
||||||
|
|
||||||
plugin.getLogger().info("Загружено " + messages.size() + " автосообщений");
|
plugin.getLogger().info("Загружено " + messages.size() + " автосообщений");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
package com.loki.lochat.util;
|
|
||||||
|
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
|
||||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Утилита для форматирования сообщений
|
|
||||||
*/
|
|
||||||
public class ChatFormatter {
|
|
||||||
private static final MiniMessage MINI_MESSAGE = MiniMessage.miniMessage();
|
|
||||||
private static final LegacyComponentSerializer LEGACY = LegacyComponentSerializer.legacyAmpersand();
|
|
||||||
|
|
||||||
public static Object parse(String message) {
|
|
||||||
try {
|
|
||||||
return MINI_MESSAGE.deserialize(message);
|
|
||||||
} catch (Exception e) {
|
|
||||||
return LEGACY.deserialize(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String toPlain(Object message) {
|
|
||||||
if (message instanceof Component component) {
|
|
||||||
return LegacyComponentSerializer.legacySection().serialize(component);
|
|
||||||
}
|
|
||||||
return message.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void sendMessage(CommandSender sender, Object message) {
|
|
||||||
if (message instanceof Component component) {
|
|
||||||
sender.sendMessage(component);
|
|
||||||
} else {
|
|
||||||
sender.sendMessage(message.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void broadcast(Object message) {
|
|
||||||
if (message instanceof Component component) {
|
|
||||||
org.bukkit.Bukkit.broadcast(component);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String stripTags(String message) {
|
|
||||||
return message.replaceAll("<[^>]+>", "").replaceAll("§[0-9a-fk-or]", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String convertAllColors(String message) {
|
|
||||||
return message.replace("&", "§");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -40,24 +40,24 @@ public final class ChatFormatter {
|
||||||
private static String convertLegacyFormats(String message) {
|
private static String convertLegacyFormats(String message) {
|
||||||
if (message == null) return "";
|
if (message == null) return "";
|
||||||
|
|
||||||
// Конвертируем &#RRGGBB в <#RRGGBB>
|
// Конвертируем &#RRGGBB в <color:#RRGGBB>
|
||||||
java.util.regex.Pattern pattern1 = java.util.regex.Pattern.compile("&#([0-9a-fA-F]{6})");
|
java.util.regex.Pattern pattern1 = java.util.regex.Pattern.compile("&#([0-9a-fA-F]{6})");
|
||||||
java.util.regex.Matcher matcher1 = pattern1.matcher(message);
|
java.util.regex.Matcher matcher1 = pattern1.matcher(message);
|
||||||
StringBuffer sb1 = new StringBuffer();
|
StringBuffer sb1 = new StringBuffer();
|
||||||
while (matcher1.find()) {
|
while (matcher1.find()) {
|
||||||
String hex = matcher1.group(1).toLowerCase();
|
String hex = matcher1.group(1).toLowerCase();
|
||||||
matcher1.appendReplacement(sb1, "<#" + hex + ">");
|
matcher1.appendReplacement(sb1, "<color:#" + hex + ">");
|
||||||
}
|
}
|
||||||
matcher1.appendTail(sb1);
|
matcher1.appendTail(sb1);
|
||||||
message = sb1.toString();
|
message = sb1.toString();
|
||||||
|
|
||||||
// Конвертируем #RRGGBB в <#RRGGBB> (только если не внутри тегов)
|
// Конвертируем #RRGGBB в <color:#RRGGBB> (только если не внутри тегов)
|
||||||
java.util.regex.Pattern pattern2 = java.util.regex.Pattern.compile("(?<!<)#([0-9a-fA-F]{6})(?![^<]*>)");
|
java.util.regex.Pattern pattern2 = java.util.regex.Pattern.compile("(?<!<)#([0-9a-fA-F]{6})(?![^<]*>)");
|
||||||
java.util.regex.Matcher matcher2 = pattern2.matcher(message);
|
java.util.regex.Matcher matcher2 = pattern2.matcher(message);
|
||||||
StringBuffer sb2 = new StringBuffer();
|
StringBuffer sb2 = new StringBuffer();
|
||||||
while (matcher2.find()) {
|
while (matcher2.find()) {
|
||||||
String hex = matcher2.group(1).toLowerCase();
|
String hex = matcher2.group(1).toLowerCase();
|
||||||
matcher2.appendReplacement(sb2, "<#" + hex + ">");
|
matcher2.appendReplacement(sb2, "<color:#" + hex + ">");
|
||||||
}
|
}
|
||||||
matcher2.appendTail(sb2);
|
matcher2.appendTail(sb2);
|
||||||
message = sb2.toString();
|
message = sb2.toString();
|
||||||
|
|
|
||||||
|
|
@ -17,20 +17,32 @@ public final class PlayerUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Safely parses a sound name from config.
|
* Safely parses a sound name from config.
|
||||||
* Uses deprecated Sound.valueOf() for backward compatibility with string-based config values.
|
* Uses Registry API for modern sound parsing with fallback to reflection.
|
||||||
*
|
*
|
||||||
* @param soundName the sound name to parse
|
* @param soundName the sound name to parse
|
||||||
* @param defaultSound the default sound to return if parsing fails
|
* @param defaultSound the default sound to return if parsing fails
|
||||||
* @return the parsed Sound or the default if invalid
|
* @return the parsed Sound or the default if invalid
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public static Sound parseSound(String soundName, Sound defaultSound) {
|
public static Sound parseSound(String soundName, Sound defaultSound) {
|
||||||
if (soundName == null || soundName.isEmpty()) {
|
if (soundName == null || soundName.isEmpty()) {
|
||||||
return defaultSound;
|
return defaultSound;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return Sound.valueOf(soundName.toUpperCase());
|
// Try to get sound by key using Registry (modern way)
|
||||||
} catch (IllegalArgumentException e) {
|
Sound sound = org.bukkit.Registry.SOUNDS.match(soundName);
|
||||||
|
if (sound != null) {
|
||||||
|
return sound;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
// Registry failed, try fallback
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback: try direct field access via reflection
|
||||||
|
try {
|
||||||
|
java.lang.reflect.Field field = Sound.class.getField(soundName.toUpperCase().trim());
|
||||||
|
return (Sound) field.get(null);
|
||||||
|
} catch (Exception ex) {
|
||||||
return defaultSound;
|
return defaultSound;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,28 +6,35 @@ public final class TimeFormatter {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String format(long millis) {
|
public static String format(long millis) {
|
||||||
if (millis <= 0) {
|
if (millis < 0) {
|
||||||
return "0с";
|
return "0с";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (millis == 0) {
|
||||||
|
return "навсегда";
|
||||||
|
}
|
||||||
|
|
||||||
long seconds = millis / 1000;
|
long seconds = millis / 1000;
|
||||||
long minutes = seconds / 60;
|
long minutes = seconds / 60;
|
||||||
long hours = minutes / 60;
|
long hours = minutes / 60;
|
||||||
long days = hours / 24;
|
long days = hours / 24;
|
||||||
|
|
||||||
if (days > 0) {
|
if (days > 0) {
|
||||||
return days + "д " + (hours % 24) + "ч";
|
long remainingHours = hours % 24;
|
||||||
|
return remainingHours > 0 ? days + "д " + remainingHours + "ч" : days + "д";
|
||||||
} else if (hours > 0) {
|
} else if (hours > 0) {
|
||||||
return hours + "ч " + (minutes % 60) + "м";
|
long remainingMinutes = minutes % 60;
|
||||||
|
return remainingMinutes > 0 ? hours + "ч " + remainingMinutes + "м" : hours + "ч";
|
||||||
} else if (minutes > 0) {
|
} else if (minutes > 0) {
|
||||||
return minutes + "м " + (seconds % 60) + "с";
|
long remainingSeconds = seconds % 60;
|
||||||
|
return remainingSeconds > 0 ? minutes + "м " + remainingSeconds + "с" : minutes + "м";
|
||||||
} else {
|
} else {
|
||||||
return seconds + "с";
|
return seconds + "с";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long parse(String timeStr) {
|
public static long parse(String timeStr) {
|
||||||
if (timeStr == null || timeStr.isEmpty()) {
|
if (timeStr == null || timeStr.trim().isEmpty()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -38,8 +45,12 @@ public final class TimeFormatter {
|
||||||
if (Character.isDigit(c)) {
|
if (Character.isDigit(c)) {
|
||||||
number.append(c);
|
number.append(c);
|
||||||
} else if (number.length() > 0) {
|
} else if (number.length() > 0) {
|
||||||
long value = Long.parseLong(number.toString());
|
try {
|
||||||
totalMillis += getMillisForUnit(c, value);
|
long value = Long.parseLong(number.toString());
|
||||||
|
totalMillis += getMillisForUnit(c, value);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
// Skip invalid numbers
|
||||||
|
}
|
||||||
number.setLength(0);
|
number.setLength(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,90 +0,0 @@
|
||||||
# ╔══════════════════════════════════════════════════════════════════════════════╗
|
|
||||||
# ║ LoChat Auto Messages ║
|
|
||||||
# ║ Автосообщения чата ║
|
|
||||||
# ║ Версия: 1.5.5-1.20.1 ║
|
|
||||||
# ╚══════════════════════════════════════════════════════════════════════════════╝
|
|
||||||
|
|
||||||
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
|
||||||
# │ НАСТРОЙКИ │
|
|
||||||
# └─────────────────────────────────────────────────────────────────────────────┘
|
|
||||||
|
|
||||||
settings:
|
|
||||||
# Префикс автосообщений
|
|
||||||
prefix: "�D4FF[�D4FFI�CAF7N�C0EEF�B7E6OcCC]"
|
|
||||||
|
|
||||||
# Режим отправки: sequential (по порядку), random (случайно), custom (свой порядок)
|
|
||||||
mode: "sequential"
|
|
||||||
|
|
||||||
# Свой порядок сообщений (только для режима custom)
|
|
||||||
# Можно указывать номера или названия сообщений
|
|
||||||
order: "welcome, rules, discord, website"
|
|
||||||
|
|
||||||
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
|
||||||
# │ СООБЩЕНИЯ │
|
|
||||||
# └─────────────────────────────────────────────────────────────────────────────┘
|
|
||||||
|
|
||||||
messages:
|
|
||||||
# Приветственное сообщение
|
|
||||||
welcome:
|
|
||||||
- "<gradient:#FFD700:#FFA500>Добро пожаловать на наш сервер!</gradient>"
|
|
||||||
- "<gray>Используйте</gray> <gradient:#87CEEB:#4682B4>/help</gradient> <gray>для получения помощи</gray>"
|
|
||||||
|
|
||||||
# Правила сервера
|
|
||||||
rules:
|
|
||||||
- "<gradient:#FF6B6B:#FF4757>Соблюдайте правила сервера!</gradient>"
|
|
||||||
- "<gray>Подробнее:</gray> <gradient:#87CEEB:#4682B4>/rules</gradient>"
|
|
||||||
|
|
||||||
# Информация о Discord
|
|
||||||
discord:
|
|
||||||
- "<gradient:#7289DA:#5865F2>Присоединяйтесь к нашему Discord!</gradient>"
|
|
||||||
- "<gray>Ссылка:</gray> <click:open_url:'https://discord.gg/example'><gradient:#87CEEB:#4682B4>discord.gg/example</gradient></click>"
|
|
||||||
|
|
||||||
# Веб-сайт
|
|
||||||
website:
|
|
||||||
- "<gradient:#00FF88:#00CC66>Посетите наш сайт!</gradient>"
|
|
||||||
- "<gray>Адрес:</gray> <click:open_url:'https://example.com'><gradient:#87CEEB:#4682B4>example.com</gradient></click>"
|
|
||||||
|
|
||||||
# Донат информация
|
|
||||||
donate:
|
|
||||||
- "<gradient:#FFD700:#FFA500>Поддержите сервер!</gradient>"
|
|
||||||
- "<gray>Донат:</gray> <click:open_url:'https://donate.example.com'><gradient:#87CEEB:#4682B4>donate.example.com</gradient></click>"
|
|
||||||
|
|
||||||
# Градиентные ники
|
|
||||||
gradients:
|
|
||||||
- "<gradient:#9370DB:#8A2BE2>Создайте красивый ник!</gradient>"
|
|
||||||
- "<gray>Команда:</gray> <gradient:#87CEEB:#4682B4>/color</gradient> <gray>для градиентов</gray>"
|
|
||||||
|
|
||||||
# Чат команды
|
|
||||||
chat-commands:
|
|
||||||
- "<gradient:#FFA726:#FF9800>Полезные команды чата:</gradient>"
|
|
||||||
- "<gradient:#87CEEB:#4682B4>/msg <игрок> <сообщение></gradient> <gray>- личное сообщение</gray>"
|
|
||||||
- "<gradient:#87CEEB:#4682B4>/ignore <игрок></gradient> <gray>- игнорировать игрока</gray>"
|
|
||||||
|
|
||||||
# Онлайн статистика
|
|
||||||
online-stats:
|
|
||||||
- "<gradient:#6BCB77:#4ECDC4>Сейчас онлайн: {online} игроков</gradient>"
|
|
||||||
- "<gray>Максимум за день:</gray> <white>{max_online}</white>"
|
|
||||||
|
|
||||||
# Время на сервере
|
|
||||||
server-time:
|
|
||||||
- "<gradient:#87CEEB:#4682B4>Время на сервере:</gradient> <white>{time}</white>"
|
|
||||||
- "<gray>Дата:</gray> <white>{date}</white>"
|
|
||||||
|
|
||||||
# События
|
|
||||||
events:
|
|
||||||
- "<gradient:#FF69B4:#FF1493>Следите за событиями!</gradient>"
|
|
||||||
- "<gray>Расписание:</gray> <gradient:#87CEEB:#4682B4>/events</gradient>"
|
|
||||||
|
|
||||||
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
|
||||||
# │ ПЛЕЙСХОЛДЕРЫ │
|
|
||||||
# └─────────────────────────────────────────────────────────────────────────────┘
|
|
||||||
|
|
||||||
# Доступные плейсхолдеры в сообщениях:
|
|
||||||
# {online} - количество игроков онлайн
|
|
||||||
# {max_online} - максимальное количество игроков (из server.properties)
|
|
||||||
# {time} - текущее время
|
|
||||||
# {date} - текущая дата
|
|
||||||
# {server_name} - название сервера
|
|
||||||
# {tps} - TPS сервера (если доступно)
|
|
||||||
#
|
|
||||||
# Также поддерживаются все плейсхолдеры PlaceholderAPI
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
formats:
|
|
||||||
global: "<gray>[G]</gray> {prefix}{name}<gray>:</gray> <white>{message}"
|
|
||||||
local: "{prefix}{name}<gray>:</gray> <white>{message}"
|
|
||||||
|
|
@ -1,75 +1,122 @@
|
||||||
# ╔══════════════════════════════════════════════════════════════════════════════╗
|
# ╔══════════════════════════════════════════════════════════════════════════════╗
|
||||||
# ║ LoChat Configuration ║
|
# ║ LoChat Configuration ║
|
||||||
# ║ Продвинутый чат-плагин для Paper ║
|
|
||||||
# ║ Версия: 1.5.5-1.20.1 ║
|
# ║ Версия: 1.5.5-1.20.1 ║
|
||||||
# ║ Автор: loki ║
|
|
||||||
# ╚══════════════════════════════════════════════════════════════════════════════╝
|
# ╚══════════════════════════════════════════════════════════════════════════════╝
|
||||||
|
|
||||||
config-version: 3
|
config-version: 4
|
||||||
|
prefix: "�D4FF[LoChat]"
|
||||||
|
|
||||||
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
# │ ОСНОВНЫЕ НАСТРОЙКИ │
|
# │ ДОПОЛНИТЕЛЬНЫЕ КОНФИГИ │
|
||||||
# └─────────────────────────────────────────────────────────────────────────────┘
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
# Префикс плагина в сообщениях
|
# Загружать дополнительные конфигурационные файлы
|
||||||
prefix: "�D4FF[�D4FFL�CAF7o�C0EEC�B7E6h�ADDDa�A3D5tcCC]"
|
load-additional-configs: true
|
||||||
|
|
||||||
|
# Список дополнительных конфигов для загрузки
|
||||||
|
additional-configs:
|
||||||
|
- "config/chat-formats.yml" # Форматы чата и сообщений
|
||||||
|
- "config/filters.yml" # Настройки фильтров
|
||||||
|
- "config/gradient-config.yml" # Конфигурация градиентов
|
||||||
|
- "config/automessages.yml" # Автосообщения
|
||||||
|
- "config/mute-config.yml" # Система мутов
|
||||||
|
- "config/sounds.yml" # Звуковые эффекты
|
||||||
|
- "config/database.yml" # База данных
|
||||||
|
- "config/integrations.yml" # Интеграции с другими плагинами
|
||||||
|
- "config/custom-commands.yml" # Кастомные команды
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ СТРУКТУРА ДАННЫХ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
# Настройки хранения данных
|
||||||
|
data-storage:
|
||||||
|
# Основная папка для данных
|
||||||
|
data-folder: "data/"
|
||||||
|
|
||||||
|
# Использовать отдельные файлы для разных типов данных
|
||||||
|
separate-files: true
|
||||||
|
|
||||||
|
# Файлы данных
|
||||||
|
files:
|
||||||
|
main: "data.yml" # Основные данные (если separate-files: false)
|
||||||
|
players: "players.yml" # Данные игроков
|
||||||
|
gradients: "gradients.yml" # Градиентные ники
|
||||||
|
mutes: "mutes.yml" # Муты и история
|
||||||
|
ignores: "ignores.yml" # Игнорирование
|
||||||
|
statistics: "statistics.yml" # Статистика
|
||||||
|
filter-words: "filter-words.json" # Запрещенные слова
|
||||||
|
|
||||||
|
# Автосохранение (секунды)
|
||||||
|
auto-save-interval: 300
|
||||||
|
|
||||||
|
# Создавать резервные копии
|
||||||
|
backup:
|
||||||
|
enabled: true
|
||||||
|
interval: 3600 # Каждый час
|
||||||
|
max-backups: 24
|
||||||
|
folder: "backups/"
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ HUB COMMAND │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
hub_command:
|
||||||
|
# Enable/disable /hub command
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# Target server name for /hub command
|
||||||
|
# Sends player to this server via BungeeCord
|
||||||
|
server: "hub"
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ КАСТОМНЫЕ КОМАНДЫ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
custom-commands:
|
||||||
|
# Включить кастомные команды
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# Настройки Discord команды
|
||||||
|
discord:
|
||||||
|
invite-link: "discord.gg/example"
|
||||||
|
|
||||||
|
# Настройки Website команды
|
||||||
|
website:
|
||||||
|
url: "https://example.com"
|
||||||
|
|
||||||
|
# Настройки координат
|
||||||
|
coords:
|
||||||
|
# Показывать координаты в actionbar
|
||||||
|
show-in-actionbar: true
|
||||||
|
# Время показа в actionbar (тики)
|
||||||
|
actionbar-duration: 60
|
||||||
|
|
||||||
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
# │ НАСТРОЙКИ ЧАТА │
|
# │ НАСТРОЙКИ ЧАТА │
|
||||||
# └─────────────────────────────────────────────────────────────────────────────┘
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
chat:
|
chat:
|
||||||
# ═══════════════════════════════════════════════════════════════════════════
|
|
||||||
# ГЛОБАЛЬНЫЙ ЧАТ
|
|
||||||
# ═══════════════════════════════════════════════════════════════════════════
|
|
||||||
global:
|
global:
|
||||||
# Включить глобальный чат
|
|
||||||
enabled: true
|
enabled: true
|
||||||
# Символ для отправки в глобальный чат
|
|
||||||
symbol: "!"
|
|
||||||
# Кулдаун между сообщениями (секунды)
|
|
||||||
cooldown: 3
|
cooldown: 3
|
||||||
# Префикс глобального чата
|
|
||||||
prefix: "&#FFD700[G]"
|
prefix: "&#FFD700[G]"
|
||||||
format: "{prefix} �FF88{player}򇨣: {message}"
|
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════════════════════
|
|
||||||
# ЛОКАЛЬНЫЙ ЧАТ
|
|
||||||
# ═══════════════════════════════════════════════════════════════════════════
|
|
||||||
local:
|
local:
|
||||||
# Включить локальный чат
|
|
||||||
enabled: true
|
enabled: true
|
||||||
# Радиус локального чата (блоки)
|
|
||||||
radius: 100
|
radius: 100
|
||||||
# Кулдаун между сообщениями (секунды)
|
|
||||||
cooldown: 1
|
cooldown: 1
|
||||||
# Префикс локального чата
|
|
||||||
prefix: "WCEEB[L]"
|
prefix: "WCEEB[L]"
|
||||||
format: "{prefix} �FF88{player}򇨣: {message}"
|
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════════════════════
|
|
||||||
# ЛИЧНЫЕ СООБЩЕНИЯ
|
|
||||||
# ═══════════════════════════════════════════════════════════════════════════
|
|
||||||
pm:
|
pm:
|
||||||
# Включить личные сообщения
|
|
||||||
enabled: true
|
enabled: true
|
||||||
# Кулдаун между PM (секунды)
|
|
||||||
cooldown: 2
|
cooldown: 2
|
||||||
# Логировать PM в консоль
|
|
||||||
log: false
|
|
||||||
# Звук при получении PM
|
|
||||||
sound: true
|
sound: true
|
||||||
sound-type: "BLOCK_NOTE_BLOCK_PLING"
|
sound-type: "BLOCK_NOTE_BLOCK_PLING"
|
||||||
|
log: false
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════════════════════
|
|
||||||
# HOVER TOOLTIP (наведение на ник)
|
|
||||||
# ═══════════════════════════════════════════════════════════════════════════
|
|
||||||
hover:
|
hover:
|
||||||
# Включить hover tooltip при наведении на ник
|
|
||||||
enabled: true
|
enabled: true
|
||||||
# Формат tooltip (список строк)
|
|
||||||
# Плейсхолдеры: {player}, {world}, {ping}, {gamemode}, {health}, {food}
|
|
||||||
# Поддержка PlaceholderAPI: %placeholder%
|
|
||||||
format:
|
format:
|
||||||
- "<gray>Игрок: <white>{player}"
|
- "<gray>Игрок: <white>{player}"
|
||||||
- "<gray>Мир: <green>{world}"
|
- "<gray>Мир: <green>{world}"
|
||||||
|
|
@ -81,87 +128,54 @@ chat:
|
||||||
# │ ГРАДИЕНТНЫЕ НИКИ │
|
# │ ГРАДИЕНТНЫЕ НИКИ │
|
||||||
# └─────────────────────────────────────────────────────────────────────────────┘
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
# Интеграция с градиентным модулем (встроенный LoPreff)
|
|
||||||
lopreff:
|
lopreff:
|
||||||
# Включить градиентные ники
|
|
||||||
enabled: true
|
enabled: true
|
||||||
# Использовать градиентный ник в чате
|
|
||||||
use-gradient-name: true
|
use-gradient-name: true
|
||||||
# Использовать кастомный префикс
|
|
||||||
use-custom-prefix: true
|
use-custom-prefix: true
|
||||||
|
|
||||||
# Настройки отображения ника
|
|
||||||
display:
|
display:
|
||||||
# Обновлять display name игрока (показывает префикс+ник над головой)
|
|
||||||
update-display-name: true
|
update-display-name: true
|
||||||
# Обновлять tab list
|
|
||||||
update-tab-list: true
|
update-tab-list: true
|
||||||
|
|
||||||
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
# │ УПОМИНАНИЯ │
|
# │ ДОПОЛНИТЕЛЬНЫЕ ФУНКЦИИ │
|
||||||
# └─────────────────────────────────────────────────────────────────────────────┘
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
mentions:
|
mentions:
|
||||||
# Включить систему упоминаний (@nickname)
|
|
||||||
enabled: true
|
enabled: true
|
||||||
# Воспроизводить звук при упоминании
|
|
||||||
sound: true
|
sound: true
|
||||||
# Тип звука
|
|
||||||
sound-type: "BLOCK_NOTE_BLOCK_PLING"
|
sound-type: "BLOCK_NOTE_BLOCK_PLING"
|
||||||
# Подсветка упоминания в чате
|
|
||||||
highlight: "&#FFFF00@{player}"
|
highlight: "&#FFFF00@{player}"
|
||||||
self-highlight: "&#FFD700{player}"
|
self-highlight: "&#FFD700{player}"
|
||||||
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
everyone:
|
||||||
# │ АВТОСООБЩЕНИЯ │
|
enabled: true
|
||||||
# └─────────────────────────────────────────────────────────────────────────────┘
|
permission: "lochat.mention.everyone"
|
||||||
|
here:
|
||||||
|
enabled: true
|
||||||
|
permission: "lochat.mention.here"
|
||||||
|
role:
|
||||||
|
enabled: true
|
||||||
|
permission: "lochat.mention.role"
|
||||||
|
|
||||||
automessages:
|
automessages:
|
||||||
# Включить автосообщения
|
|
||||||
enabled: true
|
enabled: true
|
||||||
# Интервал между сообщениями (секунды)
|
|
||||||
interval: 300
|
interval: 300
|
||||||
# Случайный порядок сообщений
|
|
||||||
random: false
|
random: false
|
||||||
|
|
||||||
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
|
||||||
# │ ОБЪЯВЛЕНИЯ │
|
|
||||||
# └─────────────────────────────────────────────────────────────────────────────┘
|
|
||||||
|
|
||||||
announcements:
|
announcements:
|
||||||
# Показывать title при объявлении
|
|
||||||
show-title: true
|
show-title: true
|
||||||
# Заголовок title
|
|
||||||
title-header: "&#FF6B6BОБЪЯВЛЕНИЕ"
|
title-header: "&#FF6B6BОБЪЯВЛЕНИЕ"
|
||||||
# Показывать actionbar при объявлении
|
|
||||||
show-actionbar: true
|
show-actionbar: true
|
||||||
# Время показа title (в секундах)
|
|
||||||
title-duration: 3
|
title-duration: 3
|
||||||
|
|
||||||
# Формат объявления
|
|
||||||
formats:
|
|
||||||
announcement: "&#FF6B6B[ОБЪЯВЛЕНИЕ] <message>"
|
|
||||||
|
|
||||||
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
|
||||||
# │ ОЧИСТКА ЧАТА │
|
|
||||||
# └─────────────────────────────────────────────────────────────────────────────┘
|
|
||||||
|
|
||||||
clearchat:
|
clearchat:
|
||||||
message:
|
message:
|
||||||
# Показывать сообщение после очистки чата
|
|
||||||
enabled: true
|
enabled: true
|
||||||
# Текст сообщения ({player} - имя администратора)
|
|
||||||
text: "&#FF6B6BЧат очищен администратором {player}"
|
text: "&#FF6B6BЧат очищен администратором {player}"
|
||||||
|
|
||||||
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
|
||||||
# │ ГОЛОВЫ ИГРОКОВ │
|
|
||||||
# └─────────────────────────────────────────────────────────────────────────────┘
|
|
||||||
|
|
||||||
head-emoji:
|
head-emoji:
|
||||||
# Включить функцию голов игроков
|
|
||||||
enabled: true
|
enabled: true
|
||||||
# Разрешить использование @head команд
|
|
||||||
allow-player-heads: true
|
allow-player-heads: true
|
||||||
# Максимальное количество голов в одном сообщении
|
|
||||||
max-heads-per-message: 3
|
max-heads-per-message: 3
|
||||||
|
|
||||||
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
|
@ -169,29 +183,8 @@ head-emoji:
|
||||||
# └─────────────────────────────────────────────────────────────────────────────┘
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
mute:
|
mute:
|
||||||
# Сообщения с плейсхолдерами:
|
|
||||||
# %duration% - время мута
|
|
||||||
# %reason% - причина
|
|
||||||
# %player% - замученный игрок
|
|
||||||
# %operator% - модератор
|
|
||||||
|
|
||||||
messages:
|
|
||||||
muted: "&#FF6B6B%player% 󙀸был замучен на &#FF6B6B%duration% 󙀸модератором &#FF6B6B%operator%󙀸. Причина: &#FF6B6B%reason%"
|
|
||||||
unmuted: "BCB77%player% 󙀸был размучен модератором BCB77%operator%"
|
|
||||||
you-muted: "&#FF6B6BВы замучены на %duration%! Причина: %reason%"
|
|
||||||
you-muted-permanent: "&#FF6B6BВы замучены навсегда! Причина: %reason%"
|
|
||||||
cannot-chat: "&#FF6B6BВы замучены! Осталось: %duration%"
|
|
||||||
cannot-chat-permanent: "&#FF6B6BВы замучены навсегда!"
|
|
||||||
silent-muted: "󙀸[Тихо] &#FF6B6B%player% 󙀸замучен на &#FF6B6B%duration% 󙀸(%operator%). Причина: %reason%"
|
|
||||||
silent-unmuted: "󙀸[Тихо] BCB77%player% 󙀸размучен (%operator%)"
|
|
||||||
|
|
||||||
# Причина по умолчанию если не указана
|
|
||||||
default-reason: "Нарушение правил"
|
default-reason: "Нарушение правил"
|
||||||
|
|
||||||
# Максимальное время мута по умолчанию (если не указано время)
|
|
||||||
default-duration: "7d"
|
default-duration: "7d"
|
||||||
|
|
||||||
# Доступные длительности для прав lochat.mute.dur.<время>
|
|
||||||
durations:
|
durations:
|
||||||
- "10m"
|
- "10m"
|
||||||
- "30m"
|
- "30m"
|
||||||
|
|
@ -210,8 +203,16 @@ mute:
|
||||||
# └─────────────────────────────────────────────────────────────────────────────┘
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
filters:
|
filters:
|
||||||
url:
|
caps:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
max-percent: 70
|
||||||
|
min-length: 5
|
||||||
|
auto-lowercase: true
|
||||||
|
|
||||||
|
advertising:
|
||||||
|
enabled: true
|
||||||
|
block-hidden-urls: true
|
||||||
|
block-domains: true
|
||||||
whitelist:
|
whitelist:
|
||||||
- "youtube.com"
|
- "youtube.com"
|
||||||
- "youtu.be"
|
- "youtu.be"
|
||||||
|
|
@ -219,30 +220,59 @@ filters:
|
||||||
- "twitch.tv"
|
- "twitch.tv"
|
||||||
blacklist:
|
blacklist:
|
||||||
- "scam-site.com"
|
- "scam-site.com"
|
||||||
blocked-message: "&#FF6B6BС&#FF5F5Fс&#FF5353ы&#FF4747л&#FF3B3Bк&#FF2F2Fи &#FF2323з&#FF1717а&#FF0B0Bп&#FF0000р&#FF0000е&#FF0000щ&#FF0000е&#FF0000н&#FF0000ы!"
|
|
||||||
|
|
||||||
ip:
|
ip:
|
||||||
enabled: true
|
enabled: true
|
||||||
block: false
|
block: false
|
||||||
replacement: "[IP скрыт]"
|
replacement: "[IP скрыт]"
|
||||||
blocked-message: "&#FF6B6BI&#FF5F5FP &#FF5353а&#FF4747д&#FF3B3Bр&#FF2F2Fе&#FF2323с&#FF1717а &#FF0B0Bз&#FF0000а&#FF0000п&#FF0000р&#FF0000е&#FF0000щ&#FF0000е&#FF0000н&#FF0000ы!"
|
|
||||||
|
|
||||||
repeat:
|
repeat:
|
||||||
enabled: true
|
enabled: true
|
||||||
max-repeats: 3
|
max-repeats: 3
|
||||||
|
|
||||||
|
# Форматы (не трогать)
|
||||||
|
formats:
|
||||||
|
announcement: "&#FF6B6B[ОБЪЯВЛЕНИЕ] <message>"
|
||||||
|
|
||||||
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
# │ УПОМИНАНИЯ │
|
# │ НАСТРОЙКИ ГРАДИЕНТОВ │
|
||||||
# └─────────────────────────────────────────────────────────────────────────────┘
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
advanced-mentions:
|
gradient:
|
||||||
enabled: true
|
storage-type: "file"
|
||||||
everyone:
|
min-colors: 1
|
||||||
enabled: true
|
max-colors: 7
|
||||||
permission: "lochat.mention.everyone"
|
price-per-color: 50
|
||||||
here:
|
prefix-price: 500
|
||||||
enabled: true
|
prefix-one-time-purchase: true
|
||||||
permission: "lochat.mention.here"
|
max-prefix-length: 16
|
||||||
role:
|
color-cooldown: 60
|
||||||
enabled: true
|
prefix-cooldown: 120
|
||||||
permission: "lochat.mention.role"
|
|
||||||
|
presets:
|
||||||
|
fire: [ "#FF4500", "#FF6347", "#FFD700" ]
|
||||||
|
ocean: [ "#00CED1", "#1E90FF", "#4169E1" ]
|
||||||
|
forest: [ "#228B22", "#32CD32", "#90EE90" ]
|
||||||
|
sunset: [ "#FF69B4", "#FF1493", "#DC143C" ]
|
||||||
|
rainbow: [ "#FF0000", "#FF7F00", "#FFFF00", "#00FF00", "#0000FF", "#4B0082", "#9400D3" ]
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ АВТОСООБЩЕНИЯ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
automessages-list:
|
||||||
|
welcome:
|
||||||
|
- "&#FFD700Добро пожаловать на наш сервер!"
|
||||||
|
- "WCEEBИспользуйте /help для получения помощи"
|
||||||
|
|
||||||
|
rules:
|
||||||
|
- "&#FF6B6BСоблюдайте правила сервера!"
|
||||||
|
- "WCEEBПодробнее: /rules"
|
||||||
|
|
||||||
|
discord:
|
||||||
|
- "ᱹDAПрисоединяйтесь к нашему Discord!"
|
||||||
|
- "WCEEBСсылка: discord.gg/example"
|
||||||
|
|
||||||
|
website:
|
||||||
|
- "�FF88Посетите наш сайт!"
|
||||||
|
- "WCEEBАдрес: example.com"
|
||||||
|
|
|
||||||
255
src/main/resources/config/automessages.yml
Normal file
255
src/main/resources/config/automessages.yml
Normal file
|
|
@ -0,0 +1,255 @@
|
||||||
|
# ╔══════════════════════════════════════════════════════════════════════════════╗
|
||||||
|
# ║ LoChat Auto Messages ║
|
||||||
|
# ║ Автосообщения ║
|
||||||
|
# ║ Версия: 1.5.5-1.20.1 ║
|
||||||
|
# ╚══════════════════════════════════════════════════════════════════════════════╝
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ОСНОВНЫЕ НАСТРОЙКИ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
settings:
|
||||||
|
# Включить автосообщения
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# Интервал между сообщениями (секунды)
|
||||||
|
interval: 300
|
||||||
|
|
||||||
|
# Случайный порядок сообщений
|
||||||
|
random: true
|
||||||
|
|
||||||
|
# Минимальное количество игроков для отправки
|
||||||
|
min-players: 1
|
||||||
|
|
||||||
|
# Префикс для автосообщений
|
||||||
|
prefix: "�D4FF[Авто]"
|
||||||
|
|
||||||
|
# Отправлять в определенные миры
|
||||||
|
worlds:
|
||||||
|
- "world"
|
||||||
|
- "world_nether"
|
||||||
|
- "world_the_end"
|
||||||
|
|
||||||
|
# Тип отправки: chat, actionbar, title, bossbar
|
||||||
|
type: "chat"
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ СООБЩЕНИЯ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
messages:
|
||||||
|
welcome:
|
||||||
|
enabled: true
|
||||||
|
weight: 10 # Вес для случайного выбора (больше = чаще)
|
||||||
|
permission: "" # Пустое = для всех
|
||||||
|
worlds: [] # Пустое = во всех мирах
|
||||||
|
content:
|
||||||
|
- "&#FFD700Добро пожаловать на наш сервер!"
|
||||||
|
- "WCEEBИспользуйте /help для получения помощи"
|
||||||
|
- "BCB77Приятной игры!"
|
||||||
|
|
||||||
|
rules:
|
||||||
|
enabled: true
|
||||||
|
weight: 8
|
||||||
|
permission: ""
|
||||||
|
worlds: []
|
||||||
|
content:
|
||||||
|
- "&#FF6B6BСоблюдайте правила сервера!"
|
||||||
|
- "WCEEBПодробнее: /rules"
|
||||||
|
- "&#FFA726Нарушения караются мутом или баном"
|
||||||
|
|
||||||
|
discord:
|
||||||
|
enabled: true
|
||||||
|
weight: 7
|
||||||
|
permission: ""
|
||||||
|
worlds: []
|
||||||
|
content:
|
||||||
|
- "ᱹDAПрисоединяйтесь к нашему Discord!"
|
||||||
|
- "WCEEBСсылка: discord.gg/example"
|
||||||
|
- "BCB77Общайтесь с игроками вне игры!"
|
||||||
|
|
||||||
|
website:
|
||||||
|
enabled: true
|
||||||
|
weight: 6
|
||||||
|
permission: ""
|
||||||
|
worlds: []
|
||||||
|
content:
|
||||||
|
- "�FF88Посетите наш сайт!"
|
||||||
|
- "WCEEBАдрес: example.com"
|
||||||
|
- "BCB77Карта сервера, статистика и многое другое!"
|
||||||
|
|
||||||
|
donate:
|
||||||
|
enabled: true
|
||||||
|
weight: 5
|
||||||
|
permission: ""
|
||||||
|
worlds: []
|
||||||
|
content:
|
||||||
|
- "&#FFD700Поддержите сервер донатом!"
|
||||||
|
- "WCEEBПолучите VIP статус и привилегии"
|
||||||
|
- "BCB77Подробнее: /donate"
|
||||||
|
|
||||||
|
tips:
|
||||||
|
enabled: true
|
||||||
|
weight: 9
|
||||||
|
permission: ""
|
||||||
|
worlds: []
|
||||||
|
content:
|
||||||
|
- "WCEEB💡 Совет: Используйте /coords для просмотра координат"
|
||||||
|
- "WCEEB💡 Совет: /ignore <игрок> - игнорировать игрока"
|
||||||
|
- "WCEEB💡 Совет: /msg <игрок> <сообщение> - личное сообщение"
|
||||||
|
- "WCEEB💡 Совет: /reply <сообщение> - ответить на ЛС"
|
||||||
|
- "WCEEB💡 Совет: /color <цвет> - изменить цвет ника"
|
||||||
|
|
||||||
|
events:
|
||||||
|
enabled: false
|
||||||
|
weight: 3
|
||||||
|
permission: ""
|
||||||
|
worlds: []
|
||||||
|
content:
|
||||||
|
- "&#FF69B4🎉 Скоро событие на сервере!"
|
||||||
|
- "WCEEBСледите за новостями в Discord"
|
||||||
|
- "BCB77Участвуйте и получайте призы!"
|
||||||
|
|
||||||
|
economy:
|
||||||
|
enabled: false
|
||||||
|
weight: 4
|
||||||
|
permission: ""
|
||||||
|
worlds: []
|
||||||
|
content:
|
||||||
|
- "&#FFD700💰 Зарабатывайте деньги на сервере!"
|
||||||
|
- "WCEEBПродавайте ресурсы в магазине"
|
||||||
|
- "BCB77Команды: /shop, /sell, /balance"
|
||||||
|
|
||||||
|
pvp:
|
||||||
|
enabled: false
|
||||||
|
weight: 2
|
||||||
|
permission: ""
|
||||||
|
worlds: ["world_pvp"]
|
||||||
|
content:
|
||||||
|
- "&#FF6B6B⚔️ Вы в PvP зоне!"
|
||||||
|
- "&#FFA726Будьте осторожны с другими игроками"
|
||||||
|
- "WCEEBИспользуйте /spawn для выхода"
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ СПЕЦИАЛЬНЫЕ СООБЩЕНИЯ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
special:
|
||||||
|
# Сообщения для новичков (первый вход)
|
||||||
|
newbie:
|
||||||
|
enabled: true
|
||||||
|
delay: 30 # Задержка после входа (секунды)
|
||||||
|
content:
|
||||||
|
- "BCB77Добро пожаловать на сервер, {player}!"
|
||||||
|
- "WCEEBЭто ваш первый визит. Изучите /help"
|
||||||
|
- "&#FFD700Желаем приятной игры!"
|
||||||
|
|
||||||
|
# Сообщения при входе
|
||||||
|
join:
|
||||||
|
enabled: false
|
||||||
|
delay: 5
|
||||||
|
content:
|
||||||
|
- "BCB77С возвращением, {player}!"
|
||||||
|
- "WCEEBНе забудьте проверить новости: /news"
|
||||||
|
|
||||||
|
# Сообщения при достижениях
|
||||||
|
achievement:
|
||||||
|
enabled: false
|
||||||
|
content:
|
||||||
|
- "&#FFD700🏆 Поздравляем с достижением!"
|
||||||
|
- "WCEEBПродолжайте исследовать мир"
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ НАСТРОЙКИ ОТОБРАЖЕНИЯ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
display:
|
||||||
|
# Настройки для title сообщений
|
||||||
|
title:
|
||||||
|
fade-in: 10
|
||||||
|
stay: 40
|
||||||
|
fade-out: 10
|
||||||
|
title: "&#FFD700Информация"
|
||||||
|
subtitle: "{message}"
|
||||||
|
|
||||||
|
# Настройки для actionbar сообщений
|
||||||
|
actionbar:
|
||||||
|
duration: 60 # Время показа (тики)
|
||||||
|
|
||||||
|
# Настройки для bossbar сообщений
|
||||||
|
bossbar:
|
||||||
|
color: "BLUE" # BLUE, GREEN, PINK, PURPLE, RED, WHITE, YELLOW
|
||||||
|
style: "SOLID" # SOLID, SEGMENTED_6, SEGMENTED_10, SEGMENTED_12, SEGMENTED_20
|
||||||
|
duration: 100 # Время показа (тики)
|
||||||
|
|
||||||
|
# Звуковые эффекты
|
||||||
|
sound:
|
||||||
|
enabled: false
|
||||||
|
type: "BLOCK_NOTE_BLOCK_PLING"
|
||||||
|
volume: 0.5
|
||||||
|
pitch: 1.0
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ УСЛОВИЯ ОТПРАВКИ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
conditions:
|
||||||
|
# Время суток (24-часовой формат)
|
||||||
|
time:
|
||||||
|
enabled: false
|
||||||
|
start: "09:00"
|
||||||
|
end: "23:00"
|
||||||
|
|
||||||
|
# Дни недели (1-7, где 1 = понедельник)
|
||||||
|
days:
|
||||||
|
enabled: false
|
||||||
|
allowed: [1, 2, 3, 4, 5, 6, 7]
|
||||||
|
|
||||||
|
# Исключить игроков в AFK
|
||||||
|
exclude-afk: false
|
||||||
|
|
||||||
|
# Исключить игроков в творческом режиме
|
||||||
|
exclude-creative: false
|
||||||
|
|
||||||
|
# Исключить игроков с определенными правами
|
||||||
|
exclude-permissions:
|
||||||
|
- "lochat.automessage.ignore"
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ПЕРСОНАЛИЗАЦИЯ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
personalization:
|
||||||
|
# Использовать имя игрока в сообщениях
|
||||||
|
use-player-name: true
|
||||||
|
|
||||||
|
# Адаптировать сообщения под группу игрока
|
||||||
|
group-specific: false
|
||||||
|
|
||||||
|
# Сообщения для разных групп
|
||||||
|
groups:
|
||||||
|
vip:
|
||||||
|
prefix: "&#FFD700[VIP Авто]"
|
||||||
|
messages:
|
||||||
|
- "&#FFD700Спасибо за поддержку сервера, {player}!"
|
||||||
|
- "WCEEBВы получаете эксклюзивные привилегии"
|
||||||
|
|
||||||
|
newbie:
|
||||||
|
prefix: "BCB77[Помощь]"
|
||||||
|
messages:
|
||||||
|
- "BCB77Нужна помощь, {player}? Спросите в чате!"
|
||||||
|
- "WCEEBИспользуйте /help для списка команд"
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ СТАТИСТИКА │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
statistics:
|
||||||
|
# Вести статистику отправленных сообщений
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# Файл для сохранения статистики
|
||||||
|
file: "plugins/LoChat/automessage-stats.yml"
|
||||||
|
|
||||||
|
# Сбрасывать статистику каждый месяц
|
||||||
|
reset-monthly: true
|
||||||
215
src/main/resources/config/chat-formats.yml
Normal file
215
src/main/resources/config/chat-formats.yml
Normal file
|
|
@ -0,0 +1,215 @@
|
||||||
|
# ╔══════════════════════════════════════════════════════════════════════════════╗
|
||||||
|
# ║ LoChat Chat Formats ║
|
||||||
|
# ║ Форматы чата ║
|
||||||
|
# ║ Версия: 1.5.5-1.20.1 ║
|
||||||
|
# ╚══════════════════════════════════════════════════════════════════════════════╝
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ФОРМАТЫ ЧАТА │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
# Доступные плейсхолдеры:
|
||||||
|
# {player} - имя игрока
|
||||||
|
# {display_name} - отображаемое имя с градиентом
|
||||||
|
# {prefix} - префикс игрока
|
||||||
|
# {suffix} - суффикс игрока
|
||||||
|
# {world} - мир игрока
|
||||||
|
# {message} - сообщение
|
||||||
|
# {time} - время
|
||||||
|
# {date} - дата
|
||||||
|
# Все плейсхолдеры PlaceholderAPI
|
||||||
|
|
||||||
|
formats:
|
||||||
|
# Глобальный чат
|
||||||
|
global:
|
||||||
|
enabled: true
|
||||||
|
format: "&#FFD700[G] {prefix}{display_name}&r: {message}"
|
||||||
|
hover:
|
||||||
|
- "<gray>Игрок: <white>{player}"
|
||||||
|
- "<gray>Мир: <green>{world}"
|
||||||
|
- "<gray>Пинг: <yellow>%player_ping%ms"
|
||||||
|
- ""
|
||||||
|
- "<yellow>▶ Клик: написать ЛС"
|
||||||
|
click:
|
||||||
|
action: "suggest_command"
|
||||||
|
value: "/msg {player} "
|
||||||
|
|
||||||
|
# Локальный чат
|
||||||
|
local:
|
||||||
|
enabled: true
|
||||||
|
format: "WCEEB[L] {prefix}{display_name}&r: {message}"
|
||||||
|
hover:
|
||||||
|
- "<gray>Игрок: <white>{player}"
|
||||||
|
- "<gray>Координаты: <yellow>{x}, {y}, {z}"
|
||||||
|
- "<gray>Расстояние: <green>%distance%м"
|
||||||
|
- ""
|
||||||
|
- "<yellow>▶ Клик: написать ЛС"
|
||||||
|
click:
|
||||||
|
action: "suggest_command"
|
||||||
|
value: "/msg {player} "
|
||||||
|
|
||||||
|
# Личные сообщения
|
||||||
|
private:
|
||||||
|
sent: "&7[→] WCEEBВы &7→ {display_name}&7: {message}"
|
||||||
|
received: "&7[←] {display_name} &7→ WCEEBВы&7: {message}"
|
||||||
|
hover:
|
||||||
|
- "<gray>Отправлено: <white>%time%"
|
||||||
|
- ""
|
||||||
|
- "<yellow>▶ Клик: ответить"
|
||||||
|
click:
|
||||||
|
action: "suggest_command"
|
||||||
|
value: "/reply "
|
||||||
|
|
||||||
|
# Объявления
|
||||||
|
announcement:
|
||||||
|
format: "&#FF6B6B[ОБЪЯВЛЕНИЕ] <message>"
|
||||||
|
title:
|
||||||
|
enabled: true
|
||||||
|
title: "&#FF6B6BОБЪЯВЛЕНИЕ"
|
||||||
|
subtitle: "{message}"
|
||||||
|
fade-in: 10
|
||||||
|
stay: 60
|
||||||
|
fade-out: 10
|
||||||
|
actionbar:
|
||||||
|
enabled: true
|
||||||
|
format: "&#FF6B6B[ОБЪЯВЛЕНИЕ] {message}"
|
||||||
|
|
||||||
|
# Системные сообщения
|
||||||
|
system:
|
||||||
|
join: "BCB77+ {display_name} BCB77присоединился к игре"
|
||||||
|
quit: "&#FF6B6B- {display_name} &#FF6B6Bпокинул игру"
|
||||||
|
death: "&#FF6B6B☠ {display_name} &#FF6B6B{death_message}"
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ФОРМАТЫ ПО ГРУППАМ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
groups:
|
||||||
|
owner:
|
||||||
|
priority: 1000
|
||||||
|
prefix: "&#FF0000[OWNER]"
|
||||||
|
suffix: ""
|
||||||
|
format: "{prefix} {display_name}&r: {message}"
|
||||||
|
name-color: "&#FF0000"
|
||||||
|
|
||||||
|
admin:
|
||||||
|
priority: 900
|
||||||
|
prefix: "&#FF6B6B[ADMIN]"
|
||||||
|
suffix: ""
|
||||||
|
format: "{prefix} {display_name}&r: {message}"
|
||||||
|
name-color: "&#FF6B6B"
|
||||||
|
|
||||||
|
moderator:
|
||||||
|
priority: 800
|
||||||
|
prefix: "&#FFA726[MOD]"
|
||||||
|
suffix: ""
|
||||||
|
format: "{prefix} {display_name}&r: {message}"
|
||||||
|
name-color: "&#FFA726"
|
||||||
|
|
||||||
|
helper:
|
||||||
|
priority: 700
|
||||||
|
prefix: "WCEEB[HELPER]"
|
||||||
|
suffix: ""
|
||||||
|
format: "{prefix} {display_name}&r: {message}"
|
||||||
|
name-color: "WCEEB"
|
||||||
|
|
||||||
|
vip:
|
||||||
|
priority: 600
|
||||||
|
prefix: "&#FFD700[VIP]"
|
||||||
|
suffix: ""
|
||||||
|
format: "{prefix} {display_name}&r: {message}"
|
||||||
|
name-color: "&#FFD700"
|
||||||
|
|
||||||
|
premium:
|
||||||
|
priority: 500
|
||||||
|
prefix: "BCB77[PREMIUM]"
|
||||||
|
suffix: ""
|
||||||
|
format: "{prefix} {display_name}&r: {message}"
|
||||||
|
name-color: "BCB77"
|
||||||
|
|
||||||
|
default:
|
||||||
|
priority: 0
|
||||||
|
prefix: ""
|
||||||
|
suffix: ""
|
||||||
|
format: "{display_name}&r: {message}"
|
||||||
|
name-color: "&#FFFFFF"
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ СПЕЦИАЛЬНЫЕ ФОРМАТЫ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
special:
|
||||||
|
# Формат для мутов
|
||||||
|
mute:
|
||||||
|
message: "&#FF6B6BВы замучены! Осталось: {time}"
|
||||||
|
permanent: "&#FF6B6BВы замучены навсегда!"
|
||||||
|
|
||||||
|
# Формат для упоминаний
|
||||||
|
mention:
|
||||||
|
format: "&#FFFF00@{player}"
|
||||||
|
sound: "BLOCK_NOTE_BLOCK_PLING"
|
||||||
|
volume: 1.0
|
||||||
|
pitch: 1.0
|
||||||
|
|
||||||
|
# Формат для эмодзи голов
|
||||||
|
head-emoji:
|
||||||
|
format: ":head_{player}:"
|
||||||
|
max-per-message: 3
|
||||||
|
|
||||||
|
# Формат для ссылок
|
||||||
|
url:
|
||||||
|
format: "<click:open_url:'{url}'><hover:show_text:'<gray>Открыть ссылку'><u>{url}</u></hover></click>"
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ НАСТРОЙКИ ОТОБРАЖЕНИЯ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
display:
|
||||||
|
# Максимальная длина сообщения
|
||||||
|
max-message-length: 256
|
||||||
|
|
||||||
|
# Показывать время в чате
|
||||||
|
show-time: false
|
||||||
|
time-format: "[HH:mm]"
|
||||||
|
|
||||||
|
# Показывать мир в чате
|
||||||
|
show-world: false
|
||||||
|
world-format: "[{world}]"
|
||||||
|
|
||||||
|
# Компактный режим (убирает лишние пробелы)
|
||||||
|
compact-mode: false
|
||||||
|
|
||||||
|
# Автоматически переносить длинные сообщения
|
||||||
|
word-wrap: true
|
||||||
|
|
||||||
|
# Цвет сообщений по умолчанию
|
||||||
|
default-message-color: "&#FFFFFF"
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ИНТЕГРАЦИИ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
integrations:
|
||||||
|
# PlaceholderAPI
|
||||||
|
placeholderapi:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# LuckPerms
|
||||||
|
luckperms:
|
||||||
|
enabled: true
|
||||||
|
use-prefix: true
|
||||||
|
use-suffix: true
|
||||||
|
|
||||||
|
# Vault
|
||||||
|
vault:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# DiscordSRV
|
||||||
|
discordsrv:
|
||||||
|
enabled: false
|
||||||
|
format: "**{player}**: {message}"
|
||||||
|
|
||||||
|
# Dynmap
|
||||||
|
dynmap:
|
||||||
|
enabled: false
|
||||||
|
format: "{player}: {message}"
|
||||||
|
|
@ -5,7 +5,41 @@
|
||||||
# ╚══════════════════════════════════════════════════════════════════════════════╝
|
# ╚══════════════════════════════════════════════════════════════════════════════╝
|
||||||
|
|
||||||
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
# │ ПРИМЕРЫ КОМАНД │
|
# │ НАСТРОЙКИ КОМАНД │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
settings:
|
||||||
|
# Включить кастомные команды
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# Настройки Discord команды
|
||||||
|
discord:
|
||||||
|
invite-link: "discord.gg/example"
|
||||||
|
|
||||||
|
# Настройки Website команды
|
||||||
|
website:
|
||||||
|
url: "https://example.com"
|
||||||
|
|
||||||
|
# Настройки координат
|
||||||
|
coords:
|
||||||
|
show-in-actionbar: true
|
||||||
|
actionbar-duration: 60
|
||||||
|
|
||||||
|
# Настройки /me команды
|
||||||
|
me:
|
||||||
|
radius: 100 # Радиус для локального действия
|
||||||
|
|
||||||
|
# Настройки звуков
|
||||||
|
sounds:
|
||||||
|
allow-toggle: true
|
||||||
|
|
||||||
|
# Настройки статистики
|
||||||
|
stats:
|
||||||
|
show-server-stats: true
|
||||||
|
show-player-stats: true
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ТЕКСТОВЫЕ КОМАНДЫ │
|
||||||
# └─────────────────────────────────────────────────────────────────────────────┘
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
# Структура команды:
|
# Структура команды:
|
||||||
346
src/main/resources/config/database.yml
Normal file
346
src/main/resources/config/database.yml
Normal file
|
|
@ -0,0 +1,346 @@
|
||||||
|
# ╔══════════════════════════════════════════════════════════════════════════════╗
|
||||||
|
# ║ LoChat Database Configuration ║
|
||||||
|
# ║ Конфигурация базы данных ║
|
||||||
|
# ║ Версия: 1.5.5-1.20.1 ║
|
||||||
|
# ╚══════════════════════════════════════════════════════════════════════════════╝
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ОСНОВНЫЕ НАСТРОЙКИ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
settings:
|
||||||
|
# Тип базы данных: file, sqlite, mysql, postgresql
|
||||||
|
type: "file"
|
||||||
|
|
||||||
|
# Префикс для таблиц
|
||||||
|
table-prefix: "lochat_"
|
||||||
|
|
||||||
|
# Автоматически создавать таблицы
|
||||||
|
auto-create-tables: true
|
||||||
|
|
||||||
|
# Автоматически обновлять структуру таблиц
|
||||||
|
auto-update-tables: true
|
||||||
|
|
||||||
|
# Кодировка для MySQL
|
||||||
|
charset: "utf8mb4"
|
||||||
|
|
||||||
|
# Collation для MySQL
|
||||||
|
collation: "utf8mb4_unicode_ci"
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ФАЙЛОВОЕ ХРАНЕНИЕ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
file:
|
||||||
|
# Папка для хранения файлов данных
|
||||||
|
data-folder: "plugins/LoChat/data/"
|
||||||
|
|
||||||
|
# Формат файлов: yaml, json
|
||||||
|
format: "yaml"
|
||||||
|
|
||||||
|
# Автоматическое сохранение (секунды)
|
||||||
|
auto-save-interval: 300
|
||||||
|
|
||||||
|
# Создавать резервные копии
|
||||||
|
backup:
|
||||||
|
enabled: true
|
||||||
|
interval: 3600 # Каждый час
|
||||||
|
max-backups: 24 # Хранить 24 копии
|
||||||
|
folder: "plugins/LoChat/backups/"
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ SQLITE │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
sqlite:
|
||||||
|
# Путь к файлу базы данных
|
||||||
|
file: "plugins/LoChat/database.db"
|
||||||
|
|
||||||
|
# Настройки соединения
|
||||||
|
connection:
|
||||||
|
# Таймаут соединения (миллисекунды)
|
||||||
|
timeout: 30000
|
||||||
|
|
||||||
|
# Включить WAL режим (Write-Ahead Logging)
|
||||||
|
wal-mode: true
|
||||||
|
|
||||||
|
# Размер кэша (KB)
|
||||||
|
cache-size: 2000
|
||||||
|
|
||||||
|
# Синхронизация: OFF, NORMAL, FULL
|
||||||
|
synchronous: "NORMAL"
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ MYSQL │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
mysql:
|
||||||
|
# Хост базы данных
|
||||||
|
host: "localhost"
|
||||||
|
|
||||||
|
# Порт базы данных
|
||||||
|
port: 3306
|
||||||
|
|
||||||
|
# Имя базы данных
|
||||||
|
database: "lochat"
|
||||||
|
|
||||||
|
# Имя пользователя
|
||||||
|
username: "root"
|
||||||
|
|
||||||
|
# Пароль
|
||||||
|
password: "password"
|
||||||
|
|
||||||
|
# Дополнительные параметры подключения
|
||||||
|
properties:
|
||||||
|
useSSL: false
|
||||||
|
allowPublicKeyRetrieval: true
|
||||||
|
serverTimezone: "UTC"
|
||||||
|
characterEncoding: "utf8"
|
||||||
|
useUnicode: true
|
||||||
|
autoReconnect: true
|
||||||
|
failOverReadOnly: false
|
||||||
|
maxReconnects: 3
|
||||||
|
initialTimeout: 1
|
||||||
|
|
||||||
|
# Настройки пула соединений (HikariCP)
|
||||||
|
pool:
|
||||||
|
# Максимальное количество соединений
|
||||||
|
maximum-pool-size: 10
|
||||||
|
|
||||||
|
# Минимальное количество простаивающих соединений
|
||||||
|
minimum-idle: 2
|
||||||
|
|
||||||
|
# Таймаут получения соединения (миллисекунды)
|
||||||
|
connection-timeout: 30000
|
||||||
|
|
||||||
|
# Время жизни простаивающего соединения (миллисекунды)
|
||||||
|
idle-timeout: 600000
|
||||||
|
|
||||||
|
# Максимальное время жизни соединения (миллисекунды)
|
||||||
|
max-lifetime: 1800000
|
||||||
|
|
||||||
|
# Интервал проверки соединений (миллисекунды)
|
||||||
|
leak-detection-threshold: 60000
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ POSTGRESQL │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
postgresql:
|
||||||
|
# Хост базы данных
|
||||||
|
host: "localhost"
|
||||||
|
|
||||||
|
# Порт базы данных
|
||||||
|
port: 5432
|
||||||
|
|
||||||
|
# Имя базы данных
|
||||||
|
database: "lochat"
|
||||||
|
|
||||||
|
# Имя пользователя
|
||||||
|
username: "postgres"
|
||||||
|
|
||||||
|
# Пароль
|
||||||
|
password: "password"
|
||||||
|
|
||||||
|
# Схема базы данных
|
||||||
|
schema: "public"
|
||||||
|
|
||||||
|
# Дополнительные параметры подключения
|
||||||
|
properties:
|
||||||
|
ssl: false
|
||||||
|
sslmode: "disable"
|
||||||
|
serverTimezone: "UTC"
|
||||||
|
characterEncoding: "utf8"
|
||||||
|
autoReconnect: true
|
||||||
|
|
||||||
|
# Настройки пула соединений
|
||||||
|
pool:
|
||||||
|
maximum-pool-size: 10
|
||||||
|
minimum-idle: 2
|
||||||
|
connection-timeout: 30000
|
||||||
|
idle-timeout: 600000
|
||||||
|
max-lifetime: 1800000
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ СТРУКТУРА ТАБЛИЦ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
tables:
|
||||||
|
# Таблица игроков
|
||||||
|
players:
|
||||||
|
name: "players"
|
||||||
|
columns:
|
||||||
|
uuid: "VARCHAR(36) PRIMARY KEY"
|
||||||
|
name: "VARCHAR(16) NOT NULL"
|
||||||
|
display_name: "TEXT"
|
||||||
|
first_join: "BIGINT NOT NULL"
|
||||||
|
last_join: "BIGINT NOT NULL"
|
||||||
|
last_quit: "BIGINT"
|
||||||
|
total_playtime: "BIGINT DEFAULT 0"
|
||||||
|
created_at: "TIMESTAMP DEFAULT CURRENT_TIMESTAMP"
|
||||||
|
updated_at: "TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP"
|
||||||
|
|
||||||
|
# Таблица градиентов
|
||||||
|
gradients:
|
||||||
|
name: "gradients"
|
||||||
|
columns:
|
||||||
|
uuid: "VARCHAR(36) PRIMARY KEY"
|
||||||
|
colors: "TEXT"
|
||||||
|
prefix: "TEXT"
|
||||||
|
enabled: "BOOLEAN DEFAULT TRUE"
|
||||||
|
created_at: "TIMESTAMP DEFAULT CURRENT_TIMESTAMP"
|
||||||
|
updated_at: "TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP"
|
||||||
|
|
||||||
|
# Таблица мутов
|
||||||
|
mutes:
|
||||||
|
name: "mutes"
|
||||||
|
columns:
|
||||||
|
id: "INT AUTO_INCREMENT PRIMARY KEY"
|
||||||
|
uuid: "VARCHAR(36) NOT NULL"
|
||||||
|
moderator_uuid: "VARCHAR(36)"
|
||||||
|
reason: "TEXT NOT NULL"
|
||||||
|
start_time: "BIGINT NOT NULL"
|
||||||
|
end_time: "BIGINT"
|
||||||
|
active: "BOOLEAN DEFAULT TRUE"
|
||||||
|
silent: "BOOLEAN DEFAULT FALSE"
|
||||||
|
created_at: "TIMESTAMP DEFAULT CURRENT_TIMESTAMP"
|
||||||
|
|
||||||
|
# История мутов
|
||||||
|
mute_history:
|
||||||
|
name: "mute_history"
|
||||||
|
columns:
|
||||||
|
id: "INT AUTO_INCREMENT PRIMARY KEY"
|
||||||
|
uuid: "VARCHAR(36) NOT NULL"
|
||||||
|
moderator_uuid: "VARCHAR(36)"
|
||||||
|
reason: "TEXT NOT NULL"
|
||||||
|
duration: "BIGINT NOT NULL"
|
||||||
|
start_time: "BIGINT NOT NULL"
|
||||||
|
end_time: "BIGINT"
|
||||||
|
unmute_reason: "TEXT"
|
||||||
|
unmute_moderator: "VARCHAR(36)"
|
||||||
|
created_at: "TIMESTAMP DEFAULT CURRENT_TIMESTAMP"
|
||||||
|
|
||||||
|
# Таблица игнорирования
|
||||||
|
ignores:
|
||||||
|
name: "ignores"
|
||||||
|
columns:
|
||||||
|
id: "INT AUTO_INCREMENT PRIMARY KEY"
|
||||||
|
player_uuid: "VARCHAR(36) NOT NULL"
|
||||||
|
ignored_uuid: "VARCHAR(36) NOT NULL"
|
||||||
|
created_at: "TIMESTAMP DEFAULT CURRENT_TIMESTAMP"
|
||||||
|
|
||||||
|
# Таблица сообщений (если включено логирование)
|
||||||
|
messages:
|
||||||
|
name: "messages"
|
||||||
|
columns:
|
||||||
|
id: "INT AUTO_INCREMENT PRIMARY KEY"
|
||||||
|
uuid: "VARCHAR(36) NOT NULL"
|
||||||
|
type: "VARCHAR(20) NOT NULL"
|
||||||
|
content: "TEXT NOT NULL"
|
||||||
|
server: "VARCHAR(50)"
|
||||||
|
world: "VARCHAR(50)"
|
||||||
|
created_at: "TIMESTAMP DEFAULT CURRENT_TIMESTAMP"
|
||||||
|
|
||||||
|
# Настройки игроков
|
||||||
|
player_settings:
|
||||||
|
name: "player_settings"
|
||||||
|
columns:
|
||||||
|
uuid: "VARCHAR(36) PRIMARY KEY"
|
||||||
|
sounds_enabled: "BOOLEAN DEFAULT TRUE"
|
||||||
|
sound_volume: "FLOAT DEFAULT 1.0"
|
||||||
|
auto_messages: "BOOLEAN DEFAULT TRUE"
|
||||||
|
mentions_enabled: "BOOLEAN DEFAULT TRUE"
|
||||||
|
pm_sounds: "BOOLEAN DEFAULT TRUE"
|
||||||
|
created_at: "TIMESTAMP DEFAULT CURRENT_TIMESTAMP"
|
||||||
|
updated_at: "TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP"
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ИНДЕКСЫ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
indexes:
|
||||||
|
# Индексы для оптимизации запросов
|
||||||
|
players:
|
||||||
|
- "CREATE INDEX idx_players_name ON {prefix}players(name)"
|
||||||
|
- "CREATE INDEX idx_players_last_join ON {prefix}players(last_join)"
|
||||||
|
|
||||||
|
mutes:
|
||||||
|
- "CREATE INDEX idx_mutes_uuid ON {prefix}mutes(uuid)"
|
||||||
|
- "CREATE INDEX idx_mutes_active ON {prefix}mutes(active)"
|
||||||
|
- "CREATE INDEX idx_mutes_end_time ON {prefix}mutes(end_time)"
|
||||||
|
|
||||||
|
mute_history:
|
||||||
|
- "CREATE INDEX idx_mute_history_uuid ON {prefix}mute_history(uuid)"
|
||||||
|
- "CREATE INDEX idx_mute_history_moderator ON {prefix}mute_history(moderator_uuid)"
|
||||||
|
- "CREATE INDEX idx_mute_history_start_time ON {prefix}mute_history(start_time)"
|
||||||
|
|
||||||
|
ignores:
|
||||||
|
- "CREATE INDEX idx_ignores_player ON {prefix}ignores(player_uuid)"
|
||||||
|
- "CREATE INDEX idx_ignores_ignored ON {prefix}ignores(ignored_uuid)"
|
||||||
|
- "CREATE UNIQUE INDEX idx_ignores_unique ON {prefix}ignores(player_uuid, ignored_uuid)"
|
||||||
|
|
||||||
|
messages:
|
||||||
|
- "CREATE INDEX idx_messages_uuid ON {prefix}messages(uuid)"
|
||||||
|
- "CREATE INDEX idx_messages_type ON {prefix}messages(type)"
|
||||||
|
- "CREATE INDEX idx_messages_created_at ON {prefix}messages(created_at)"
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ОЧИСТКА ДАННЫХ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
# Автоматическая очистка старых данных
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# Интервал очистки (секунды)
|
||||||
|
interval: 86400 # Раз в день
|
||||||
|
|
||||||
|
# Настройки очистки для каждой таблицы
|
||||||
|
tables:
|
||||||
|
mute_history:
|
||||||
|
# Удалять записи старше N дней
|
||||||
|
max-age-days: 90
|
||||||
|
# Оставлять минимум записей на игрока
|
||||||
|
min-records-per-player: 5
|
||||||
|
|
||||||
|
messages:
|
||||||
|
max-age-days: 30
|
||||||
|
# Максимальное количество записей
|
||||||
|
max-records: 100000
|
||||||
|
|
||||||
|
players:
|
||||||
|
# Удалять неактивных игроков (дни)
|
||||||
|
inactive-days: 365
|
||||||
|
# Не удалять игроков с определенными данными
|
||||||
|
keep-with-data: true
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ МИГРАЦИИ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
migrations:
|
||||||
|
# Автоматически выполнять миграции
|
||||||
|
auto-migrate: true
|
||||||
|
|
||||||
|
# Создавать резервные копии перед миграцией
|
||||||
|
backup-before-migrate: true
|
||||||
|
|
||||||
|
# Версия схемы базы данных
|
||||||
|
schema-version: 1
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ОТЛАДКА │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
debug:
|
||||||
|
# Логировать SQL запросы
|
||||||
|
log-queries: false
|
||||||
|
|
||||||
|
# Логировать медленные запросы (миллисекунды)
|
||||||
|
slow-query-threshold: 1000
|
||||||
|
|
||||||
|
# Показывать статистику соединений
|
||||||
|
show-connection-stats: false
|
||||||
|
|
||||||
|
# Интервал вывода статистики (секунды)
|
||||||
|
stats-interval: 300
|
||||||
286
src/main/resources/config/filters.yml
Normal file
286
src/main/resources/config/filters.yml
Normal file
|
|
@ -0,0 +1,286 @@
|
||||||
|
# ╔══════════════════════════════════════════════════════════════════════════════╗
|
||||||
|
# ║ LoChat Filters Configuration ║
|
||||||
|
# ║ Конфигурация фильтров ║
|
||||||
|
# ║ Версия: 1.5.5-1.20.1 ║
|
||||||
|
# ╚══════════════════════════════════════════════════════════════════════════════╝
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ФИЛЬТР ЗАГЛАВНЫХ БУКВ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
caps:
|
||||||
|
# Включить фильтр заглавных букв
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# Максимальный процент заглавных букв (0-100)
|
||||||
|
max-percent: 70
|
||||||
|
|
||||||
|
# Минимальная длина сообщения для проверки
|
||||||
|
min-length: 5
|
||||||
|
|
||||||
|
# Автоматически переводить в нижний регистр
|
||||||
|
auto-lowercase: true
|
||||||
|
|
||||||
|
# Действие при нарушении: block, warn, lowercase
|
||||||
|
action: "lowercase"
|
||||||
|
|
||||||
|
# Сообщение при блокировке
|
||||||
|
block-message: "&#FF6B6BСлишком много заглавных букв!"
|
||||||
|
|
||||||
|
# Сообщение-предупреждение
|
||||||
|
warn-message: "&#FFA726Не используйте слишком много заглавных букв"
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ФИЛЬТР РЕКЛАМЫ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
advertising:
|
||||||
|
# Включить фильтр рекламы
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# Блокировать скрытые URL (bit.ly, tinyurl и т.д.)
|
||||||
|
block-hidden-urls: true
|
||||||
|
|
||||||
|
# Блокировать домены
|
||||||
|
block-domains: true
|
||||||
|
|
||||||
|
# Блокировать IP адреса
|
||||||
|
block-ips: true
|
||||||
|
|
||||||
|
# Действие при обнаружении: block, warn, replace
|
||||||
|
action: "block"
|
||||||
|
|
||||||
|
# Сообщение при блокировке
|
||||||
|
block-message: "&#FF6B6BРеклама запрещена!"
|
||||||
|
|
||||||
|
# Замена для заблокированного контента
|
||||||
|
replacement: "[РЕКЛАМА УДАЛЕНА]"
|
||||||
|
|
||||||
|
# Белый список доменов (разрешенные)
|
||||||
|
whitelist:
|
||||||
|
- "youtube.com"
|
||||||
|
- "youtu.be"
|
||||||
|
- "discord.gg"
|
||||||
|
- "twitch.tv"
|
||||||
|
- "imgur.com"
|
||||||
|
- "gyazo.com"
|
||||||
|
- "prntscr.com"
|
||||||
|
|
||||||
|
# Черный список доменов (запрещенные)
|
||||||
|
blacklist:
|
||||||
|
- "scam-site.com"
|
||||||
|
- "virus-site.ru"
|
||||||
|
- "fake-minecraft.net"
|
||||||
|
|
||||||
|
# Регулярные выражения для поиска рекламы
|
||||||
|
patterns:
|
||||||
|
- "(?i)\\b(?:[0-9]{1,3}\\.){3}[0-9]{1,3}(?::[0-9]{1,5})?\\b" # IP адреса
|
||||||
|
- "(?i)\\b[a-z0-9.-]+\\.(com|net|org|ru|de|uk)\\b" # Домены
|
||||||
|
- "(?i)\\b(server|сервер)\\s*[:-]?\\s*[a-z0-9.-]+\\b" # Серверы
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ФИЛЬТР IP АДРЕСОВ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
ip:
|
||||||
|
# Включить фильтр IP адресов
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# Блокировать сообщение или заменять IP
|
||||||
|
block: false
|
||||||
|
|
||||||
|
# Замена для IP адресов
|
||||||
|
replacement: "[IP СКРЫТ]"
|
||||||
|
|
||||||
|
# Сообщение при блокировке
|
||||||
|
block-message: "&#FF6B6BIP адреса запрещены!"
|
||||||
|
|
||||||
|
# Белый список IP (разрешенные)
|
||||||
|
whitelist:
|
||||||
|
- "127.0.0.1"
|
||||||
|
- "localhost"
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ФИЛЬТР ПОВТОРОВ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
repeat:
|
||||||
|
# Включить фильтр повторяющихся символов
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# Максимальное количество повторов подряд
|
||||||
|
max-repeats: 3
|
||||||
|
|
||||||
|
# Действие: block, warn, replace
|
||||||
|
action: "replace"
|
||||||
|
|
||||||
|
# Сообщение при блокировке
|
||||||
|
block-message: "&#FF6B6BНе повторяйте символы!"
|
||||||
|
|
||||||
|
# Автоматически сокращать повторы
|
||||||
|
auto-reduce: true
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ФИЛЬТР СПАМА │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
spam:
|
||||||
|
# Включить антиспам
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# Максимальное количество одинаковых сообщений
|
||||||
|
max-similar-messages: 3
|
||||||
|
|
||||||
|
# Время для сброса счетчика (секунды)
|
||||||
|
reset-time: 60
|
||||||
|
|
||||||
|
# Процент схожести сообщений (0-100)
|
||||||
|
similarity-threshold: 80
|
||||||
|
|
||||||
|
# Действие при спаме: block, warn, mute
|
||||||
|
action: "warn"
|
||||||
|
|
||||||
|
# Сообщение при блокировке
|
||||||
|
block-message: "&#FF6B6BНе спамьте!"
|
||||||
|
|
||||||
|
# Время мута за спам (секунды)
|
||||||
|
mute-duration: 300
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ФИЛЬТР МАТА │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
swear:
|
||||||
|
# Включить фильтр мата
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# Использовать внешний файл со словами
|
||||||
|
use-external-file: true
|
||||||
|
|
||||||
|
# Файл со словами (относительно папки плагина)
|
||||||
|
words-file: "filter-words.json"
|
||||||
|
|
||||||
|
# Действие: block, warn, replace, mute
|
||||||
|
action: "replace"
|
||||||
|
|
||||||
|
# Символ для замены
|
||||||
|
replacement-char: "*"
|
||||||
|
|
||||||
|
# Сообщение при блокировке
|
||||||
|
block-message: "&#FF6B6BМат запрещен!"
|
||||||
|
|
||||||
|
# Время мута за мат (секунды)
|
||||||
|
mute-duration: 600
|
||||||
|
|
||||||
|
# Встроенный список слов (если не используется внешний файл)
|
||||||
|
words:
|
||||||
|
- "плохое_слово1"
|
||||||
|
- "плохое_слово2"
|
||||||
|
|
||||||
|
# Проверять фрагменты слов
|
||||||
|
check-fragments: true
|
||||||
|
|
||||||
|
# Игнорировать регистр
|
||||||
|
ignore-case: true
|
||||||
|
|
||||||
|
# Проверять транслитерацию
|
||||||
|
check-transliteration: true
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ФИЛЬТР ФЛУДА │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
flood:
|
||||||
|
# Включить антифлуд
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# Максимальное количество сообщений в период
|
||||||
|
max-messages: 5
|
||||||
|
|
||||||
|
# Период времени (секунды)
|
||||||
|
time-period: 10
|
||||||
|
|
||||||
|
# Действие при флуде: block, warn, mute
|
||||||
|
action: "warn"
|
||||||
|
|
||||||
|
# Сообщение при блокировке
|
||||||
|
block-message: "&#FF6B6BНе флудите!"
|
||||||
|
|
||||||
|
# Время мута за флуд (секунды)
|
||||||
|
mute-duration: 180
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ДОПОЛНИТЕЛЬНЫЕ ФИЛЬТРЫ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
additional:
|
||||||
|
# Фильтр эмодзи
|
||||||
|
emoji:
|
||||||
|
enabled: false
|
||||||
|
max-per-message: 5
|
||||||
|
block-message: "&#FF6B6BСлишком много эмодзи!"
|
||||||
|
|
||||||
|
# Фильтр длинных сообщений
|
||||||
|
length:
|
||||||
|
enabled: true
|
||||||
|
max-length: 256
|
||||||
|
action: "truncate" # truncate или block
|
||||||
|
block-message: "&#FF6B6BСообщение слишком длинное!"
|
||||||
|
|
||||||
|
# Фильтр пустых сообщений
|
||||||
|
empty:
|
||||||
|
enabled: true
|
||||||
|
block-message: "&#FF6B6BПустые сообщения запрещены!"
|
||||||
|
|
||||||
|
# Фильтр только пробелов
|
||||||
|
whitespace:
|
||||||
|
enabled: true
|
||||||
|
block-message: "&#FF6B6BСообщение не может состоять только из пробелов!"
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ НАСТРОЙКИ ОБХОДА │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
bypass:
|
||||||
|
# Права для обхода фильтров
|
||||||
|
permissions:
|
||||||
|
caps: "lochat.bypass.caps"
|
||||||
|
advertising: "lochat.bypass.advertising"
|
||||||
|
ip: "lochat.bypass.ip"
|
||||||
|
repeat: "lochat.bypass.repeat"
|
||||||
|
spam: "lochat.bypass.spam"
|
||||||
|
swear: "lochat.bypass.swear"
|
||||||
|
flood: "lochat.bypass.flood"
|
||||||
|
all: "lochat.bypass.filter"
|
||||||
|
|
||||||
|
# Группы, которые обходят все фильтры
|
||||||
|
groups:
|
||||||
|
- "admin"
|
||||||
|
- "moderator"
|
||||||
|
|
||||||
|
# Миры, где фильтры отключены
|
||||||
|
worlds:
|
||||||
|
- "creative_world"
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ЛОГИРОВАНИЕ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
logging:
|
||||||
|
# Логировать заблокированные сообщения
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# Файл для логов
|
||||||
|
file: "plugins/LoChat/logs/filter.log"
|
||||||
|
|
||||||
|
# Формат лога
|
||||||
|
format: "[{time}] {player} ({filter}): {message}"
|
||||||
|
|
||||||
|
# Логировать в консоль
|
||||||
|
console: true
|
||||||
|
|
||||||
|
# Уведомлять администраторов
|
||||||
|
notify-admins: true
|
||||||
|
|
||||||
|
# Право для получения уведомлений
|
||||||
|
notify-permission: "lochat.filter.notify"
|
||||||
208
src/main/resources/config/gradient-config.yml
Normal file
208
src/main/resources/config/gradient-config.yml
Normal file
|
|
@ -0,0 +1,208 @@
|
||||||
|
# ╔══════════════════════════════════════════════════════════════════════════════╗
|
||||||
|
# ║ LoChat Gradient Configuration ║
|
||||||
|
# ║ Конфигурация градиентов ║
|
||||||
|
# ║ Версия: 1.5.5-1.20.1 ║
|
||||||
|
# ╚══════════════════════════════════════════════════════════════════════════════╝
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ОСНОВНЫЕ НАСТРОЙКИ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
gradient:
|
||||||
|
# Тип хранения данных: file, mysql, sqlite
|
||||||
|
storage-type: "file"
|
||||||
|
|
||||||
|
# Минимальное количество цветов в градиенте
|
||||||
|
min-colors: 1
|
||||||
|
|
||||||
|
# Максимальное количество цветов в градиенте
|
||||||
|
max-colors: 7
|
||||||
|
|
||||||
|
# Стоимость за каждый цвет (PlayerPoints)
|
||||||
|
price-per-color: 50
|
||||||
|
|
||||||
|
# Стоимость префикса
|
||||||
|
prefix-price: 500
|
||||||
|
|
||||||
|
# Одноразовая покупка префикса (true) или за каждое изменение (false)
|
||||||
|
prefix-one-time-purchase: true
|
||||||
|
|
||||||
|
# Максимальная длина префикса
|
||||||
|
max-prefix-length: 16
|
||||||
|
|
||||||
|
# Кулдаун на смену цвета (секунды)
|
||||||
|
color-cooldown: 60
|
||||||
|
|
||||||
|
# Кулдаун на смену префикса (секунды)
|
||||||
|
prefix-cooldown: 120
|
||||||
|
|
||||||
|
# Автоматически применять градиент к нику
|
||||||
|
auto-apply-gradient: true
|
||||||
|
|
||||||
|
# Обновлять отображаемое имя
|
||||||
|
update-display-name: true
|
||||||
|
|
||||||
|
# Обновлять таб-лист
|
||||||
|
update-tab-list: true
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ГОТОВЫЕ ПРЕСЕТЫ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
presets:
|
||||||
|
fire:
|
||||||
|
name: "Огонь"
|
||||||
|
colors: [ "#FF4500", "#FF6347", "#FFD700" ]
|
||||||
|
permission: "gradient.preset.fire"
|
||||||
|
price: 100
|
||||||
|
|
||||||
|
ocean:
|
||||||
|
name: "Океан"
|
||||||
|
colors: [ "#00CED1", "#1E90FF", "#4169E1" ]
|
||||||
|
permission: "gradient.preset.ocean"
|
||||||
|
price: 100
|
||||||
|
|
||||||
|
forest:
|
||||||
|
name: "Лес"
|
||||||
|
colors: [ "#228B22", "#32CD32", "#90EE90" ]
|
||||||
|
permission: "gradient.preset.forest"
|
||||||
|
price: 100
|
||||||
|
|
||||||
|
sunset:
|
||||||
|
name: "Закат"
|
||||||
|
colors: [ "#FF69B4", "#FF1493", "#DC143C" ]
|
||||||
|
permission: "gradient.preset.sunset"
|
||||||
|
price: 150
|
||||||
|
|
||||||
|
rainbow:
|
||||||
|
name: "Радуга"
|
||||||
|
colors: [ "#FF0000", "#FF7F00", "#FFFF00", "#00FF00", "#0000FF", "#4B0082", "#9400D3" ]
|
||||||
|
permission: "gradient.preset.rainbow"
|
||||||
|
price: 300
|
||||||
|
|
||||||
|
gold:
|
||||||
|
name: "Золото"
|
||||||
|
colors: [ "#FFD700", "#FFA500", "#FF8C00" ]
|
||||||
|
permission: "gradient.preset.gold"
|
||||||
|
price: 200
|
||||||
|
|
||||||
|
silver:
|
||||||
|
name: "Серебро"
|
||||||
|
colors: [ "#C0C0C0", "#A9A9A9", "#808080" ]
|
||||||
|
permission: "gradient.preset.silver"
|
||||||
|
price: 150
|
||||||
|
|
||||||
|
purple:
|
||||||
|
name: "Фиолетовый"
|
||||||
|
colors: [ "#9400D3", "#8A2BE2", "#DA70D6" ]
|
||||||
|
permission: "gradient.preset.purple"
|
||||||
|
price: 120
|
||||||
|
|
||||||
|
ice:
|
||||||
|
name: "Лёд"
|
||||||
|
colors: [ "#B0E0E6", "#87CEEB", "#4682B4" ]
|
||||||
|
permission: "gradient.preset.ice"
|
||||||
|
price: 120
|
||||||
|
|
||||||
|
lava:
|
||||||
|
name: "Лава"
|
||||||
|
colors: [ "#DC143C", "#B22222", "#8B0000" ]
|
||||||
|
permission: "gradient.preset.lava"
|
||||||
|
price: 150
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ НАСТРОЙКИ БАЗЫ ДАННЫХ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
database:
|
||||||
|
mysql:
|
||||||
|
host: "localhost"
|
||||||
|
port: 3306
|
||||||
|
database: "lochat"
|
||||||
|
username: "root"
|
||||||
|
password: "password"
|
||||||
|
table-prefix: "lochat_"
|
||||||
|
|
||||||
|
# Настройки пула соединений
|
||||||
|
pool:
|
||||||
|
maximum-pool-size: 10
|
||||||
|
minimum-idle: 5
|
||||||
|
connection-timeout: 30000
|
||||||
|
idle-timeout: 600000
|
||||||
|
max-lifetime: 1800000
|
||||||
|
|
||||||
|
sqlite:
|
||||||
|
file: "plugins/LoChat/gradient-data.db"
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ДОПОЛНИТЕЛЬНЫЕ ФУНКЦИИ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
features:
|
||||||
|
# Анимированные градиенты
|
||||||
|
animated-gradients:
|
||||||
|
enabled: false
|
||||||
|
speed: 1000 # миллисекунды
|
||||||
|
|
||||||
|
# Случайные градиенты
|
||||||
|
random-gradients:
|
||||||
|
enabled: true
|
||||||
|
change-interval: 3600 # секунды (1 час)
|
||||||
|
|
||||||
|
# Градиенты в чате
|
||||||
|
chat-gradients:
|
||||||
|
enabled: true
|
||||||
|
apply-to-messages: true
|
||||||
|
|
||||||
|
# Градиенты в табе
|
||||||
|
tab-gradients:
|
||||||
|
enabled: true
|
||||||
|
update-interval: 20 # тики
|
||||||
|
|
||||||
|
# Сохранение градиентов при выходе
|
||||||
|
save-on-quit: true
|
||||||
|
|
||||||
|
# Восстановление градиентов при входе
|
||||||
|
restore-on-join: true
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ПРАВА ДОСТУПА │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
# Базовые права
|
||||||
|
use-gradient: "gradient.use"
|
||||||
|
use-prefix: "gradient.prefix"
|
||||||
|
admin: "gradient.admin"
|
||||||
|
|
||||||
|
# Обход ограничений
|
||||||
|
bypass-cooldown: "gradient.bypass.cooldown"
|
||||||
|
bypass-cost: "gradient.bypass.cost"
|
||||||
|
bypass-length: "gradient.bypass.length"
|
||||||
|
|
||||||
|
# Дополнительные цвета
|
||||||
|
extra-colors:
|
||||||
|
"gradient.colors.5": 5
|
||||||
|
"gradient.colors.10": 10
|
||||||
|
"gradient.colors.15": 15
|
||||||
|
"gradient.colors.unlimited": 999
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ФОРМАТИРОВАНИЕ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
formatting:
|
||||||
|
# Формат ника с градиентом
|
||||||
|
nick-format: "{gradient}{nick}"
|
||||||
|
|
||||||
|
# Формат префикса с градиентом
|
||||||
|
prefix-format: "{gradient}{prefix}"
|
||||||
|
|
||||||
|
# Формат в табе
|
||||||
|
tab-format: "{prefix} {gradient}{nick}"
|
||||||
|
|
||||||
|
# Формат в чате
|
||||||
|
chat-format: "{prefix} {gradient}{nick}&r: {message}"
|
||||||
|
|
||||||
|
# Разделитель между префиксом и ником
|
||||||
|
separator: " "
|
||||||
380
src/main/resources/config/integrations.yml
Normal file
380
src/main/resources/config/integrations.yml
Normal file
|
|
@ -0,0 +1,380 @@
|
||||||
|
# ╔══════════════════════════════════════════════════════════════════════════════╗
|
||||||
|
# ║ LoChat Integrations ║
|
||||||
|
# ║ Интеграции ║
|
||||||
|
# ║ Версия: 1.5.5-1.20.1 ║
|
||||||
|
# ╚══════════════════════════════════════════════════════════════════════════════╝
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ PLACEHOLDERAPI │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
placeholderapi:
|
||||||
|
# Включить интеграцию с PlaceholderAPI
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# Регистрировать собственные плейсхолдеры
|
||||||
|
register-placeholders: true
|
||||||
|
|
||||||
|
# Доступные плейсхолдеры LoChat:
|
||||||
|
# %lochat_player_muted% - замучен ли игрок (true/false)
|
||||||
|
# %lochat_player_mute_time% - оставшееся время мута
|
||||||
|
# %lochat_player_mute_reason% - причина мута
|
||||||
|
# %lochat_player_gradient% - градиентный ник
|
||||||
|
# %lochat_player_prefix% - кастомный префикс
|
||||||
|
# %lochat_player_ignored_count% - количество игнорируемых игроков
|
||||||
|
# %lochat_player_messages_sent% - отправлено сообщений
|
||||||
|
# %lochat_player_last_message% - последнее сообщение
|
||||||
|
# %lochat_server_muted_count% - количество замученных игроков
|
||||||
|
# %lochat_server_messages_today% - сообщений сегодня
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ LUCKPERMS │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
luckperms:
|
||||||
|
# Включить интеграцию с LuckPerms
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# Использовать префиксы из LuckPerms
|
||||||
|
use-prefix: true
|
||||||
|
|
||||||
|
# Использовать суффиксы из LuckPerms
|
||||||
|
use-suffix: true
|
||||||
|
|
||||||
|
# Использовать мета-данные из LuckPerms
|
||||||
|
use-meta: true
|
||||||
|
|
||||||
|
# Приоритет групп для форматирования чата
|
||||||
|
group-priority: true
|
||||||
|
|
||||||
|
# Кэшировать данные LuckPerms
|
||||||
|
cache-data: true
|
||||||
|
|
||||||
|
# Время кэширования (секунды)
|
||||||
|
cache-duration: 300
|
||||||
|
|
||||||
|
# Синхронизировать изменения прав
|
||||||
|
sync-changes: true
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ VAULT │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
vault:
|
||||||
|
# Включить интеграцию с Vault
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# Использовать Vault для прав
|
||||||
|
use-permissions: true
|
||||||
|
|
||||||
|
# Использовать Vault для экономики
|
||||||
|
use-economy: true
|
||||||
|
|
||||||
|
# Использовать Vault для чата (префиксы/суффиксы)
|
||||||
|
use-chat: true
|
||||||
|
|
||||||
|
# Приоритет Vault над другими системами
|
||||||
|
priority: 1
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ PLAYERPOINTS │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
playerpoints:
|
||||||
|
# Включить интеграцию с PlayerPoints
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# Использовать поинты для покупки градиентов
|
||||||
|
use-for-gradients: true
|
||||||
|
|
||||||
|
# Использовать поинты для покупки префиксов
|
||||||
|
use-for-prefixes: true
|
||||||
|
|
||||||
|
# Автоматически списывать поинты
|
||||||
|
auto-deduct: true
|
||||||
|
|
||||||
|
# Уведомлять о списании поинтов
|
||||||
|
notify-deduction: true
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ LIBERTYBANS │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
libertybans:
|
||||||
|
# Включить интеграцию с LibertyBans
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
# Синхронизировать муты с LibertyBans
|
||||||
|
sync-mutes: true
|
||||||
|
|
||||||
|
# Использовать LibertyBans для мутов вместо встроенной системы
|
||||||
|
use-for-mutes: false
|
||||||
|
|
||||||
|
# Импортировать существующие муты из LibertyBans
|
||||||
|
import-existing: false
|
||||||
|
|
||||||
|
# Экспортировать муты в LibertyBans
|
||||||
|
export-mutes: true
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ SKINSRESTORER │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
skinsrestorer:
|
||||||
|
# Включить интеграцию с SkinsRestorer
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# Обновлять отображение при смене скина
|
||||||
|
update-on-skin-change: true
|
||||||
|
|
||||||
|
# Использовать скины в head emoji
|
||||||
|
use-in-head-emoji: true
|
||||||
|
|
||||||
|
# Кэшировать данные скинов
|
||||||
|
cache-skins: true
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ DISCORDSRV │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
discordsrv:
|
||||||
|
# Включить интеграцию с DiscordSRV
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
# Отправлять сообщения чата в Discord
|
||||||
|
send-chat-to-discord: true
|
||||||
|
|
||||||
|
# Отправлять сообщения из Discord в игру
|
||||||
|
send-discord-to-chat: true
|
||||||
|
|
||||||
|
# Канал для глобального чата
|
||||||
|
global-chat-channel: "global-chat"
|
||||||
|
|
||||||
|
# Канал для локального чата
|
||||||
|
local-chat-channel: "local-chat"
|
||||||
|
|
||||||
|
# Канал для объявлений
|
||||||
|
announcement-channel: "announcements"
|
||||||
|
|
||||||
|
# Формат сообщений в Discord
|
||||||
|
discord-format: "**{player}**: {message}"
|
||||||
|
|
||||||
|
# Формат сообщений из Discord
|
||||||
|
minecraft-format: "&7[Discord] &b{user}&7: {message}"
|
||||||
|
|
||||||
|
# Использовать градиентные ники в Discord
|
||||||
|
use-gradients-in-discord: false
|
||||||
|
|
||||||
|
# Webhook для отправки сообщений
|
||||||
|
webhook:
|
||||||
|
enabled: false
|
||||||
|
url: ""
|
||||||
|
username: "LoChat"
|
||||||
|
avatar-url: ""
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ DYNMAP │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
dynmap:
|
||||||
|
# Включить интеграцию с Dynmap
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
# Отправлять сообщения чата на веб-карту
|
||||||
|
send-chat-to-web: true
|
||||||
|
|
||||||
|
# Отправлять сообщения с веб-карты в игру
|
||||||
|
send-web-to-chat: true
|
||||||
|
|
||||||
|
# Формат сообщений на веб-карте
|
||||||
|
web-format: "{player}: {message}"
|
||||||
|
|
||||||
|
# Формат сообщений с веб-карты
|
||||||
|
minecraft-format: "&7[Web] &a{player}&7: {message}"
|
||||||
|
|
||||||
|
# Использовать градиентные ники на веб-карте
|
||||||
|
use-gradients-on-web: false
|
||||||
|
|
||||||
|
# Фильтровать сообщения для веб-карты
|
||||||
|
filter-messages: true
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ BLUEMAP │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
bluemap:
|
||||||
|
# Включить интеграцию с BlueMap
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
# Отправлять сообщения чата на карту
|
||||||
|
send-chat-to-map: true
|
||||||
|
|
||||||
|
# Формат сообщений на карте
|
||||||
|
map-format: "{player}: {message}"
|
||||||
|
|
||||||
|
# Использовать градиентные ники на карте
|
||||||
|
use-gradients-on-map: false
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ PLAN │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
plan:
|
||||||
|
# Включить интеграцию с Plan
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
# Отправлять статистику чата в Plan
|
||||||
|
send-chat-stats: true
|
||||||
|
|
||||||
|
# Отправлять статистику мутов в Plan
|
||||||
|
send-mute-stats: true
|
||||||
|
|
||||||
|
# Интервал отправки статистики (секунды)
|
||||||
|
stats-interval: 300
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ COREPROTECT │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
coreprotect:
|
||||||
|
# Включить интеграцию с CoreProtect
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
# Логировать сообщения чата
|
||||||
|
log-chat-messages: true
|
||||||
|
|
||||||
|
# Логировать команды
|
||||||
|
log-commands: true
|
||||||
|
|
||||||
|
# Логировать муты
|
||||||
|
log-mutes: true
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ AUTHME │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
authme:
|
||||||
|
# Включить интеграцию с AuthMe
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
# Блокировать чат для неавторизованных игроков
|
||||||
|
block-chat-for-unregistered: true
|
||||||
|
|
||||||
|
# Сообщение для неавторизованных игроков
|
||||||
|
unregistered-message: "&#FF6B6BВойдите в аккаунт для использования чата!"
|
||||||
|
|
||||||
|
# Разрешенные команды для неавторизованных
|
||||||
|
allowed-commands:
|
||||||
|
- "/login"
|
||||||
|
- "/register"
|
||||||
|
- "/l"
|
||||||
|
- "/reg"
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ TOWNY │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
towny:
|
||||||
|
# Включить интеграцию с Towny
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
# Чат города
|
||||||
|
town-chat:
|
||||||
|
enabled: true
|
||||||
|
format: "&6[Town] {prefix}{player}&r: {message}"
|
||||||
|
command: "/tc"
|
||||||
|
|
||||||
|
# Чат нации
|
||||||
|
nation-chat:
|
||||||
|
enabled: true
|
||||||
|
format: "&5[Nation] {prefix}{player}&r: {message}"
|
||||||
|
command: "/nc"
|
||||||
|
|
||||||
|
# Показывать город в чате
|
||||||
|
show-town-in-chat: true
|
||||||
|
|
||||||
|
# Формат города в чате
|
||||||
|
town-format: "&7[{town}]"
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ FACTIONS │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
factions:
|
||||||
|
# Включить интеграцию с Factions
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
# Чат фракции
|
||||||
|
faction-chat:
|
||||||
|
enabled: true
|
||||||
|
format: "&c[Faction] {prefix}{player}&r: {message}"
|
||||||
|
command: "/fc"
|
||||||
|
|
||||||
|
# Чат альянса
|
||||||
|
alliance-chat:
|
||||||
|
enabled: true
|
||||||
|
format: "&a[Alliance] {prefix}{player}&r: {message}"
|
||||||
|
command: "/ac"
|
||||||
|
|
||||||
|
# Показывать фракцию в чате
|
||||||
|
show-faction-in-chat: true
|
||||||
|
|
||||||
|
# Формат фракции в чате
|
||||||
|
faction-format: "&7[{faction}]"
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ MULTIVERSE │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
multiverse:
|
||||||
|
# Включить интеграцию с Multiverse
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
# Разделять чат по мирам
|
||||||
|
separate-chat-by-world: false
|
||||||
|
|
||||||
|
# Показывать мир в чате
|
||||||
|
show-world-in-chat: true
|
||||||
|
|
||||||
|
# Формат мира в чате
|
||||||
|
world-format: "&7[{world}]"
|
||||||
|
|
||||||
|
# Настройки чата для конкретных миров
|
||||||
|
world-settings:
|
||||||
|
world_nether:
|
||||||
|
chat-color: "&c"
|
||||||
|
prefix: "&4[Nether]"
|
||||||
|
|
||||||
|
world_the_end:
|
||||||
|
chat-color: "&5"
|
||||||
|
prefix: "&d[End]"
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ОБЩИЕ НАСТРОЙКИ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
general:
|
||||||
|
# Автоматически определять доступные плагины
|
||||||
|
auto-detect-plugins: true
|
||||||
|
|
||||||
|
# Интервал проверки плагинов (секунды)
|
||||||
|
plugin-check-interval: 60
|
||||||
|
|
||||||
|
# Логировать интеграции
|
||||||
|
log-integrations: true
|
||||||
|
|
||||||
|
# Уведомлять о подключении/отключении интеграций
|
||||||
|
notify-integration-changes: true
|
||||||
|
|
||||||
|
# Приоритет интеграций (чем выше число, тем выше приоритет)
|
||||||
|
integration-priority:
|
||||||
|
luckperms: 100
|
||||||
|
vault: 90
|
||||||
|
placeholderapi: 80
|
||||||
|
playerpoints: 70
|
||||||
|
libertybans: 60
|
||||||
|
skinsrestorer: 50
|
||||||
|
discordsrv: 40
|
||||||
|
dynmap: 30
|
||||||
|
plan: 20
|
||||||
|
coreprotect: 10
|
||||||
336
src/main/resources/config/mute-config.yml
Normal file
336
src/main/resources/config/mute-config.yml
Normal file
|
|
@ -0,0 +1,336 @@
|
||||||
|
# ╔══════════════════════════════════════════════════════════════════════════════╗
|
||||||
|
# ║ LoChat Mute Configuration ║
|
||||||
|
# ║ Конфигурация мутов ║
|
||||||
|
# ║ Версия: 1.5.5-1.20.1 ║
|
||||||
|
# ╚══════════════════════════════════════════════════════════════════════════════╝
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ОСНОВНЫЕ НАСТРОЙКИ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
settings:
|
||||||
|
# Причина мута по умолчанию
|
||||||
|
default-reason: "Нарушение правил чата"
|
||||||
|
|
||||||
|
# Длительность мута по умолчанию
|
||||||
|
default-duration: "1h"
|
||||||
|
|
||||||
|
# Максимальная длина причины мута
|
||||||
|
max-reason-length: 100
|
||||||
|
|
||||||
|
# Показывать причину мута игроку
|
||||||
|
show-reason: true
|
||||||
|
|
||||||
|
# Показывать оставшееся время мута
|
||||||
|
show-remaining-time: true
|
||||||
|
|
||||||
|
# Автоматически размучивать при истечении времени
|
||||||
|
auto-unmute: true
|
||||||
|
|
||||||
|
# Сохранять историю мутов
|
||||||
|
save-history: true
|
||||||
|
|
||||||
|
# Максимальное количество записей в истории на игрока
|
||||||
|
max-history-entries: 50
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ДОСТУПНЫЕ ДЛИТЕЛЬНОСТИ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
durations:
|
||||||
|
# Формат: "время": "право для использования"
|
||||||
|
"5m":
|
||||||
|
permission: "lochat.mute.dur.5m"
|
||||||
|
display: "5 минут"
|
||||||
|
|
||||||
|
"10m":
|
||||||
|
permission: "lochat.mute.dur.10m"
|
||||||
|
display: "10 минут"
|
||||||
|
|
||||||
|
"30m":
|
||||||
|
permission: "lochat.mute.dur.30m"
|
||||||
|
display: "30 минут"
|
||||||
|
|
||||||
|
"1h":
|
||||||
|
permission: "lochat.mute.dur.1h"
|
||||||
|
display: "1 час"
|
||||||
|
|
||||||
|
"3h":
|
||||||
|
permission: "lochat.mute.dur.3h"
|
||||||
|
display: "3 часа"
|
||||||
|
|
||||||
|
"6h":
|
||||||
|
permission: "lochat.mute.dur.6h"
|
||||||
|
display: "6 часов"
|
||||||
|
|
||||||
|
"12h":
|
||||||
|
permission: "lochat.mute.dur.12h"
|
||||||
|
display: "12 часов"
|
||||||
|
|
||||||
|
"1d":
|
||||||
|
permission: "lochat.mute.dur.1d"
|
||||||
|
display: "1 день"
|
||||||
|
|
||||||
|
"3d":
|
||||||
|
permission: "lochat.mute.dur.3d"
|
||||||
|
display: "3 дня"
|
||||||
|
|
||||||
|
"7d":
|
||||||
|
permission: "lochat.mute.dur.7d"
|
||||||
|
display: "7 дней"
|
||||||
|
|
||||||
|
"14d":
|
||||||
|
permission: "lochat.mute.dur.14d"
|
||||||
|
display: "14 дней"
|
||||||
|
|
||||||
|
"30d":
|
||||||
|
permission: "lochat.mute.dur.30d"
|
||||||
|
display: "30 дней"
|
||||||
|
|
||||||
|
"perm":
|
||||||
|
permission: "lochat.mute.dur.perm"
|
||||||
|
display: "Навсегда"
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ГОТОВЫЕ ПРИЧИНЫ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
reasons:
|
||||||
|
spam:
|
||||||
|
text: "Спам в чате"
|
||||||
|
duration: "30m"
|
||||||
|
permission: "lochat.mute.reason.spam"
|
||||||
|
|
||||||
|
caps:
|
||||||
|
text: "Злоупотребление заглавными буквами"
|
||||||
|
duration: "15m"
|
||||||
|
permission: "lochat.mute.reason.caps"
|
||||||
|
|
||||||
|
swear:
|
||||||
|
text: "Использование нецензурной лексики"
|
||||||
|
duration: "1h"
|
||||||
|
permission: "lochat.mute.reason.swear"
|
||||||
|
|
||||||
|
flood:
|
||||||
|
text: "Флуд в чате"
|
||||||
|
duration: "20m"
|
||||||
|
permission: "lochat.mute.reason.flood"
|
||||||
|
|
||||||
|
advertising:
|
||||||
|
text: "Реклама"
|
||||||
|
duration: "3h"
|
||||||
|
permission: "lochat.mute.reason.advertising"
|
||||||
|
|
||||||
|
insult:
|
||||||
|
text: "Оскорбления игроков"
|
||||||
|
duration: "2h"
|
||||||
|
permission: "lochat.mute.reason.insult"
|
||||||
|
|
||||||
|
toxicity:
|
||||||
|
text: "Токсичное поведение"
|
||||||
|
duration: "6h"
|
||||||
|
permission: "lochat.mute.reason.toxicity"
|
||||||
|
|
||||||
|
politics:
|
||||||
|
text: "Обсуждение политики"
|
||||||
|
duration: "1h"
|
||||||
|
permission: "lochat.mute.reason.politics"
|
||||||
|
|
||||||
|
religion:
|
||||||
|
text: "Религиозные споры"
|
||||||
|
duration: "1h"
|
||||||
|
permission: "lochat.mute.reason.religion"
|
||||||
|
|
||||||
|
begging:
|
||||||
|
text: "Попрошайничество"
|
||||||
|
duration: "30m"
|
||||||
|
permission: "lochat.mute.reason.begging"
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ АВТОМАТИЧЕСКИЕ МУТЫ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
auto-mute:
|
||||||
|
# Включить автоматические муты
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# Мут за спам
|
||||||
|
spam:
|
||||||
|
enabled: true
|
||||||
|
threshold: 5 # Количество сообщений
|
||||||
|
time-window: 10 # За какое время (секунды)
|
||||||
|
duration: "10m"
|
||||||
|
reason: "Автомут: спам в чате"
|
||||||
|
|
||||||
|
# Мут за мат
|
||||||
|
swear:
|
||||||
|
enabled: true
|
||||||
|
threshold: 3 # Количество нарушений
|
||||||
|
duration: "30m"
|
||||||
|
reason: "Автомут: использование мата"
|
||||||
|
|
||||||
|
# Мут за заглавные буквы
|
||||||
|
caps:
|
||||||
|
enabled: true
|
||||||
|
threshold: 5 # Количество нарушений
|
||||||
|
duration: "5m"
|
||||||
|
reason: "Автомут: злоупотребление CAPS"
|
||||||
|
|
||||||
|
# Мут за рекламу
|
||||||
|
advertising:
|
||||||
|
enabled: true
|
||||||
|
threshold: 1 # Одно нарушение
|
||||||
|
duration: "1h"
|
||||||
|
reason: "Автомут: реклама"
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ЭСКАЛАЦИЯ НАКАЗАНИЙ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
escalation:
|
||||||
|
# Включить эскалацию наказаний
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# Период для подсчета нарушений (дни)
|
||||||
|
period: 30
|
||||||
|
|
||||||
|
# Уровни наказаний
|
||||||
|
levels:
|
||||||
|
1:
|
||||||
|
duration: "30m"
|
||||||
|
reason: "Первое нарушение"
|
||||||
|
|
||||||
|
2:
|
||||||
|
duration: "2h"
|
||||||
|
reason: "Повторное нарушение"
|
||||||
|
|
||||||
|
3:
|
||||||
|
duration: "12h"
|
||||||
|
reason: "Третье нарушение"
|
||||||
|
|
||||||
|
4:
|
||||||
|
duration: "3d"
|
||||||
|
reason: "Четвертое нарушение"
|
||||||
|
|
||||||
|
5:
|
||||||
|
duration: "7d"
|
||||||
|
reason: "Пятое нарушение"
|
||||||
|
|
||||||
|
6:
|
||||||
|
duration: "perm"
|
||||||
|
reason: "Систематические нарушения"
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ УВЕДОМЛЕНИЯ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
notifications:
|
||||||
|
# Уведомлять администраторов о мутах
|
||||||
|
notify-staff: true
|
||||||
|
|
||||||
|
# Право для получения уведомлений
|
||||||
|
staff-permission: "lochat.mute.notify"
|
||||||
|
|
||||||
|
# Публичные уведомления о мутах
|
||||||
|
public-mute: false
|
||||||
|
|
||||||
|
# Публичные уведомления о размутах
|
||||||
|
public-unmute: false
|
||||||
|
|
||||||
|
# Скрытые муты (с флагом -s)
|
||||||
|
silent-mute:
|
||||||
|
enabled: true
|
||||||
|
permission: "lochat.mute.silent"
|
||||||
|
notify-permission: "lochat.mute.see-silent"
|
||||||
|
|
||||||
|
# Формат уведомлений
|
||||||
|
formats:
|
||||||
|
mute: "&#FF6B6B{moderator} замутил {player} на {duration}. Причина: {reason}"
|
||||||
|
unmute: "BCB77{moderator} размутил {player}"
|
||||||
|
silent-mute: "&#FFA726[ТИХО] {moderator} замутил {player} на {duration}. Причина: {reason}"
|
||||||
|
auto-mute: "&#FF6B6B[АВТО] {player} замучен на {duration}. Причина: {reason}"
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ИНТЕГРАЦИИ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
integrations:
|
||||||
|
# LibertyBans
|
||||||
|
libertybans:
|
||||||
|
enabled: false
|
||||||
|
sync-mutes: true
|
||||||
|
|
||||||
|
# AdvancedBan
|
||||||
|
advancedban:
|
||||||
|
enabled: false
|
||||||
|
sync-mutes: true
|
||||||
|
|
||||||
|
# LiteBans
|
||||||
|
litebans:
|
||||||
|
enabled: false
|
||||||
|
sync-mutes: true
|
||||||
|
|
||||||
|
# Discord уведомления
|
||||||
|
discord:
|
||||||
|
enabled: false
|
||||||
|
webhook-url: ""
|
||||||
|
format: "**{moderator}** замутил **{player}** на **{duration}**\nПричина: {reason}"
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ХРАНЕНИЕ ДАННЫХ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
storage:
|
||||||
|
# Тип хранения: file, mysql, sqlite
|
||||||
|
type: "file"
|
||||||
|
|
||||||
|
# Настройки MySQL
|
||||||
|
mysql:
|
||||||
|
host: "localhost"
|
||||||
|
port: 3306
|
||||||
|
database: "lochat"
|
||||||
|
username: "root"
|
||||||
|
password: "password"
|
||||||
|
table-prefix: "lochat_"
|
||||||
|
|
||||||
|
# Настройки SQLite
|
||||||
|
sqlite:
|
||||||
|
file: "plugins/LoChat/mutes.db"
|
||||||
|
|
||||||
|
# Автоматическая очистка старых записей
|
||||||
|
cleanup:
|
||||||
|
enabled: true
|
||||||
|
days: 90 # Удалять записи старше N дней
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ДОПОЛНИТЕЛЬНЫЕ ФУНКЦИИ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
features:
|
||||||
|
# Временные муты (автоматически снимаются)
|
||||||
|
temporary-mutes: true
|
||||||
|
|
||||||
|
# IP муты (мутить по IP адресу)
|
||||||
|
ip-mutes:
|
||||||
|
enabled: false
|
||||||
|
permission: "lochat.mute.ip"
|
||||||
|
|
||||||
|
# Мут команд (блокировать определенные команды)
|
||||||
|
command-mute:
|
||||||
|
enabled: false
|
||||||
|
blocked-commands:
|
||||||
|
- "me"
|
||||||
|
- "say"
|
||||||
|
- "tell"
|
||||||
|
|
||||||
|
# Предупреждения перед мутом
|
||||||
|
warnings:
|
||||||
|
enabled: true
|
||||||
|
max-warnings: 3
|
||||||
|
reset-time: 3600 # Сброс предупреждений (секунды)
|
||||||
|
|
||||||
|
# Апелляции на муты
|
||||||
|
appeals:
|
||||||
|
enabled: false
|
||||||
|
command: "/appeal"
|
||||||
|
permission: "lochat.appeal"
|
||||||
313
src/main/resources/config/sounds.yml
Normal file
313
src/main/resources/config/sounds.yml
Normal file
|
|
@ -0,0 +1,313 @@
|
||||||
|
# ╔══════════════════════════════════════════════════════════════════════════════╗
|
||||||
|
# ║ LoChat Sounds Configuration ║
|
||||||
|
# ║ Конфигурация звуков ║
|
||||||
|
# ║ Версия: 1.5.5-1.20.1 ║
|
||||||
|
# ╚══════════════════════════════════════════════════════════════════════════════╝
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ОСНОВНЫЕ НАСТРОЙКИ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
settings:
|
||||||
|
# Включить звуки
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# Глобальная громкость (0.0 - 1.0)
|
||||||
|
global-volume: 0.5
|
||||||
|
|
||||||
|
# Глобальная высота тона (0.5 - 2.0)
|
||||||
|
global-pitch: 1.0
|
||||||
|
|
||||||
|
# Разрешить игрокам отключать звуки
|
||||||
|
allow-disable: true
|
||||||
|
|
||||||
|
# Команда для управления звуками
|
||||||
|
toggle-command: "/sounds"
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ЗВУКИ СООБЩЕНИЙ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
messages:
|
||||||
|
# Личные сообщения
|
||||||
|
private-message:
|
||||||
|
enabled: true
|
||||||
|
sound: "BLOCK_NOTE_BLOCK_PLING"
|
||||||
|
volume: 0.8
|
||||||
|
pitch: 1.2
|
||||||
|
# Играть только получателю
|
||||||
|
receiver-only: true
|
||||||
|
|
||||||
|
# Упоминания в чате
|
||||||
|
mention:
|
||||||
|
enabled: true
|
||||||
|
sound: "BLOCK_NOTE_BLOCK_BELL"
|
||||||
|
volume: 0.7
|
||||||
|
pitch: 1.5
|
||||||
|
# Дополнительный звук для @everyone
|
||||||
|
everyone-sound: "BLOCK_NOTE_BLOCK_CHIME"
|
||||||
|
|
||||||
|
# Глобальный чат
|
||||||
|
global-chat:
|
||||||
|
enabled: false
|
||||||
|
sound: "UI_BUTTON_CLICK"
|
||||||
|
volume: 0.3
|
||||||
|
pitch: 1.0
|
||||||
|
|
||||||
|
# Локальный чат
|
||||||
|
local-chat:
|
||||||
|
enabled: false
|
||||||
|
sound: "UI_BUTTON_CLICK"
|
||||||
|
volume: 0.2
|
||||||
|
pitch: 0.8
|
||||||
|
|
||||||
|
# Объявления
|
||||||
|
announcement:
|
||||||
|
enabled: true
|
||||||
|
sound: "BLOCK_NOTE_BLOCK_CHIME"
|
||||||
|
volume: 1.0
|
||||||
|
pitch: 1.0
|
||||||
|
# Дополнительные звуки для важных объявлений
|
||||||
|
important-sound: "ENTITY_ENDER_DRAGON_GROWL"
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ЗВУКИ СИСТЕМЫ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
system:
|
||||||
|
# Подключение к серверу
|
||||||
|
join:
|
||||||
|
enabled: false
|
||||||
|
sound: "ENTITY_PLAYER_LEVELUP"
|
||||||
|
volume: 0.5
|
||||||
|
pitch: 1.0
|
||||||
|
# Играть только подключившемуся игроку
|
||||||
|
self-only: true
|
||||||
|
|
||||||
|
# Отключение от сервера
|
||||||
|
quit:
|
||||||
|
enabled: false
|
||||||
|
sound: "BLOCK_NOTE_BLOCK_BASS"
|
||||||
|
volume: 0.3
|
||||||
|
pitch: 0.8
|
||||||
|
|
||||||
|
# Мут игрока
|
||||||
|
mute:
|
||||||
|
enabled: true
|
||||||
|
sound: "BLOCK_ANVIL_LAND"
|
||||||
|
volume: 0.6
|
||||||
|
pitch: 0.5
|
||||||
|
# Играть замученному игроку
|
||||||
|
target-sound: "ENTITY_VILLAGER_NO"
|
||||||
|
|
||||||
|
# Размут игрока
|
||||||
|
unmute:
|
||||||
|
enabled: true
|
||||||
|
sound: "ENTITY_PLAYER_LEVELUP"
|
||||||
|
volume: 0.7
|
||||||
|
pitch: 1.2
|
||||||
|
# Играть размученному игроку
|
||||||
|
target-sound: "ENTITY_VILLAGER_YES"
|
||||||
|
|
||||||
|
# Очистка чата
|
||||||
|
clear-chat:
|
||||||
|
enabled: true
|
||||||
|
sound: "ITEM_BUCKET_EMPTY"
|
||||||
|
volume: 0.5
|
||||||
|
pitch: 1.5
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ЗВУКИ ГРАДИЕНТОВ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
gradient:
|
||||||
|
# Установка градиента
|
||||||
|
color-set:
|
||||||
|
enabled: true
|
||||||
|
sound: "BLOCK_NOTE_BLOCK_HARP"
|
||||||
|
volume: 0.6
|
||||||
|
pitch: 1.3
|
||||||
|
|
||||||
|
# Сброс градиента
|
||||||
|
color-reset:
|
||||||
|
enabled: true
|
||||||
|
sound: "BLOCK_NOTE_BLOCK_BASS"
|
||||||
|
volume: 0.4
|
||||||
|
pitch: 0.7
|
||||||
|
|
||||||
|
# Установка префикса
|
||||||
|
prefix-set:
|
||||||
|
enabled: true
|
||||||
|
sound: "BLOCK_NOTE_BLOCK_CHIME"
|
||||||
|
volume: 0.7
|
||||||
|
pitch: 1.4
|
||||||
|
|
||||||
|
# Ошибка (недостаточно средств, кулдаун и т.д.)
|
||||||
|
error:
|
||||||
|
enabled: true
|
||||||
|
sound: "ENTITY_VILLAGER_NO"
|
||||||
|
volume: 0.5
|
||||||
|
pitch: 0.8
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ЗВУКИ КОМАНД │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
commands:
|
||||||
|
# Успешное выполнение команды
|
||||||
|
success:
|
||||||
|
enabled: false
|
||||||
|
sound: "ENTITY_EXPERIENCE_ORB_PICKUP"
|
||||||
|
volume: 0.4
|
||||||
|
pitch: 1.2
|
||||||
|
|
||||||
|
# Ошибка выполнения команды
|
||||||
|
error:
|
||||||
|
enabled: true
|
||||||
|
sound: "ENTITY_VILLAGER_NO"
|
||||||
|
volume: 0.5
|
||||||
|
pitch: 0.8
|
||||||
|
|
||||||
|
# Недостаточно прав
|
||||||
|
no-permission:
|
||||||
|
enabled: true
|
||||||
|
sound: "BLOCK_NOTE_BLOCK_BASS"
|
||||||
|
volume: 0.6
|
||||||
|
pitch: 0.5
|
||||||
|
|
||||||
|
# Игрок не найден
|
||||||
|
player-not-found:
|
||||||
|
enabled: true
|
||||||
|
sound: "ENTITY_ITEM_BREAK"
|
||||||
|
volume: 0.4
|
||||||
|
pitch: 0.6
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ЗВУКИ ФИЛЬТРОВ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
filters:
|
||||||
|
# Сообщение заблокировано фильтром
|
||||||
|
blocked:
|
||||||
|
enabled: true
|
||||||
|
sound: "ENTITY_VILLAGER_NO"
|
||||||
|
volume: 0.6
|
||||||
|
pitch: 0.7
|
||||||
|
|
||||||
|
# Предупреждение от фильтра
|
||||||
|
warning:
|
||||||
|
enabled: true
|
||||||
|
sound: "BLOCK_NOTE_BLOCK_PLING"
|
||||||
|
volume: 0.5
|
||||||
|
pitch: 0.9
|
||||||
|
|
||||||
|
# Автоматическое исправление (например, caps)
|
||||||
|
auto-fix:
|
||||||
|
enabled: false
|
||||||
|
sound: "UI_BUTTON_CLICK"
|
||||||
|
volume: 0.3
|
||||||
|
pitch: 1.1
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ КАСТОМНЫЕ ЗВУКИ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
custom:
|
||||||
|
# Звуки для VIP игроков
|
||||||
|
vip:
|
||||||
|
enabled: false
|
||||||
|
join-sound: "ENTITY_PLAYER_LEVELUP"
|
||||||
|
message-sound: "BLOCK_NOTE_BLOCK_HARP"
|
||||||
|
volume: 0.8
|
||||||
|
pitch: 1.3
|
||||||
|
|
||||||
|
# Звуки для администраторов
|
||||||
|
admin:
|
||||||
|
enabled: false
|
||||||
|
join-sound: "ENTITY_ENDER_DRAGON_GROWL"
|
||||||
|
command-sound: "BLOCK_ANVIL_USE"
|
||||||
|
volume: 0.7
|
||||||
|
pitch: 1.0
|
||||||
|
|
||||||
|
# Праздничные звуки
|
||||||
|
holiday:
|
||||||
|
enabled: false
|
||||||
|
christmas:
|
||||||
|
sound: "BLOCK_NOTE_BLOCK_CHIME"
|
||||||
|
volume: 0.6
|
||||||
|
pitch: 1.5
|
||||||
|
new-year:
|
||||||
|
sound: "ENTITY_FIREWORK_ROCKET_BLAST"
|
||||||
|
volume: 0.8
|
||||||
|
pitch: 1.2
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ЗВУКОВЫЕ СХЕМЫ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
schemes:
|
||||||
|
# Классическая схема
|
||||||
|
classic:
|
||||||
|
name: "Классическая"
|
||||||
|
description: "Стандартные звуки Minecraft"
|
||||||
|
sounds:
|
||||||
|
private-message: "BLOCK_NOTE_BLOCK_PLING"
|
||||||
|
mention: "BLOCK_NOTE_BLOCK_BELL"
|
||||||
|
announcement: "BLOCK_NOTE_BLOCK_CHIME"
|
||||||
|
|
||||||
|
# Минималистичная схема
|
||||||
|
minimal:
|
||||||
|
name: "Минимальная"
|
||||||
|
description: "Только важные звуки"
|
||||||
|
sounds:
|
||||||
|
private-message: "UI_BUTTON_CLICK"
|
||||||
|
mention: "BLOCK_NOTE_BLOCK_PLING"
|
||||||
|
announcement: "ENTITY_EXPERIENCE_ORB_PICKUP"
|
||||||
|
|
||||||
|
# Отключенная схема
|
||||||
|
silent:
|
||||||
|
name: "Тишина"
|
||||||
|
description: "Все звуки отключены"
|
||||||
|
sounds: {}
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ НАСТРОЙКИ ПО МИРАМ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
worlds:
|
||||||
|
# Настройки для конкретных миров
|
||||||
|
world_nether:
|
||||||
|
volume-modifier: 0.7 # Уменьшить громкость на 30%
|
||||||
|
pitch-modifier: 0.8 # Понизить тон
|
||||||
|
|
||||||
|
world_the_end:
|
||||||
|
volume-modifier: 0.5
|
||||||
|
pitch-modifier: 1.2
|
||||||
|
# Отключить определенные звуки
|
||||||
|
disabled-sounds:
|
||||||
|
- "global-chat"
|
||||||
|
- "local-chat"
|
||||||
|
|
||||||
|
creative_world:
|
||||||
|
volume-modifier: 1.2
|
||||||
|
# Включить дополнительные звуки
|
||||||
|
extra-sounds:
|
||||||
|
build: "BLOCK_STONE_PLACE"
|
||||||
|
fly: "ENTITY_BAT_TAKEOFF"
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ПЕРСОНАЛЬНЫЕ НАСТРОЙКИ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
personal:
|
||||||
|
# Разрешить игрокам настраивать громкость
|
||||||
|
allow-volume-control: true
|
||||||
|
|
||||||
|
# Разрешить игрокам выбирать звуковые схемы
|
||||||
|
allow-scheme-selection: true
|
||||||
|
|
||||||
|
# Сохранять настройки игроков
|
||||||
|
save-preferences: true
|
||||||
|
|
||||||
|
# Файл для сохранения настроек
|
||||||
|
preferences-file: "plugins/LoChat/sound-preferences.yml"
|
||||||
91
src/main/resources/data/data.yml
Normal file
91
src/main/resources/data/data.yml
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
# ╔══════════════════════════════════════════════════════════════════════════════╗
|
||||||
|
# ║ LoChat Data Storage ║
|
||||||
|
# ║ Хранилище данных LoChat ║
|
||||||
|
# ║ Версия: 1.5.5-1.20.1 ║
|
||||||
|
# ╚══════════════════════════════════════════════════════════════════════════════╝
|
||||||
|
|
||||||
|
# Этот файл содержит основные данные плагина
|
||||||
|
# НЕ РЕДАКТИРУЙТЕ ЭТОТ ФАЙЛ ВРУЧНУЮ!
|
||||||
|
|
||||||
|
data-version: 1
|
||||||
|
last-updated: 0
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ДАННЫЕ ИГРОКОВ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
players: {}
|
||||||
|
# Структура:
|
||||||
|
# uuid:
|
||||||
|
# name: "PlayerName"
|
||||||
|
# display-name: "GradientName"
|
||||||
|
# first-join: 1234567890
|
||||||
|
# last-join: 1234567890
|
||||||
|
# total-playtime: 3600000
|
||||||
|
# settings:
|
||||||
|
# sounds-enabled: true
|
||||||
|
# auto-messages: true
|
||||||
|
# mentions-enabled: true
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ГРАДИЕНТНЫЕ НИКИ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
gradients: {}
|
||||||
|
# Структура:
|
||||||
|
# uuid:
|
||||||
|
# colors: ["#FF0000", "#00FF00", "#0000FF"]
|
||||||
|
# prefix: "[CUSTOM]"
|
||||||
|
# enabled: true
|
||||||
|
# created: 1234567890
|
||||||
|
# last-updated: 1234567890
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ АКТИВНЫЕ МУТЫ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
mutes: {}
|
||||||
|
# Структура:
|
||||||
|
# uuid:
|
||||||
|
# moderator: "ModeratorUUID"
|
||||||
|
# reason: "Причина мута"
|
||||||
|
# start-time: 1234567890
|
||||||
|
# end-time: 1234567890
|
||||||
|
# silent: false
|
||||||
|
# active: true
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ ИГНОРИРОВАНИЕ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
ignores: {}
|
||||||
|
# Структура:
|
||||||
|
# player-uuid:
|
||||||
|
# - "ignored-uuid-1"
|
||||||
|
# - "ignored-uuid-2"
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ СТАТИСТИКА │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
statistics:
|
||||||
|
total-messages: 0
|
||||||
|
messages-today: 0
|
||||||
|
last-reset: 0
|
||||||
|
top-chatters: {}
|
||||||
|
# uuid: message-count
|
||||||
|
|
||||||
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
# │ КЭШИРОВАННЫЕ ДАННЫЕ │
|
||||||
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
cache:
|
||||||
|
last-messages: {}
|
||||||
|
# uuid: "last message"
|
||||||
|
|
||||||
|
cooldowns: {}
|
||||||
|
# uuid:
|
||||||
|
# global: 1234567890
|
||||||
|
# local: 1234567890
|
||||||
|
# pm: 1234567890
|
||||||
|
# gradient: 1234567890
|
||||||
22
src/main/resources/data/gradients.yml
Normal file
22
src/main/resources/data/gradients.yml
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
# ╔══════════════════════════════════════════════════════════════════════════════╗
|
||||||
|
# ║ Gradient Data ║
|
||||||
|
# ║ Данные градиентов ║
|
||||||
|
# ╚══════════════════════════════════════════════════════════════════════════════╝
|
||||||
|
|
||||||
|
# НЕ РЕДАКТИРУЙТЕ ЭТОТ ФАЙЛ ВРУЧНУЮ!
|
||||||
|
|
||||||
|
data-version: 1
|
||||||
|
gradients: {}
|
||||||
|
|
||||||
|
# Пример структуры:
|
||||||
|
# 550e8400-e29b-41d4-a716-446655440000:
|
||||||
|
# colors:
|
||||||
|
# - "#FF0000"
|
||||||
|
# - "#00FF00"
|
||||||
|
# - "#0000FF"
|
||||||
|
# prefix: "[VIP]"
|
||||||
|
# enabled: true
|
||||||
|
# created: 1640995200000
|
||||||
|
# last-updated: 1640995200000
|
||||||
|
# preset-used: "rainbow"
|
||||||
|
# cost-paid: 300
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue