Add TextDisplay system for floating gradient names above players (1.19.4+)
This commit is contained in:
parent
64c672c02e
commit
dbb6a61351
7 changed files with 313 additions and 1 deletions
|
|
@ -12,6 +12,7 @@ import com.loki.lochat.gradient.listeners.GradientGUIListener;
|
||||||
import com.loki.lochat.gradient.listeners.GradientPlayerListener;
|
import com.loki.lochat.gradient.listeners.GradientPlayerListener;
|
||||||
import com.loki.lochat.gradient.util.DisplayNameUtil;
|
import com.loki.lochat.gradient.util.DisplayNameUtil;
|
||||||
import com.loki.lochat.gradient.util.GradientUtil;
|
import com.loki.lochat.gradient.util.GradientUtil;
|
||||||
|
import com.loki.lochat.gradient.util.TextDisplayManager;
|
||||||
import org.black_ixx.playerpoints.PlayerPoints;
|
import org.black_ixx.playerpoints.PlayerPoints;
|
||||||
import org.black_ixx.playerpoints.PlayerPointsAPI;
|
import org.black_ixx.playerpoints.PlayerPointsAPI;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
|
@ -29,6 +30,7 @@ public class GradientModule {
|
||||||
private GradientDataManager dataManager;
|
private GradientDataManager dataManager;
|
||||||
private GradientLuckPermsHook luckPermsHook;
|
private GradientLuckPermsHook luckPermsHook;
|
||||||
private PlayerPointsAPI playerPointsAPI;
|
private PlayerPointsAPI playerPointsAPI;
|
||||||
|
private TextDisplayManager textDisplayManager;
|
||||||
private boolean enabled;
|
private boolean enabled;
|
||||||
|
|
||||||
public GradientModule(JavaPlugin plugin) {
|
public GradientModule(JavaPlugin plugin) {
|
||||||
|
|
@ -64,6 +66,9 @@ public class GradientModule {
|
||||||
// Подключение LuckPerms
|
// Подключение LuckPerms
|
||||||
luckPermsHook = new GradientLuckPermsHook(plugin);
|
luckPermsHook = new GradientLuckPermsHook(plugin);
|
||||||
|
|
||||||
|
// Инициализация TextDisplayManager
|
||||||
|
textDisplayManager = new TextDisplayManager(this);
|
||||||
|
|
||||||
// Регистрация команд
|
// Регистрация команд
|
||||||
registerCommands();
|
registerCommands();
|
||||||
|
|
||||||
|
|
@ -100,6 +105,9 @@ public class GradientModule {
|
||||||
* Выключение модуля
|
* Выключение модуля
|
||||||
*/
|
*/
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
|
if (textDisplayManager != null) {
|
||||||
|
textDisplayManager.removeAllDisplays();
|
||||||
|
}
|
||||||
if (dataManager != null) {
|
if (dataManager != null) {
|
||||||
dataManager.saveAll();
|
dataManager.saveAll();
|
||||||
}
|
}
|
||||||
|
|
@ -260,6 +268,7 @@ public class GradientModule {
|
||||||
public GradientDataManager getDataManager() { return dataManager; }
|
public GradientDataManager getDataManager() { return dataManager; }
|
||||||
public GradientLuckPermsHook getLuckPermsHook() { return luckPermsHook; }
|
public GradientLuckPermsHook getLuckPermsHook() { return luckPermsHook; }
|
||||||
public PlayerPointsAPI getPlayerPointsAPI() { return playerPointsAPI; }
|
public PlayerPointsAPI getPlayerPointsAPI() { return playerPointsAPI; }
|
||||||
|
public TextDisplayManager getTextDisplayManager() { return textDisplayManager; }
|
||||||
public boolean hasPlayerPoints() { return playerPointsAPI != null; }
|
public boolean hasPlayerPoints() { return playerPointsAPI != null; }
|
||||||
public boolean isEnabled() { return enabled; }
|
public boolean isEnabled() { return enabled; }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,9 @@ public class GradientAdminCommand implements CommandExecutor, TabCompleter {
|
||||||
case "updateall" -> {
|
case "updateall" -> {
|
||||||
handleUpdateAll(sender, msg);
|
handleUpdateAll(sender, msg);
|
||||||
}
|
}
|
||||||
|
case "toggledisplay" -> {
|
||||||
|
handleToggleDisplay(sender, msg);
|
||||||
|
}
|
||||||
default -> sendHelp(sender);
|
default -> sendHelp(sender);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -104,6 +107,7 @@ public class GradientAdminCommand implements CommandExecutor, TabCompleter {
|
||||||
sender.sendMessage("§e/aprefix resetcolor <игрок> §7— сбросить цвет");
|
sender.sendMessage("§e/aprefix resetcolor <игрок> §7— сбросить цвет");
|
||||||
sender.sendMessage("§e/aprefix resetprefix <игрок> §7— сбросить префикс");
|
sender.sendMessage("§e/aprefix resetprefix <игрок> §7— сбросить префикс");
|
||||||
sender.sendMessage("§e/aprefix updateall §7— обновить display names всех игроков");
|
sender.sendMessage("§e/aprefix updateall §7— обновить display names всех игроков");
|
||||||
|
sender.sendMessage("§e/aprefix toggledisplay §7— переключить TextDisplay/обычный режим");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleInfo(CommandSender sender, String playerName, GradientMessages msg) {
|
private void handleInfo(CommandSender sender, String playerName, GradientMessages msg) {
|
||||||
|
|
@ -330,6 +334,37 @@ public class GradientAdminCommand implements CommandExecutor, TabCompleter {
|
||||||
sender.sendMessage("§aОбновлены display names для §f" + count + " §aигроков");
|
sender.sendMessage("§aОбновлены display names для §f" + count + " §aигроков");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleToggleDisplay(CommandSender sender, GradientMessages msg) {
|
||||||
|
// Переключаем режим TextDisplay в конфиге
|
||||||
|
boolean currentMode = module.getConfig().isUseTextDisplay();
|
||||||
|
boolean newMode = !currentMode;
|
||||||
|
|
||||||
|
// Обновляем конфиг (временно в памяти)
|
||||||
|
module.getConfig().setUseTextDisplay(newMode);
|
||||||
|
|
||||||
|
if (newMode) {
|
||||||
|
// Переключаемся на TextDisplay
|
||||||
|
sender.sendMessage("§aВключен режим TextDisplay");
|
||||||
|
// Удаляем все обычные display names и создаем TextDisplay
|
||||||
|
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||||
|
player.displayName(null); // Сбрасываем обычный display name
|
||||||
|
GradientPlayerData data = module.getDataManager().getPlayerData(player.getUniqueId());
|
||||||
|
FoliaUtil.runEntityTask(module.getPlugin(), player,
|
||||||
|
() -> module.getTextDisplayManager().updatePlayerDisplay(player));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Переключаемся на обычный display name
|
||||||
|
sender.sendMessage("§cВыключен режим TextDisplay");
|
||||||
|
// Удаляем все TextDisplay и обновляем обычные display names
|
||||||
|
module.getTextDisplayManager().removeAllDisplays();
|
||||||
|
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||||
|
GradientPlayerData data = module.getDataManager().getPlayerData(player.getUniqueId());
|
||||||
|
FoliaUtil.runEntityTask(module.getPlugin(), player,
|
||||||
|
() -> DisplayNameUtil.updateDisplayName(module, player, data));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command,
|
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command,
|
||||||
@NotNull String alias, @NotNull String[] args) {
|
@NotNull String alias, @NotNull String[] args) {
|
||||||
|
|
@ -337,7 +372,7 @@ public class GradientAdminCommand implements CommandExecutor, TabCompleter {
|
||||||
|
|
||||||
if (args.length == 1) {
|
if (args.length == 1) {
|
||||||
return Arrays.asList("reload", "info", "setcolor", "setprefix", "coloron", "coloroff",
|
return Arrays.asList("reload", "info", "setcolor", "setprefix", "coloron", "coloroff",
|
||||||
"prefixon", "prefixoff", "resetcolor", "resetprefix", "updateall").stream()
|
"prefixon", "prefixoff", "resetcolor", "resetprefix", "updateall", "toggledisplay").stream()
|
||||||
.filter(s -> s.startsWith(args[0].toLowerCase()))
|
.filter(s -> s.startsWith(args[0].toLowerCase()))
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -83,4 +83,12 @@ public class GradientConfig {
|
||||||
// Display settings
|
// Display settings
|
||||||
public boolean isUpdateDisplayName() { return config.getBoolean("display.update-display-name", true); }
|
public boolean isUpdateDisplayName() { return config.getBoolean("display.update-display-name", true); }
|
||||||
public boolean isUpdateTabList() { return config.getBoolean("display.update-tab-list", true); }
|
public boolean isUpdateTabList() { return config.getBoolean("display.update-tab-list", true); }
|
||||||
|
public boolean isUseTextDisplay() { return config.getBoolean("display.use-text-display", true); }
|
||||||
|
public double getTextDisplayHeight() { return config.getDouble("display.text-display-height", 2.3); }
|
||||||
|
public float getTextDisplayScale() { return (float) config.getDouble("display.text-display-scale", 0.8); }
|
||||||
|
|
||||||
|
// Метод для временного изменения настройки TextDisplay
|
||||||
|
public void setUseTextDisplay(boolean useTextDisplay) {
|
||||||
|
config.set("display.use-text-display", useTextDisplay);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,12 @@ public class GradientPlayerListener implements Listener {
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||||
Player player = event.getPlayer();
|
Player player = event.getPlayer();
|
||||||
|
|
||||||
|
// Удаляем TextDisplay если есть
|
||||||
|
if (module.getTextDisplayManager() != null) {
|
||||||
|
module.getTextDisplayManager().removePlayerDisplay(player.getUniqueId());
|
||||||
|
}
|
||||||
|
|
||||||
FoliaUtil.runAsync(module.getPlugin(),
|
FoliaUtil.runAsync(module.getPlugin(),
|
||||||
() -> module.getDataManager().savePlayerData(player.getUniqueId()));
|
() -> module.getDataManager().savePlayerData(player.getUniqueId()));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,12 @@ public final class DisplayNameUtil {
|
||||||
public static void updateDisplayName(GradientModule module, Player player, GradientPlayerData data) {
|
public static void updateDisplayName(GradientModule module, Player player, GradientPlayerData data) {
|
||||||
GradientConfig cfg = module.getConfig();
|
GradientConfig cfg = module.getConfig();
|
||||||
|
|
||||||
|
// Если включен TextDisplay, используем его вместо обычного display name
|
||||||
|
if (cfg.isUseTextDisplay()) {
|
||||||
|
module.getTextDisplayManager().updatePlayerDisplay(player);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
String prefix = null;
|
String prefix = null;
|
||||||
String prefixFormat = cfg.getPrefixFormat();
|
String prefixFormat = cfg.getPrefixFormat();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,242 @@
|
||||||
|
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();
|
||||||
|
|
||||||
|
// Создаем новый 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(true); // Видно через стены
|
||||||
|
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) // Без поворота после масштабирования
|
||||||
|
));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Привязываем 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 prefix = null;
|
||||||
|
String prefixFormat = module.getConfig().getPrefixFormat();
|
||||||
|
|
||||||
|
// Определяем префикс: сначала кастомный, потом LuckPerms
|
||||||
|
if (data.isPrefixEnabled() && data.hasPrefix()) {
|
||||||
|
prefix = data.getPrefix();
|
||||||
|
} else if (module.getLuckPermsHook().isEnabled()) {
|
||||||
|
String lpPrefix = module.getLuckPermsHook().getActivePrefix(player);
|
||||||
|
if (lpPrefix != null && !lpPrefix.isEmpty()) {
|
||||||
|
// Для LuckPerms префикса используем специальную логику
|
||||||
|
return buildWithLuckPermsPrefix(
|
||||||
|
lpPrefix,
|
||||||
|
player.getName(),
|
||||||
|
data.isColorEnabled() ? data.getColors() : null,
|
||||||
|
module.getConfig().isUseLegacyRgbFormat(),
|
||||||
|
module.getConfig().isContinuousGradient()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Строим display text с кастомным префиксом или без префикса
|
||||||
|
String displayText = GradientUtil.buildDisplayName(
|
||||||
|
prefix,
|
||||||
|
player.getName(),
|
||||||
|
data.isColorEnabled() ? data.getColors() : null,
|
||||||
|
module.getConfig().isGradientOnPrefix(),
|
||||||
|
module.getConfig().isContinuousGradient(),
|
||||||
|
prefixFormat,
|
||||||
|
false // Используем MiniMessage формат для TextDisplay
|
||||||
|
);
|
||||||
|
|
||||||
|
// Конвертируем &#RRGGBB в <#RRGGBB> для MiniMessage
|
||||||
|
return convertToMiniMessageFormat(displayText);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Строит текст с LuckPerms префиксом
|
||||||
|
*/
|
||||||
|
private String buildWithLuckPermsPrefix(String lpPrefix, String nick,
|
||||||
|
java.util.List<String> colors,
|
||||||
|
boolean useLegacyFormat,
|
||||||
|
boolean continuousGradient) {
|
||||||
|
if (colors == null || colors.isEmpty()) {
|
||||||
|
return convertToMiniMessageFormat(lpPrefix + nick);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (continuousGradient) {
|
||||||
|
String cleanPrefix = stripColors(lpPrefix);
|
||||||
|
String fullText = cleanPrefix + nick;
|
||||||
|
String result = GradientUtil.applyGradient(fullText, colors, false); // MiniMessage формат
|
||||||
|
return convertToMiniMessageFormat(result);
|
||||||
|
} else {
|
||||||
|
String result = convertToMiniMessageFormat(lpPrefix) +
|
||||||
|
convertToMiniMessageFormat(GradientUtil.applyGradient(nick, colors, false));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Убирает цветовые коды из строки
|
||||||
|
*/
|
||||||
|
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}|<[^>]+>)", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Конвертирует &#RRGGBB в <#RRGGBB> для MiniMessage
|
||||||
|
*/
|
||||||
|
private String convertToMiniMessageFormat(String text) {
|
||||||
|
if (text == null) return "";
|
||||||
|
// Конвертируем &#RRGGBB в <#RRGGBB>
|
||||||
|
text = text.replaceAll("&#([0-9a-fA-F]{6})", "<#$1>");
|
||||||
|
// Конвертируем §x§R§R§G§G§B§B в <#RRGGBB> (используем Pattern и Matcher)
|
||||||
|
java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("§x(§[0-9a-fA-F]){6}");
|
||||||
|
java.util.regex.Matcher matcher = pattern.matcher(text);
|
||||||
|
StringBuffer sb = new StringBuffer();
|
||||||
|
while (matcher.find()) {
|
||||||
|
String hex = matcher.group().replaceAll("§", "").substring(1); // Убираем все § и x
|
||||||
|
matcher.appendReplacement(sb, "<#" + hex + ">");
|
||||||
|
}
|
||||||
|
matcher.appendTail(sb);
|
||||||
|
text = sb.toString();
|
||||||
|
|
||||||
|
// Конвертируем обычные цветовые коды §a в <green> и т.д.
|
||||||
|
text = text.replaceAll("§([0-9a-fk-or])", "<$1>");
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Удаляет 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -49,6 +49,12 @@ display:
|
||||||
update-display-name: true
|
update-display-name: true
|
||||||
# Обновлять tab list
|
# Обновлять tab list
|
||||||
update-tab-list: true
|
update-tab-list: true
|
||||||
|
# Использовать TextDisplay вместо обычного display name (1.19.4+)
|
||||||
|
use-text-display: true
|
||||||
|
# Высота TextDisplay над игроком (в блоках)
|
||||||
|
text-display-height: 2.3
|
||||||
|
# Размер TextDisplay (от 0.1 до 2.0)
|
||||||
|
text-display-scale: 0.8
|
||||||
|
|
||||||
# Тип хранилища: YAML или SQLITE
|
# Тип хранилища: YAML или SQLITE
|
||||||
storage-type: YAML
|
storage-type: YAML
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue