Initial commit: LoChat v1.0.0 with Gradient module
This commit is contained in:
commit
252b0a60db
86 changed files with 8922 additions and 0 deletions
118
src/main/java/com/loki/lochat/gradient/util/DisplayNameUtil.java
Normal file
118
src/main/java/com/loki/lochat/gradient/util/DisplayNameUtil.java
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
package com.loki.lochat.gradient.util;
|
||||
|
||||
import com.loki.lochat.gradient.GradientModule;
|
||||
import com.loki.lochat.gradient.config.GradientConfig;
|
||||
import com.loki.lochat.gradient.data.GradientPlayerData;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Утилита для обновления отображаемого имени игрока
|
||||
*/
|
||||
public final class DisplayNameUtil {
|
||||
|
||||
private static final LegacyComponentSerializer SERIALIZER = LegacyComponentSerializer.builder()
|
||||
.character('&')
|
||||
.hexCharacter('#')
|
||||
.hexColors()
|
||||
.build();
|
||||
|
||||
private DisplayNameUtil() {}
|
||||
|
||||
public static void updateDisplayName(GradientModule module, Player player, GradientPlayerData data) {
|
||||
GradientConfig cfg = module.getConfig();
|
||||
|
||||
String prefix = null;
|
||||
String prefixFormat = cfg.getPrefixFormat();
|
||||
|
||||
if (data.isPrefixEnabled() && data.hasPrefix()) {
|
||||
prefix = data.getPrefix();
|
||||
} else {
|
||||
String lpPrefix = module.getLuckPermsHook().getActivePrefix(player);
|
||||
if (lpPrefix != null && !lpPrefix.isEmpty()) {
|
||||
String displayName = buildWithLuckPermsPrefix(
|
||||
lpPrefix,
|
||||
player.getName(),
|
||||
data.isColorEnabled() ? data.getColors() : null,
|
||||
cfg.isUseLegacyRgbFormat(),
|
||||
cfg.isContinuousGradient()
|
||||
);
|
||||
var component = SERIALIZER.deserialize(displayName);
|
||||
player.displayName(component);
|
||||
player.playerListName(component);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
String displayName = GradientUtil.buildDisplayName(
|
||||
prefix,
|
||||
player.getName(),
|
||||
data.isColorEnabled() ? data.getColors() : null,
|
||||
cfg.isGradientOnPrefix(),
|
||||
cfg.isContinuousGradient(),
|
||||
prefixFormat,
|
||||
cfg.isUseLegacyRgbFormat()
|
||||
);
|
||||
var component = SERIALIZER.deserialize(displayName);
|
||||
player.displayName(component);
|
||||
player.playerListName(component);
|
||||
}
|
||||
|
||||
private static String buildWithLuckPermsPrefix(String lpPrefix, String nick,
|
||||
List<String> colors,
|
||||
boolean useLegacyFormat,
|
||||
boolean continuousGradient) {
|
||||
if (colors == null || colors.isEmpty()) {
|
||||
return lpPrefix + nick;
|
||||
}
|
||||
|
||||
if (continuousGradient) {
|
||||
String cleanPrefix = stripColors(lpPrefix);
|
||||
String fullText = cleanPrefix + nick;
|
||||
return GradientUtil.applyGradient(fullText, colors, useLegacyFormat);
|
||||
} else {
|
||||
return lpPrefix + GradientUtil.applyGradient(nick, colors, useLegacyFormat);
|
||||
}
|
||||
}
|
||||
|
||||
private static String stripColors(String text) {
|
||||
if (text == null) return null;
|
||||
return text.replaceAll("(?i)(§x(§[0-9a-f]){6}|§[0-9a-fk-or]|&[0-9a-fk-or]|&#[0-9a-f]{6})", "");
|
||||
}
|
||||
|
||||
public static String buildColoredPrefix(GradientModule module, GradientPlayerData data) {
|
||||
if (!data.hasPrefix() || !data.isPrefixEnabled()) return null;
|
||||
|
||||
GradientConfig cfg = module.getConfig();
|
||||
String prefix = cfg.getPrefixFormat().replace("{prefix}", data.getPrefix()).stripTrailing();
|
||||
|
||||
return (data.hasColors() && data.isColorEnabled() && cfg.isGradientOnPrefix())
|
||||
? GradientUtil.applyGradient(prefix, data.getColors(), cfg.isUseLegacyRgbFormat())
|
||||
: prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получает полное отображаемое имя игрока с градиентом
|
||||
*/
|
||||
public static String getFullDisplayName(GradientModule module, Player player) {
|
||||
GradientPlayerData data = module.getDataManager().getPlayerData(player.getUniqueId());
|
||||
GradientConfig cfg = module.getConfig();
|
||||
|
||||
String prefix = null;
|
||||
if (data.isPrefixEnabled() && data.hasPrefix()) {
|
||||
prefix = data.getPrefix();
|
||||
}
|
||||
|
||||
return GradientUtil.buildDisplayName(
|
||||
prefix,
|
||||
player.getName(),
|
||||
data.isColorEnabled() ? data.getColors() : null,
|
||||
cfg.isGradientOnPrefix(),
|
||||
cfg.isContinuousGradient(),
|
||||
cfg.getPrefixFormat(),
|
||||
cfg.isUseLegacyRgbFormat()
|
||||
);
|
||||
}
|
||||
}
|
||||
74
src/main/java/com/loki/lochat/gradient/util/FoliaUtil.java
Normal file
74
src/main/java/com/loki/lochat/gradient/util/FoliaUtil.java
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
package com.loki.lochat.gradient.util;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Утилита для работы с Folia
|
||||
*/
|
||||
public final class FoliaUtil {
|
||||
|
||||
private static final boolean IS_FOLIA;
|
||||
|
||||
static {
|
||||
IS_FOLIA = checkFolia();
|
||||
}
|
||||
|
||||
private FoliaUtil() {}
|
||||
|
||||
private static boolean checkFolia() {
|
||||
try {
|
||||
Class.forName("io.papermc.paper.threadedregions.RegionizedServer");
|
||||
return true;
|
||||
} catch (ClassNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isFolia() {
|
||||
return IS_FOLIA;
|
||||
}
|
||||
|
||||
public static void runEntityTask(Plugin plugin, Entity entity, Runnable task) {
|
||||
if (IS_FOLIA) {
|
||||
entity.getScheduler().run(plugin, scheduledTask -> task.run(), null);
|
||||
} else {
|
||||
Bukkit.getScheduler().runTask(plugin, task);
|
||||
}
|
||||
}
|
||||
|
||||
public static void runEntityTaskLater(Plugin plugin, Entity entity, Runnable task, long delayTicks) {
|
||||
if (IS_FOLIA) {
|
||||
entity.getScheduler().runDelayed(plugin, scheduledTask -> task.run(), null, delayTicks);
|
||||
} else {
|
||||
Bukkit.getScheduler().runTaskLater(plugin, task, delayTicks);
|
||||
}
|
||||
}
|
||||
|
||||
public static void runAsync(Plugin plugin, Runnable task) {
|
||||
if (IS_FOLIA) {
|
||||
Bukkit.getAsyncScheduler().runNow(plugin, scheduledTask -> task.run());
|
||||
} else {
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, task);
|
||||
}
|
||||
}
|
||||
|
||||
public static void runAsyncLater(Plugin plugin, Runnable task, long delayMs) {
|
||||
if (IS_FOLIA) {
|
||||
Bukkit.getAsyncScheduler().runDelayed(plugin, scheduledTask -> task.run(), delayMs, TimeUnit.MILLISECONDS);
|
||||
} else {
|
||||
Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, task, delayMs / 50);
|
||||
}
|
||||
}
|
||||
|
||||
public static void runGlobalTask(Plugin plugin, Runnable task) {
|
||||
if (IS_FOLIA) {
|
||||
Bukkit.getGlobalRegionScheduler().run(plugin, scheduledTask -> task.run());
|
||||
} else {
|
||||
Bukkit.getScheduler().runTask(plugin, task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package com.loki.lochat.gradient.util;
|
||||
|
||||
/**
|
||||
* Константы для градиентного модуля
|
||||
*/
|
||||
public final class GradientConstants {
|
||||
|
||||
private GradientConstants() {}
|
||||
|
||||
public static final long MILLIS_PER_SECOND = 1000L;
|
||||
|
||||
// GUI слоты
|
||||
public static final int GUI_CONFIRM_SLOT = 11;
|
||||
public static final int GUI_CANCEL_SLOT = 15;
|
||||
public static final int GUI_PREVIEW_SLOT = 13;
|
||||
|
||||
// LuckPerms
|
||||
public static final int LUCKPERMS_PREFIX_PRIORITY = 100;
|
||||
}
|
||||
123
src/main/java/com/loki/lochat/gradient/util/GradientUtil.java
Normal file
123
src/main/java/com/loki/lochat/gradient/util/GradientUtil.java
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
package com.loki.lochat.gradient.util;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Утилита для работы с градиентами
|
||||
*/
|
||||
public final class GradientUtil {
|
||||
|
||||
private static final Pattern HEX_PATTERN = Pattern.compile("^#[0-9A-Fa-f]{6}$");
|
||||
|
||||
private GradientUtil() {}
|
||||
|
||||
public static boolean isValidHex(String color) {
|
||||
return HEX_PATTERN.matcher(color).matches();
|
||||
}
|
||||
|
||||
public static String applyGradient(String text, List<String> hexColors, boolean useLegacyFormat) {
|
||||
if (text == null || text.isEmpty() || hexColors == null || hexColors.isEmpty()) {
|
||||
return text;
|
||||
}
|
||||
|
||||
char[] chars = text.toCharArray();
|
||||
int length = chars.length;
|
||||
if (length == 0) return text;
|
||||
|
||||
StringBuilder result = new StringBuilder();
|
||||
|
||||
if (hexColors.size() == 1) {
|
||||
String colorCode = formatHex(hexColors.get(0), useLegacyFormat);
|
||||
for (char c : chars) {
|
||||
result.append(colorCode).append(c);
|
||||
}
|
||||
} else {
|
||||
Color[] colors = hexColors.stream()
|
||||
.map(GradientUtil::parseHex)
|
||||
.toArray(Color[]::new);
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
Color interpolated = interpolateMultiColor(colors, (double) i / Math.max(1, length - 1));
|
||||
String hex = String.format("#%02x%02x%02x",
|
||||
interpolated.getRed(), interpolated.getGreen(), interpolated.getBlue());
|
||||
result.append(formatHex(hex, useLegacyFormat)).append(chars[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private static Color interpolateMultiColor(Color[] colors, double ratio) {
|
||||
if (colors.length == 1) return colors[0];
|
||||
if (ratio <= 0) return colors[0];
|
||||
if (ratio >= 1) return colors[colors.length - 1];
|
||||
|
||||
double scaledRatio = ratio * (colors.length - 1);
|
||||
int index = (int) scaledRatio;
|
||||
double localRatio = scaledRatio - index;
|
||||
|
||||
if (index >= colors.length - 1) {
|
||||
return colors[colors.length - 1];
|
||||
}
|
||||
|
||||
return interpolate(colors[index], colors[index + 1], localRatio);
|
||||
}
|
||||
|
||||
private static Color interpolate(Color c1, Color c2, double ratio) {
|
||||
int r = (int) (c1.getRed() + (c2.getRed() - c1.getRed()) * ratio);
|
||||
int g = (int) (c1.getGreen() + (c2.getGreen() - c1.getGreen()) * ratio);
|
||||
int b = (int) (c1.getBlue() + (c2.getBlue() - c1.getBlue()) * ratio);
|
||||
return new Color(
|
||||
Math.max(0, Math.min(255, r)),
|
||||
Math.max(0, Math.min(255, g)),
|
||||
Math.max(0, Math.min(255, b))
|
||||
);
|
||||
}
|
||||
|
||||
private static Color parseHex(String hex) {
|
||||
hex = hex.replace("#", "");
|
||||
return new Color(
|
||||
Integer.parseInt(hex.substring(0, 2), 16),
|
||||
Integer.parseInt(hex.substring(2, 4), 16),
|
||||
Integer.parseInt(hex.substring(4, 6), 16)
|
||||
);
|
||||
}
|
||||
|
||||
private static String formatHex(String hex, boolean useLegacyFormat) {
|
||||
hex = hex.replace("#", "").toLowerCase();
|
||||
if (useLegacyFormat) {
|
||||
return "&#" + hex;
|
||||
} else {
|
||||
return "<#" + hex + ">";
|
||||
}
|
||||
}
|
||||
|
||||
public static String buildDisplayName(String prefix, String nick, List<String> colors,
|
||||
boolean gradientOnPrefix, boolean continuousGradient,
|
||||
String prefixFormat, boolean useLegacyFormat) {
|
||||
if (colors == null || colors.isEmpty()) {
|
||||
if (prefix != null && !prefix.isEmpty()) {
|
||||
return prefixFormat.replace("{prefix}", prefix) + nick;
|
||||
}
|
||||
return nick;
|
||||
}
|
||||
|
||||
if (prefix == null || prefix.isEmpty()) {
|
||||
return applyGradient(nick, colors, useLegacyFormat);
|
||||
}
|
||||
|
||||
if (continuousGradient && gradientOnPrefix) {
|
||||
String fullText = prefixFormat.replace("{prefix}", prefix) + nick;
|
||||
return applyGradient(fullText, colors, useLegacyFormat);
|
||||
} else if (gradientOnPrefix) {
|
||||
String coloredPrefix = applyGradient(prefixFormat.replace("{prefix}", prefix), colors, useLegacyFormat);
|
||||
String coloredNick = applyGradient(nick, colors, useLegacyFormat);
|
||||
return coloredPrefix + coloredNick;
|
||||
} else {
|
||||
String formattedPrefix = prefixFormat.replace("{prefix}", prefix);
|
||||
return formattedPrefix + applyGradient(nick, colors, useLegacyFormat);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue