v1.5.5: Add &b&l formatting support, fix teleport issue, add display settings to config, hide TextDisplay on sneak
This commit is contained in:
parent
000f1962e0
commit
798e52eff9
7 changed files with 121 additions and 248 deletions
|
|
@ -3,7 +3,7 @@ plugins {
|
||||||
}
|
}
|
||||||
|
|
||||||
group = 'com.loki'
|
group = 'com.loki'
|
||||||
version = '1.5.4'
|
version = '1.5.5'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
|
@ -43,7 +43,7 @@ test {
|
||||||
}
|
}
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
archiveFileName = 'LoChat-1.5.4.jar'
|
archiveFileName = 'LoChat-1.5.5.jar'
|
||||||
from {
|
from {
|
||||||
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
|
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,12 @@ public class GradientConfig {
|
||||||
|
|
||||||
private final JavaPlugin plugin;
|
private final JavaPlugin plugin;
|
||||||
private FileConfiguration config;
|
private FileConfiguration config;
|
||||||
|
private FileConfiguration mainConfig;
|
||||||
private File configFile;
|
private File configFile;
|
||||||
|
|
||||||
public GradientConfig(JavaPlugin plugin) {
|
public GradientConfig(JavaPlugin plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
|
this.mainConfig = plugin.getConfig();
|
||||||
loadConfig();
|
loadConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -42,6 +44,7 @@ public class GradientConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reload() {
|
public void reload() {
|
||||||
|
this.mainConfig = plugin.getConfig();
|
||||||
loadConfig();
|
loadConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -80,14 +83,55 @@ public class GradientConfig {
|
||||||
.anyMatch(blacklisted -> lowerPrefix.contains(blacklisted.toLowerCase()));
|
.anyMatch(blacklisted -> lowerPrefix.contains(blacklisted.toLowerCase()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display settings
|
// Display settings - читаем из main config.yml, если есть, иначе из gradient-config.yml
|
||||||
public boolean isUpdateDisplayName() { return config.getBoolean("display.update-display-name", true); }
|
public boolean isUpdateDisplayName() {
|
||||||
public boolean isUpdateTabList() { return config.getBoolean("display.update-tab-list", true); }
|
if (mainConfig.contains("display.update-display-name")) {
|
||||||
public boolean isUseTextDisplay() { return config.getBoolean("display.use-text-display", true); }
|
return mainConfig.getBoolean("display.update-display-name", true);
|
||||||
public double getTextDisplayHeight() { return config.getDouble("display.text-display-height", 2.8); }
|
}
|
||||||
public float getTextDisplayScale() { return (float) config.getDouble("display.text-display-scale", 0.8); }
|
return config.getBoolean("display.update-display-name", true);
|
||||||
public boolean isTextDisplaySeeThrough() { return config.getBoolean("display.text-display-see-through", false); }
|
}
|
||||||
public String getTextDisplayFormat() { return config.getString("display.text-display-format", "{prefix}{player}"); }
|
|
||||||
|
public boolean isUpdateTabList() {
|
||||||
|
if (mainConfig.contains("display.update-tab-list")) {
|
||||||
|
return mainConfig.getBoolean("display.update-tab-list", true);
|
||||||
|
}
|
||||||
|
return config.getBoolean("display.update-tab-list", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isUseTextDisplay() {
|
||||||
|
if (mainConfig.contains("display.use-text-display")) {
|
||||||
|
return mainConfig.getBoolean("display.use-text-display", true);
|
||||||
|
}
|
||||||
|
return config.getBoolean("display.use-text-display", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getTextDisplayHeight() {
|
||||||
|
if (mainConfig.contains("display.text-display-height")) {
|
||||||
|
return mainConfig.getDouble("display.text-display-height", 2.8);
|
||||||
|
}
|
||||||
|
return config.getDouble("display.text-display-height", 2.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getTextDisplayScale() {
|
||||||
|
if (mainConfig.contains("display.text-display-scale")) {
|
||||||
|
return (float) mainConfig.getDouble("display.text-display-scale", 0.8);
|
||||||
|
}
|
||||||
|
return (float) config.getDouble("display.text-display-scale", 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isTextDisplaySeeThrough() {
|
||||||
|
if (mainConfig.contains("display.text-display-see-through")) {
|
||||||
|
return mainConfig.getBoolean("display.text-display-see-through", false);
|
||||||
|
}
|
||||||
|
return config.getBoolean("display.text-display-see-through", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTextDisplayFormat() {
|
||||||
|
if (mainConfig.contains("display.text-display-format")) {
|
||||||
|
return mainConfig.getString("display.text-display-format", "{prefix}{player}");
|
||||||
|
}
|
||||||
|
return config.getString("display.text-display-format", "{prefix}{player}");
|
||||||
|
}
|
||||||
|
|
||||||
// Метод для временного изменения настройки TextDisplay
|
// Метод для временного изменения настройки TextDisplay
|
||||||
public void setUseTextDisplay(boolean useTextDisplay) {
|
public void setUseTextDisplay(boolean useTextDisplay) {
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import org.bukkit.event.EventPriority;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.player.PlayerJoinEvent;
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
|
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Слушатель событий игроков для градиентного модуля
|
* Слушатель событий игроков для градиентного модуля
|
||||||
|
|
@ -62,9 +63,30 @@ public class GradientPlayerListener implements Listener {
|
||||||
public void onPlayerToggleSneak(org.bukkit.event.player.PlayerToggleSneakEvent event) {
|
public void onPlayerToggleSneak(org.bukkit.event.player.PlayerToggleSneakEvent event) {
|
||||||
Player player = event.getPlayer();
|
Player player = event.getPlayer();
|
||||||
|
|
||||||
// Обновляем TextDisplay чтобы он не скрывался при приседании
|
// Скрываем/показываем TextDisplay при приседании
|
||||||
if (module.getTextDisplayManager() != null && module.getTextDisplayManager().hasDisplay(player.getUniqueId())) {
|
if (module.getTextDisplayManager() != null && module.getTextDisplayManager().hasDisplay(player.getUniqueId())) {
|
||||||
FoliaUtil.runEntityTask(module.getPlugin(), player, () -> {
|
FoliaUtil.runEntityTask(module.getPlugin(), player, () -> {
|
||||||
|
if (event.isSneaking()) {
|
||||||
|
// Игрок начал приседать - скрываем TextDisplay
|
||||||
|
module.getTextDisplayManager().hidePlayerDisplay(player.getUniqueId());
|
||||||
|
} else {
|
||||||
|
// Игрок перестал приседать - показываем TextDisplay
|
||||||
|
module.getTextDisplayManager().showPlayerDisplay(player.getUniqueId());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.MONITOR)
|
||||||
|
public void onPlayerTeleport(PlayerTeleportEvent event) {
|
||||||
|
if (event.isCancelled()) return;
|
||||||
|
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
|
||||||
|
// Обновляем TextDisplay после телепортации
|
||||||
|
if (module.getTextDisplayManager() != null && module.getTextDisplayManager().hasDisplay(player.getUniqueId())) {
|
||||||
|
FoliaUtil.runEntityTask(module.getPlugin(), player, () -> {
|
||||||
|
if (!player.isOnline()) return;
|
||||||
module.getTextDisplayManager().updateDisplayPosition(player);
|
module.getTextDisplayManager().updateDisplayPosition(player);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,236 +0,0 @@
|
||||||
package com.loki.lochat.gradient.util;
|
|
||||||
|
|
||||||
import com.loki.lochat.gradient.GradientModule;
|
|
||||||
import com.loki.lochat.gradient.data.GradientPlayerData;
|
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.entity.TextDisplay;
|
|
||||||
import org.bukkit.util.Transformation;
|
|
||||||
import org.joml.AxisAngle4f;
|
|
||||||
import org.joml.Vector3f;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Менеджер для управления TextDisplay над игроками
|
|
||||||
*/
|
|
||||||
public class TextDisplayManager {
|
|
||||||
|
|
||||||
private final GradientModule module;
|
|
||||||
private final Map<UUID, TextDisplay> playerDisplays = new ConcurrentHashMap<>();
|
|
||||||
private static final MiniMessage MINI_MESSAGE = MiniMessage.miniMessage();
|
|
||||||
|
|
||||||
public TextDisplayManager(GradientModule module) {
|
|
||||||
this.module = module;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Создает или обновляет TextDisplay над игроком
|
|
||||||
*/
|
|
||||||
public void updatePlayerDisplay(Player player) {
|
|
||||||
if (!module.getConfig().isUpdateDisplayName() || !module.getConfig().isUseTextDisplay()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
GradientPlayerData data = module.getDataManager().getPlayerData(player.getUniqueId());
|
|
||||||
|
|
||||||
// Получаем текст для отображения
|
|
||||||
String displayText = getDisplayText(player, data);
|
|
||||||
Component textComponent = MINI_MESSAGE.deserialize(displayText);
|
|
||||||
|
|
||||||
TextDisplay display = playerDisplays.get(player.getUniqueId());
|
|
||||||
|
|
||||||
if (display == null || !display.isValid()) {
|
|
||||||
// Создаем новый TextDisplay
|
|
||||||
createTextDisplay(player, textComponent);
|
|
||||||
} else {
|
|
||||||
// Обновляем существующий
|
|
||||||
updateTextDisplay(display, player, textComponent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Создает новый TextDisplay над игроком
|
|
||||||
*/
|
|
||||||
private void createTextDisplay(Player player, Component textComponent) {
|
|
||||||
// Удаляем старый display если есть
|
|
||||||
removePlayerDisplay(player.getUniqueId());
|
|
||||||
|
|
||||||
double height = module.getConfig().getTextDisplayHeight();
|
|
||||||
float scale = module.getConfig().getTextDisplayScale();
|
|
||||||
boolean seeThrough = module.getConfig().isTextDisplaySeeThrough();
|
|
||||||
|
|
||||||
// Создаем новый TextDisplay
|
|
||||||
TextDisplay display = player.getWorld().spawn(
|
|
||||||
player.getLocation().add(0, height, 0), // Над головой игрока
|
|
||||||
TextDisplay.class,
|
|
||||||
entity -> {
|
|
||||||
entity.text(textComponent);
|
|
||||||
entity.setBillboard(org.bukkit.entity.Display.Billboard.CENTER);
|
|
||||||
entity.setViewRange(64.0f); // Видимость на 64 блока
|
|
||||||
entity.setSeeThrough(seeThrough); // Настраиваемая видимость через стены
|
|
||||||
entity.setShadowRadius(0.0f); // Без тени
|
|
||||||
entity.setShadowStrength(0.0f); // Без тени
|
|
||||||
|
|
||||||
// Настройка трансформации (размер текста)
|
|
||||||
entity.setTransformation(new Transformation(
|
|
||||||
new Vector3f(0, 0, 0), // Без смещения
|
|
||||||
new AxisAngle4f(0, 0, 0, 1), // Без поворота
|
|
||||||
new Vector3f(scale, scale, scale), // Размер текста
|
|
||||||
new AxisAngle4f(0, 0, 0, 1) // Без поворота после масштабирования
|
|
||||||
));
|
|
||||||
|
|
||||||
// Отключаем скрытие при приседании
|
|
||||||
entity.setVisibleByDefault(true);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Привязываем TextDisplay к игроку как пассажира
|
|
||||||
player.addPassenger(display);
|
|
||||||
|
|
||||||
// Сохраняем в карте
|
|
||||||
playerDisplays.put(player.getUniqueId(), display);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Обновляет существующий TextDisplay
|
|
||||||
*/
|
|
||||||
private void updateTextDisplay(TextDisplay display, Player player, Component textComponent) {
|
|
||||||
display.text(textComponent);
|
|
||||||
|
|
||||||
// Проверяем, что display все еще привязан к игроку
|
|
||||||
if (!player.getPassengers().contains(display)) {
|
|
||||||
player.addPassenger(display);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Получает текст для отображения над игроком
|
|
||||||
*/
|
|
||||||
private String getDisplayText(Player player, GradientPlayerData data) {
|
|
||||||
String format = module.getConfig().getTextDisplayFormat();
|
|
||||||
|
|
||||||
// Получаем компоненты
|
|
||||||
String prefix = getPlayerPrefix(player, data);
|
|
||||||
String playerName = getPlayerName(player, data);
|
|
||||||
|
|
||||||
// Заменяем плейсхолдеры
|
|
||||||
String result = format
|
|
||||||
.replace("{prefix}", prefix != null ? prefix : "")
|
|
||||||
.replace("{player}", playerName)
|
|
||||||
.replace("{name}", playerName); // Альтернативный плейсхолдер
|
|
||||||
|
|
||||||
// Конвертируем legacy форматы в MiniMessage
|
|
||||||
return convertLegacyFormats(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Конвертирует legacy форматы цветов в MiniMessage формат
|
|
||||||
*/
|
|
||||||
private String convertLegacyFormats(String message) {
|
|
||||||
if (message == null) return "";
|
|
||||||
|
|
||||||
// Конвертируем &#RRGGBB в <#RRGGBB>
|
|
||||||
message = message.replaceAll("&#([0-9a-fA-F]{6})", "<#$1>");
|
|
||||||
|
|
||||||
// Конвертируем #RRGGBB в <#RRGGBB> (только если не внутри тегов)
|
|
||||||
message = message.replaceAll("(?<!<)#([0-9a-fA-F]{6})(?![^<]*>)", "<#$1>");
|
|
||||||
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Получает префикс игрока
|
|
||||||
*/
|
|
||||||
private String getPlayerPrefix(Player player, GradientPlayerData data) {
|
|
||||||
String prefixFormat = module.getConfig().getPrefixFormat();
|
|
||||||
|
|
||||||
// Определяем префикс: сначала кастомный, потом LuckPerms
|
|
||||||
if (data.isPrefixEnabled() && data.hasPrefix()) {
|
|
||||||
String prefix = prefixFormat.replace("{prefix}", data.getPrefix());
|
|
||||||
// Применяем градиент только если цвета включены
|
|
||||||
if (data.isColorEnabled() && data.hasColors() && module.getConfig().isGradientOnPrefix()) {
|
|
||||||
return GradientUtil.applyGradient(prefix, data.getColors(), false); // MiniMessage формат
|
|
||||||
}
|
|
||||||
return prefix;
|
|
||||||
} else if (module.getLuckPermsHook().isEnabled()) {
|
|
||||||
String lpPrefix = module.getLuckPermsHook().getActivePrefix(player);
|
|
||||||
if (lpPrefix != null && !lpPrefix.isEmpty()) {
|
|
||||||
// Для LuckPerms префикса применяем градиент только если включено
|
|
||||||
if (data.isColorEnabled() && data.hasColors() && module.getConfig().isGradientOnLuckPermsPrefix()) {
|
|
||||||
String cleanPrefix = stripColors(lpPrefix);
|
|
||||||
return GradientUtil.applyGradient(cleanPrefix, data.getColors(), false);
|
|
||||||
}
|
|
||||||
return lpPrefix;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Получает имя игрока с градиентом
|
|
||||||
*/
|
|
||||||
private String getPlayerName(Player player, GradientPlayerData data) {
|
|
||||||
// Применяем градиент только если цвета включены
|
|
||||||
if (data.isColorEnabled() && data.hasColors()) {
|
|
||||||
return GradientUtil.applyGradient(player.getName(), data.getColors(), false); // MiniMessage формат
|
|
||||||
}
|
|
||||||
return player.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Убирает цветовые коды из строки
|
|
||||||
*/
|
|
||||||
private String stripColors(String text) {
|
|
||||||
if (text == null) return "";
|
|
||||||
return text.replaceAll("(?i)(§x(§[0-9a-f]){6}|§[0-9a-fk-or]|&[0-9a-fk-or]|&#[0-9a-f]{6}|<[^>]+>)", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Удаляет TextDisplay игрока
|
|
||||||
*/
|
|
||||||
public void removePlayerDisplay(UUID playerId) {
|
|
||||||
TextDisplay display = playerDisplays.remove(playerId);
|
|
||||||
if (display != null && display.isValid()) {
|
|
||||||
display.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Удаляет все TextDisplay
|
|
||||||
*/
|
|
||||||
public void removeAllDisplays() {
|
|
||||||
for (TextDisplay display : playerDisplays.values()) {
|
|
||||||
if (display != null && display.isValid()) {
|
|
||||||
display.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
playerDisplays.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Обновляет позицию TextDisplay (вызывается при движении игрока)
|
|
||||||
*/
|
|
||||||
public void updateDisplayPosition(Player player) {
|
|
||||||
TextDisplay display = playerDisplays.get(player.getUniqueId());
|
|
||||||
if (display != null && display.isValid()) {
|
|
||||||
// TextDisplay автоматически следует за игроком как пассажир
|
|
||||||
// Но можем обновить высоту если нужно
|
|
||||||
if (!player.getPassengers().contains(display)) {
|
|
||||||
player.addPassenger(display);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Проверяет, есть ли у игрока TextDisplay
|
|
||||||
*/
|
|
||||||
public boolean hasDisplay(UUID playerId) {
|
|
||||||
TextDisplay display = playerDisplays.get(playerId);
|
|
||||||
return display != null && display.isValid();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -45,6 +45,32 @@ public final class ChatFormatter {
|
||||||
// Конвертируем #RRGGBB в <#RRGGBB> (только если не внутри тегов)
|
// Конвертируем #RRGGBB в <#RRGGBB> (только если не внутри тегов)
|
||||||
message = message.replaceAll("(?<!<)#([0-9a-fA-F]{6})(?![^<]*>)", "<#$1>");
|
message = message.replaceAll("(?<!<)#([0-9a-fA-F]{6})(?![^<]*>)", "<#$1>");
|
||||||
|
|
||||||
|
// Конвертируем &[0-9a-fk-or] в соответствующие MiniMessage теги
|
||||||
|
message = message.replaceAll("&0", "<black>");
|
||||||
|
message = message.replaceAll("&1", "<dark_blue>");
|
||||||
|
message = message.replaceAll("&2", "<dark_green>");
|
||||||
|
message = message.replaceAll("&3", "<dark_aqua>");
|
||||||
|
message = message.replaceAll("&4", "<dark_red>");
|
||||||
|
message = message.replaceAll("&5", "<dark_purple>");
|
||||||
|
message = message.replaceAll("&6", "<gold>");
|
||||||
|
message = message.replaceAll("&7", "<gray>");
|
||||||
|
message = message.replaceAll("&8", "<dark_gray>");
|
||||||
|
message = message.replaceAll("&9", "<blue>");
|
||||||
|
message = message.replaceAll("&a", "<green>");
|
||||||
|
message = message.replaceAll("&b", "<aqua>");
|
||||||
|
message = message.replaceAll("&c", "<red>");
|
||||||
|
message = message.replaceAll("&d", "<light_purple>");
|
||||||
|
message = message.replaceAll("&e", "<yellow>");
|
||||||
|
message = message.replaceAll("&f", "<white>");
|
||||||
|
|
||||||
|
// Конвертируем форматирование
|
||||||
|
message = message.replaceAll("&k", "<obfuscated>");
|
||||||
|
message = message.replaceAll("&l", "<bold>");
|
||||||
|
message = message.replaceAll("&m", "<strikethrough>");
|
||||||
|
message = message.replaceAll("&n", "<underlined>");
|
||||||
|
message = message.replaceAll("&o", "<italic>");
|
||||||
|
message = message.replaceAll("&r", "<reset>");
|
||||||
|
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,23 @@ lopreff:
|
||||||
# Использовать кастомный префикс
|
# Использовать кастомный префикс
|
||||||
use-custom-prefix: true
|
use-custom-prefix: true
|
||||||
|
|
||||||
|
# Настройки отображения ника
|
||||||
|
display:
|
||||||
|
# Обновлять display name игрока (показывает префикс+ник над головой)
|
||||||
|
update-display-name: true
|
||||||
|
# Обновлять tab list
|
||||||
|
update-tab-list: true
|
||||||
|
# Использовать TextDisplay вместо обычного display name (1.19.4+)
|
||||||
|
use-text-display: true
|
||||||
|
# Высота TextDisplay над игроком (в блоках)
|
||||||
|
text-display-height: 2.8
|
||||||
|
# Размер TextDisplay (от 0.1 до 2.0)
|
||||||
|
text-display-scale: 0.8
|
||||||
|
# Видно ли TextDisplay через стены
|
||||||
|
text-display-see-through: false
|
||||||
|
# Формат TextDisplay (поддерживает &b&l и другие коды, &#RRGGBB, #RRGGBB)
|
||||||
|
text-display-format: "{prefix}{player}"
|
||||||
|
|
||||||
# Упоминания @ник
|
# Упоминания @ник
|
||||||
mentions:
|
mentions:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
name: LoChat
|
name: LoChat
|
||||||
version: '1.5.4'
|
version: '1.5.5'
|
||||||
main: com.loki.lochat.LoChat
|
main: com.loki.lochat.LoChat
|
||||||
api-version: '1.21'
|
api-version: '1.21'
|
||||||
folia-supported: true
|
folia-supported: true
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue