Compare commits

...
29 Commits
Author SHA1 Message Date
NEZNAMY 4c3bd66209 Update README.md 2024-10-11 20:27:07 +02:00
NEZNAMY 0827d083bf 4.1.9 2024-10-11 19:56:06 +02:00
NEZNAMY 2f7b42ab85 [Bukkit] Fix NPE caused by another plugin making a not-null field null (#1368) 2024-10-07 19:20:14 +02:00
NEZNAMY 735aa666d6 I just love Velocity 2024-10-06 18:21:54 +02:00
NEZNAMY c2ceb643e5 [Bukkit] Bump dependency 2024-10-03 18:22:18 +02:00
NEZNAMY 5c166f647f [Velocity] Fix exploit (not specifying more to keep users safe) 2024-10-02 20:48:10 +02:00
NEZNAMY 03a8fb9aa2 4.1.9-SNAPSHOT 2024-08-30 19:11:38 +02:00
NEZNAMY 1a44c97d5a 4.1.8 2024-08-30 18:57:45 +02:00
NEZNAMY 29cf0a26d6 4.1.8-SNAPSHOT 2024-08-25 20:11:13 +02:00
NEZNAMY 33d172598d [BungeeCord] Avoid sending UPDATE_LIST_ORDER tablist action to <1.21.2 players (#1359) 2024-08-25 20:10:53 +02:00
NEZNAMY af1e685c2b Merge pull request #1357 from hans362/fix-get-skin
Get skin from profile properties by property name
2024-08-20 16:01:48 +02:00
hans362 09129974db Get skin from profile properties by property name 2024-08-20 21:26:08 +08:00
NEZNAMY 0efb69fb4b [Fabric] Add 1.21.1 to supported versions 2024-08-10 09:46:22 +02:00
NEZNAMY 5cbec52ea3 4.1.7 2024-08-10 09:38:23 +02:00
NEZNAMY 8db9e64121 Update to 1.21.1 2024-08-10 09:37:20 +02:00
NEZNAMY 05009b17f0 [Layout] Fix API usage causing placeholders to not refresh (#1347) 2024-08-06 17:57:41 +02:00
NEZNAMY 032af707dd [Sorting] Fix sorting placeholder using old instance when a placeholder is overridden 2024-07-25 20:52:33 +02:00
NEZNAMY cf227a97f3 [BungeeCord] Add try/catch for yet another NPE in BungeeCord code (#1338) 2024-07-25 15:56:21 +02:00
NEZNAMY 1a2075dfe2 [Bukkit] Fix compatibility with random modded server 2024-07-22 19:26:57 +02:00
NEZNAMY 1de7665309 [Bug fix] Colors not displaying correctly in Fabric and Velocity console (#1298) 2024-06-26 14:25:05 +02:00
NEZNAMY 9473037127 Merge pull request #1323 from sunmisc/master
represent getOnlinePlayers as a collection
2024-06-22 23:37:47 +02:00
sunmisc dcb234dc08 stream api to collection 2024-06-23 00:35:16 +03:00
sunmisc 79eb34fc32 Revert "stream api to collection"
This reverts commit 40544ef5d3.
2024-06-23 00:31:38 +03:00
sunmisc 40544ef5d3 stream api to collection 2024-06-23 00:19:33 +03:00
sunmisc 14dfa0154a Stream api for getOnlinePlayers 2024-06-22 23:44:51 +03:00
NEZNAMY 7df2aba2d1 [RedisBungee] Override %serveronline% to count redis players as well (#1316) 2024-06-16 20:10:25 +02:00
NEZNAMY 9edf3176ea [MiniMessage] Add dummy character to parsed text to disable color compacting (#1312) 2024-06-16 09:16:57 +02:00
NEZNAMY ec73aa13b4 4.1.7-SNAPSHOT 2024-06-16 09:16:48 +02:00
NEZNAMY 6f002cd61b Change action builds to only upload from v5 branch 2024-06-13 21:11:12 +02:00
41 changed files with 190 additions and 155 deletions

No files matched your search

+1 -1
View File
@@ -2,7 +2,7 @@ name: Build
on:
push:
branches:
- master
- v5
jobs:
build:
name: Build
+2 -58
View File
@@ -1,58 +1,2 @@
# About
TAB aims to be a superior all-in-one minecraft plugin for displaying information that outperforms all
similar plugins in terms of features, performance and compatibility.
More information can be found at [Why TAB?](https://github.com/NEZNAMY/TAB/wiki/Why-TAB%3F) wiki page.
# Download
### Releases
You can download full releases from [GitHub releases](https://github.com/NEZNAMY/TAB/releases),
[SpigotMC](https://www.spigotmc.org/resources/57806/), [Modrinth](https://modrinth.com/plugin/tab-was-taken) or [BuiltByBit](https://builtbybit.com/resources/20631).
### Dev builds
Plugin's development is continuous and contains lots of small changes/fixes not worthy of being called a full
update, therefore development builds are being created and eventually a full update is released when enough changes are made.
If you want to benefit from a recent change in the code before official release, you can download development builds
from [GitHub actions](https://github.com/NEZNAMY/TAB/actions) (you must be logged into GitHub to be able to download it).
# Compiling
Compilation requires JDK 21 and up.
To compile the plugin, run `./gradlew build` from the terminal.
Once the plugin compiles, grab the jar from `/jar/build/libs/` folder.
The universal jar contains all modules for all supported platforms.
# Documentation
You can find everything about the plugin on the [Wiki](https://github.com/NEZNAMY/TAB/wiki). This includes a detailed description
of all features, as well as information regarding compatibility or limitations of each feature.
# Issues
The [Issues](https://github.com/NEZNAMY/TAB/issues) section is an issue tracker for all the kind of problems covered in issue templates.
Please refrain from attempting to use it to receive help with your server, such issues will be closed immediately.
When opening an issue, provide as much information as possible. The difference between a bug getting fixed in 1 week vs 1 hour
is in quality of the report. Bug reports where steps to reproduce are "idk" have no value and will not help to get the bug fixed at all.
# Contributing
See [CONTRIBUTING.md](https://github.com/NEZNAMY/TAB/blob/master/CONTRIBUTING.md)
# Provided services
The plugin is being used by a large amount of servers, which also means the demand for my attention is high. Unfortunately,
I am no longer able to keep up with the demand since I don't want to dedicate my whole existence to a free plugin.
In order to provide the best quality of all provided services, the amount of services provided may vary over time.
Here is the full list of potential services and their status:
| Service type | Availability |
|-------------------------------|--------------|
| Updates for new MC versions | ✔ |
| Bug fixes | ✔ |
| Wiki updates<sup>1</sup> | ✔ |
| Feature requests | ❌ |
| Customer support<sup>2</sup> | ✔ |
| Free user support<sup>3</sup> | ❌* |
| Optimization<sup>4</sup> | ✔ |
<sup>1</sup> - Adding new examples, guides and other kind of useful information people ask about.
<sup>2</sup> - Unrestricted assistance with the plugin for those, who bought a copy of the plugin when it was purchasable.
<sup>3</sup> - Unlimited access to my free time for everyone in the world.
<sup>4</sup> - Improving plugin's performance while not losing out on any features. This was done
proactively a lot in the past, so there isn't much to do anymore, only if someone actually finds and reports something.
*Instead, you can use [this fresh new community discord](https://discord.gg/YPqXt63YQj) made by a nice person who will provide this service.
# Warning
This branch is abandoned and NO support will be provided. It is an archived source code of the latest release with unlimited nametags and 1.8 bossbars (4.1.9) for MC 1.5 - 1.21.1.
@@ -1,5 +1,6 @@
package me.neznamy.tab.api;
import java.util.Collection;
import java.util.UUID;
import lombok.NonNull;
@@ -67,8 +68,17 @@ public abstract class TabAPI {
*
* @return collection of online players
*/
@Deprecated
public abstract @NotNull TabPlayer[] getOnlinePlayers();
/**
* Returns a stream of all online players
*
* @return stream of online players
*/
public abstract @NotNull Collection<? extends TabPlayer> onlinePlayers();
/**
* Return BossBar manager instance if the feature is enabled. If not, returns {@code null}.
*
+1 -1
View File
@@ -4,7 +4,7 @@ plugins {
allprojects {
group = "me.neznamy"
version = "4.1.6"
version = "4.1.9"
description = "An all-in-one solution that works"
ext.set("id", "tab")
+1 -1
View File
@@ -2,7 +2,7 @@ dependencies {
implementation(projects.shared)
implementation("org.bstats:bstats-bukkit:3.0.1")
compileOnly("org.purpurmc.purpur:purpur-api:1.16.5-R0.1-SNAPSHOT")
compileOnly("me.clip:placeholderapi:2.11.2")
compileOnly("me.clip:placeholderapi:2.11.6")
compileOnly("com.mojang:authlib:1.5.25")
compileOnly("com.github.MilkBowl:VaultAPI:1.7") {
exclude("org.bukkit", "bukkit")
@@ -71,7 +71,7 @@ public class ComponentConverter {
Class<?> chatClickable = BukkitReflection.getClass("network.chat.ClickEvent", "network.chat.ChatClickable", "ChatClickable");
Class<?> chatHoverable = BukkitReflection.getClass("network.chat.HoverEvent", "network.chat.ChatHoverable", "ChatHoverable");
ResourceLocation_tryParse = ReflectionUtils.getMethod(ResourceLocation, new String[]{"tryParse", "m_135820_", "a"}, String.class);
ChatHexColor_fromRGB = ReflectionUtils.getOnlyMethod(chatHexColor, chatHexColor, int.class);
ChatHexColor_fromRGB = ReflectionUtils.getMethods(chatHexColor, chatHexColor, int.class).get(0); // There should only be 1, but some mods add more
newChatModifier = ReflectionUtils.setAccessible(ChatModifier.getDeclaredConstructor(chatHexColor, Boolean.class, Boolean.class, Boolean.class,
Boolean.class, Boolean.class, chatClickable, chatHoverable, String.class, ResourceLocation));
convertModifier = this::createModifierModern;
@@ -16,6 +16,7 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
@@ -309,7 +310,8 @@ public class TeamPacketData {
if (!TeamPacketClass.isInstance(packet)) return;
int action = TeamPacket_ACTION.getInt(packet);
if (action == TeamAction.UPDATE) return;
TeamPacket_PLAYERS.set(packet, player.getScoreboard().onTeamPacket(
action, (String) TeamPacket_NAME.get(packet), (Collection<String>) TeamPacket_PLAYERS.get(packet)));
Collection<String> players = (Collection<String>) TeamPacket_PLAYERS.get(packet);
if (players == null) players = Collections.emptyList();
TeamPacket_PLAYERS.set(packet, player.getScoreboard().onTeamPacket(action, (String) TeamPacket_NAME.get(packet), players));
}
}
@@ -71,7 +71,20 @@ public class BungeeTabPlayer extends ProxyTabPlayer {
@Override
public void sendMessage(@NotNull TabComponent message) {
getPlayer().sendMessage((BaseComponent) message.convert(getVersion()));
try {
getPlayer().sendMessage((BaseComponent) message.convert(getVersion()));
} catch (NullPointerException BungeeCordBug) {
// java.lang.NullPointerException: Cannot invoke "net.md_5.bungee.protocol.MinecraftEncoder.getProtocol()" because the return value of "io.netty.channel.ChannelPipeline.get(java.lang.Class)" is null
// at net.md_5.bungee.netty.ChannelWrapper.getEncodeProtocol(ChannelWrapper.java:51)
// at net.md_5.bungee.UserConnection.sendPacketQueued(UserConnection.java:198)
// at net.md_5.bungee.UserConnection.sendMessage(UserConnection.java:565)
// at net.md_5.bungee.UserConnection.sendMessage(UserConnection.java:520)
// at net.md_5.bungee.UserConnection.sendMessage(UserConnection.java:508)
if (TAB.getInstance().getConfiguration().isDebugMode()) {
TAB.getInstance().getErrorManager().printError("Failed to send message to player " + getName() +
" (online = " + getPlayer().isConnected() + "): " + message.convert(getVersion()), BungeeCordBug);
}
}
}
@Override
@@ -80,8 +93,13 @@ public class BungeeTabPlayer extends ProxyTabPlayer {
LoginResult loginResult = ((InitialHandler)getPlayer().getPendingConnection()).getLoginProfile();
if (loginResult == null) return null;
Property[] properties = loginResult.getProperties();
if (properties == null || properties.length == 0) return null; //Offline mode
return new TabList.Skin(properties[0].getValue(), properties[0].getSignature());
if (properties == null) return null; //Offline mode
for (Property property : properties) {
if (property.getName().equals(TabList.TEXTURES_PROPERTY)) {
return new TabList.Skin(property.getValue(), property.getSignature());
}
}
return null;
}
@Override
@@ -20,7 +20,15 @@ public class BungeeTabList1193 extends BungeeTabList {
private static final Map<Action, EnumSet<PlayerListItemUpdate.Action>> actions = new EnumMap<>(Action.class);
static {
actions.put(Action.ADD_PLAYER, EnumSet.allOf(PlayerListItemUpdate.Action.class));
// Do not use allOf because <1.21.2 does not support UPDATE_LIST_ORDER
// TODO Once bungeecord dependency is updated, support it properly
actions.put(Action.ADD_PLAYER, EnumSet.of(
PlayerListItemUpdate.Action.ADD_PLAYER,
PlayerListItemUpdate.Action.UPDATE_GAMEMODE,
PlayerListItemUpdate.Action.UPDATE_LISTED,
PlayerListItemUpdate.Action.UPDATE_LATENCY,
PlayerListItemUpdate.Action.UPDATE_DISPLAY_NAME
));
actions.put(Action.UPDATE_GAME_MODE, EnumSet.of(PlayerListItemUpdate.Action.UPDATE_GAMEMODE));
actions.put(Action.UPDATE_DISPLAY_NAME, EnumSet.of(PlayerListItemUpdate.Action.UPDATE_DISPLAY_NAME));
actions.put(Action.UPDATE_LATENCY, EnumSet.of(PlayerListItemUpdate.Action.UPDATE_LATENCY));
+1 -1
View File
@@ -12,7 +12,7 @@ repositories {
dependencies {
api(projects.shared)
minecraft("com.mojang:minecraft:1.21")
minecraft("com.mojang:minecraft:1.21.1")
mappings(loom.officialMojangMappings())
modImplementation("me.lucko:fabric-permissions-api:0.2-SNAPSHOT")
modImplementation("net.fabricmc:fabric-loader:0.15.9")
@@ -4,7 +4,7 @@ import com.mojang.authlib.properties.Property;
import io.netty.channel.Channel;
import lombok.SneakyThrows;
import me.neznamy.tab.platforms.fabric.loader.Loader;
import me.neznamy.tab.platforms.fabric.loader.Loader_1_21;
import me.neznamy.tab.platforms.fabric.loader.Loader_1_21_1;
import me.neznamy.tab.shared.ProtocolVersion;
import me.neznamy.tab.shared.backend.EntityData;
import me.neznamy.tab.shared.backend.Location;
@@ -38,7 +38,7 @@ public class FabricMultiVersion {
private static final ProtocolVersion serverVersion = ProtocolVersion.fromFriendlyName(FabricTAB.minecraftVersion);
/** Method loader using latest supported MC version */
private static final Loader loaderNew = new Loader_1_21();
private static final Loader loaderNew = new Loader_1_21_1();
/** Method loader using 1.18.2 */
private static final Loader loader1_18_2 = createLoader("1_18_2");
@@ -42,14 +42,13 @@ import org.jetbrains.annotations.Nullable;
import java.util.*;
/**
* Method loader compiled using Minecraft 1.21.
* Method loader compiled using Minecraft 1.21.1.
*/
@SuppressWarnings({
"unchecked", // Java generic types
"DataFlowIssue", // Profile is not null on add action
"unused" // Actually used, just via reflection
"DataFlowIssue" // Profile is not null on add action
})
public class Loader_1_21 implements Loader {
public class Loader_1_21_1 implements Loader {
@Override
@NotNull
@@ -320,12 +319,12 @@ public class Loader_1_21 implements Loader {
@Override
public void logInfo(@NotNull TabComponent message) {
MinecraftServer.LOGGER.info("[TAB] " + message.toLegacyText());
MinecraftServer.LOGGER.info("[TAB] " + message.toRawText());
}
@Override
public void logWarn(@NotNull TabComponent message) {
MinecraftServer.LOGGER.warn("[TAB] " + message.toLegacyText());
MinecraftServer.LOGGER.warn("[TAB] " + message.toRawText());
}
/**
@@ -361,10 +360,6 @@ public class Loader_1_21 implements Loader {
static final Map<TabList.Action, EnumSet<ClientboundPlayerInfoUpdatePacket.Action>> actionMap = createActionMap();
public static EnumSet<ClientboundPlayerInfoUpdatePacket.Action> convertAction(TabList.Action action) {
return EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.valueOf(action.name()));
}
private static Map<TabList.Action, EnumSet<ClientboundPlayerInfoUpdatePacket.Action>> createActionMap() {
Map<TabList.Action, EnumSet<ClientboundPlayerInfoUpdatePacket.Action>> actions = new EnumMap<>(TabList.Action.class);
actions.put(TabList.Action.ADD_PLAYER, EnumSet.allOf(ClientboundPlayerInfoUpdatePacket.Action.class));
+1 -1
View File
@@ -20,7 +20,7 @@
"1.18", "1.18.1", "1.18.2",
"1.19", "1.19.1", "1.19.2", "1.19.3", "1.19.4",
"1.20", "1.20.1", "1.20.2", "1.20.3", "1.20.4", "1.20.5", "1.20.6",
"1.21"
"1.21", "1.21.1"
]
},
"recommends": {
@@ -319,13 +319,13 @@ public class Loader_1_14_4 implements Loader {
@SneakyThrows
public void logInfo(@NotNull TabComponent message) {
Object logger = ReflectionUtils.getFields(MinecraftServer.class, Class.forName("org.apache.logging.log4j.Logger")).get(0).get(null);
logger.getClass().getMethod("info", String.class).invoke(logger, "[TAB] " + message.toLegacyText());
logger.getClass().getMethod("info", String.class).invoke(logger, "[TAB] " + message.toRawText());
}
@Override
@SneakyThrows
public void logWarn(@NotNull TabComponent message) {
Object logger = ReflectionUtils.getFields(MinecraftServer.class, Class.forName("org.apache.logging.log4j.Logger")).get(0).get(null);
logger.getClass().getMethod("warn", String.class).invoke(logger, "[TAB] " + message.toLegacyText());
logger.getClass().getMethod("warn", String.class).invoke(logger, "[TAB] " + message.toRawText());
}
}
@@ -3,7 +3,7 @@ package me.neznamy.tab.shared;
import lombok.Getter;
import me.neznamy.tab.api.event.TabEvent;
import me.neznamy.tab.shared.chat.EnumChatFormat;
import me.neznamy.tab.shared.chat.SimpleComponent;
import me.neznamy.tab.shared.chat.TabComponent;
import me.neznamy.tab.shared.platform.TabPlayer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -118,13 +118,13 @@ public class ErrorManager {
if (file.length() < TabConstants.MAX_LOG_SIZE)
buf.write(dateFormat.format(new Date()) + "[TAB v" + TabConstants.PLUGIN_VERSION + "] " + EnumChatFormat.decolor(message) + System.lineSeparator());
if (intoConsoleToo || TAB.getInstance().getConfiguration().isDebugMode())
TAB.getInstance().getPlatform().logWarn(new SimpleComponent(message));
TAB.getInstance().getPlatform().logWarn(TabComponent.fromColoredText(message));
}
for (String line : error) {
if (file.length() < TabConstants.MAX_LOG_SIZE)
buf.write(dateFormat.format(new Date()) + line + System.lineSeparator());
if (intoConsoleToo || TAB.getInstance().getConfiguration().isDebugMode())
TAB.getInstance().getPlatform().logWarn(new SimpleComponent(line));
TAB.getInstance().getPlatform().logWarn(TabComponent.fromColoredText(line));
}
}
} catch (IOException ex) {
@@ -134,7 +134,7 @@ public class ErrorManager {
lines.add("Original error: " + message);
lines.addAll(error);
for (String line : lines) {
TAB.getInstance().getPlatform().logWarn(new SimpleComponent(line));
TAB.getInstance().getPlatform().logWarn(TabComponent.fromColoredText(line));
}
}
}
@@ -11,6 +11,7 @@ import org.jetbrains.annotations.NotNull;
public enum ProtocolVersion {
UNKNOWN,
V1_21_1 (767),
V1_21 (767),
V1_20_6 (766),
V1_20_5 (766),
@@ -10,7 +10,7 @@ import me.neznamy.tab.api.scoreboard.ScoreboardManager;
import me.neznamy.tab.api.tablist.HeaderFooterManager;
import me.neznamy.tab.api.tablist.TabListFormatManager;
import me.neznamy.tab.shared.chat.EnumChatFormat;
import me.neznamy.tab.shared.chat.SimpleComponent;
import me.neznamy.tab.shared.chat.TabComponent;
import me.neznamy.tab.shared.config.helper.ConfigHelper;
import me.neznamy.tab.shared.cpu.CpuManager;
import me.neznamy.tab.shared.features.nametags.NameTag;
@@ -28,6 +28,8 @@ import org.jetbrains.annotations.Nullable;
import org.yaml.snakeyaml.error.YAMLException;
import java.io.File;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
@@ -184,10 +186,10 @@ public class TAB extends TabAPI {
cpu.enable();
configHelper.startup().checkErrorLog();
configHelper.startup().printWarnCount();
platform.logInfo(new SimpleComponent(EnumChatFormat.GREEN + "Enabled in " + (System.currentTimeMillis()-time) + "ms"));
platform.logInfo(TabComponent.fromColoredText(EnumChatFormat.GREEN + "Enabled in " + (System.currentTimeMillis()-time) + "ms"));
return configuration.getMessages().getReloadSuccess();
} catch (YAMLException e) {
platform.logWarn(new SimpleComponent(EnumChatFormat.RED + "Did not enable due to a broken configuration file."));
platform.logWarn(TabComponent.fromColoredText(EnumChatFormat.RED + "Did not enable due to a broken configuration file."));
kill();
return (configuration == null ? "&4Failed to reload, file %file% has broken syntax. Check console for more info."
: configuration.getMessages().getReloadFailBrokenFile()).replace("%file%", brokenFile);
@@ -208,7 +210,7 @@ public class TAB extends TabAPI {
long time = System.currentTimeMillis();
if (configuration.getMysql() != null) configuration.getMysql().closeConnection();
featureManager.unload();
platform.logInfo(new SimpleComponent(EnumChatFormat.GREEN + "Disabled in " + (System.currentTimeMillis()-time) + "ms"));
platform.logInfo(TabComponent.fromColoredText(EnumChatFormat.GREEN + "Disabled in " + (System.currentTimeMillis()-time) + "ms"));
} catch (Throwable e) {
errorManager.criticalError("Failed to disable", e);
}
@@ -293,6 +295,11 @@ public class TAB extends TabAPI {
return featureManager.getFeature(TabConstants.Feature.HEADER_FOOTER);
}
@Override
public @NotNull Collection<? extends TabPlayer> onlinePlayers() {
return Collections.unmodifiableCollection(data.values());
}
@Override
public @Nullable TabListFormatManager getTabListFormatManager() {
return featureManager.getFeature(TabConstants.Feature.PLAYER_LIST);
@@ -317,6 +324,6 @@ public class TAB extends TabAPI {
*/
public void debug(@NotNull String message) {
if (configuration != null && configuration.isDebugMode())
platform.logInfo(new SimpleComponent(EnumChatFormat.BLUE + "[DEBUG] " + message));
platform.logInfo(TabComponent.fromColoredText(EnumChatFormat.BLUE + "[DEBUG] " + message));
}
}
@@ -19,4 +19,11 @@ public class SimpleComponent extends TabComponent {
public String toLegacyText() {
return text;
}
@Override
@NotNull
public String toRawText() {
return text;
}
}
@@ -115,17 +115,14 @@ public class StructuredComponent extends TabComponent {
return builder.toString();
}
/**
* Returns raw text without colors, only works correctly when component is organized
*
* @return raw text in this component and all child components
*/
public @NotNull String toRawText() {
StringBuilder builder = new StringBuilder();
builder.append(text);
for (StructuredComponent child : getExtra()) {
builder.append(child.text);
@Override
@NotNull
public String toRawText() {
StringBuilder builder = new StringBuilder(text);
for (StructuredComponent extra : getExtra()) {
builder.append(extra.toRawText());
}
return builder.toString();
}
}
@@ -64,6 +64,15 @@ public abstract class TabComponent {
*/
public abstract String toLegacyText();
/**
* Converts this component into a string that only consists of text without any formatting.
*
* @return String containing text of the component and extras
*/
@NotNull
public abstract String toRawText();
/**
* Returns the most optimized component based on text. Returns null if text is null,
* organized component if RGB colors are used or simple component with only text field
@@ -14,13 +14,17 @@ public class MiniMessageFormat implements RGBFormatter {
private static final LegacyComponentSerializer SERIALIZER = LegacyComponentSerializer.builder()
.hexColors().useUnusualXRepeatedCharacterHexFormat().build();
/** Dummy character to append to disable MiniMessage's color compacting that prevents team color from being detected as last color of prefix */
private static final char dummyChar = Character.MAX_VALUE;
@Override
@NotNull
public String reformat(@NotNull String text) {
if (!text.contains("<")) return text; // User did not even attempt to use MiniMessage
if (text.contains(EnumChatFormat.COLOR_STRING)) return text;
try {
return SERIALIZER.serialize(MiniMessage.miniMessage().deserialize(text));
String serialized = SERIALIZER.serialize(MiniMessage.miniMessage().deserialize(text + dummyChar));
return serialized.substring(0, serialized.length()-1); // Remove the dummy char back
} catch (Throwable ignored) {
return text;
}
@@ -4,7 +4,7 @@ import java.text.DecimalFormat;
import java.util.Map;
import java.util.Map.Entry;
import me.neznamy.tab.shared.chat.SimpleComponent;
import me.neznamy.tab.shared.chat.TabComponent;
import me.neznamy.tab.shared.cpu.CpuReport;
import me.neznamy.tab.shared.platform.TabPlayer;
import me.neznamy.tab.shared.chat.EnumChatFormat;
@@ -74,13 +74,13 @@ public class CpuCommand extends SubCommand {
}
public void sendToConsole(@NotNull Map<String, Map<String, Float>> features) {
TAB.getInstance().getPlatform().logInfo(new SimpleComponent(EnumChatFormat.color("&8&l" + LINE_CHAR + " &6Features:")));
TAB.getInstance().getPlatform().logInfo(TabComponent.fromColoredText(EnumChatFormat.color("&8&l" + LINE_CHAR + " &6Features:")));
for (Entry<String, Map<String, Float>> entry : features.entrySet()) {
TAB.getInstance().getPlatform().logInfo(new SimpleComponent(EnumChatFormat.color(
TAB.getInstance().getPlatform().logInfo(TabComponent.fromColoredText(EnumChatFormat.color(
String.format("&8&l%s &7%s &7(%s%%&7):", LINE_CHAR, entry.getKey(),
colorize(decimal3.format(entry.getValue().values().stream().mapToDouble(Float::floatValue).sum()), 5, 1)))));
for (Entry<String, Float> type : entry.getValue().entrySet()) {
TAB.getInstance().getPlatform().logInfo(new SimpleComponent(EnumChatFormat.color(
TAB.getInstance().getPlatform().logInfo(TabComponent.fromColoredText(EnumChatFormat.color(
String.format("&8&l%s &7%s - %s%%", LINE_CHAR, type.getKey(), colorize(decimal3.format(type.getValue()), 5, 1)))));
}
}
@@ -91,7 +91,7 @@ public class CpuCommand extends SubCommand {
for (Entry<String, Map<String, Float>> entry : features.entrySet()) {
double featureTotal = entry.getValue().values().stream().mapToDouble(Float::floatValue).sum();
String core = String.format("&8&l%s &7%s &7(%s%%&7):", LINE_CHAR, entry.getKey(), colorize(decimal3.format(featureTotal), 5, 1));
sender.sendMessage(new SimpleComponent(EnumChatFormat.color(core)));
sender.sendMessage(TabComponent.fromColoredText(EnumChatFormat.color(core)));
}
}
@@ -3,7 +3,7 @@ package me.neznamy.tab.shared.config;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.shared.chat.EnumChatFormat;
import me.neznamy.tab.shared.chat.SimpleComponent;
import me.neznamy.tab.shared.chat.TabComponent;
import me.neznamy.tab.shared.config.file.ConfigurationFile;
import me.neznamy.tab.shared.config.file.YamlConfigurationFile;
import org.jetbrains.annotations.NotNull;
@@ -25,7 +25,7 @@ public class Converter {
public void convert2810to290(@NotNull ConfigurationFile animations) {
if (animations.getValues().size() == 1 && animations.getValues().containsKey("animations")) {
TAB.getInstance().getPlatform().logInfo(new SimpleComponent(EnumChatFormat.YELLOW + "Performing configuration conversion from 2.8.10 to 2.9.0"));
TAB.getInstance().getPlatform().logInfo(TabComponent.fromColoredText(EnumChatFormat.YELLOW + "Performing configuration conversion from 2.8.10 to 2.9.0"));
animations.setValues(animations.getConfigurationSection("animations"));
animations.save();
}
@@ -42,7 +42,7 @@ public class Converter {
*/
public void convert292to300(@NotNull ConfigurationFile currentConfig) throws IOException {
if (!currentConfig.hasConfigOption("change-nametag-prefix-suffix")) return;
TAB.getInstance().getPlatform().logInfo(new SimpleComponent(EnumChatFormat.YELLOW + "Performing configuration conversion from 2.9.2 to 3.0.0"));
TAB.getInstance().getPlatform().logInfo(TabComponent.fromColoredText(EnumChatFormat.YELLOW + "Performing configuration conversion from 2.9.2 to 3.0.0"));
File folder = TAB.getInstance().getDataFolder();
moveOldFiles();
@@ -346,13 +346,13 @@ public class Converter {
public void convert301to302(@NotNull ConfigurationFile config) {
if (config.removeOption("placeholders.remove-strings")) {
TAB.getInstance().getPlatform().logInfo(new SimpleComponent(EnumChatFormat.YELLOW + "Performing configuration conversion from 3.0.1 to 3.0.2"));
TAB.getInstance().getPlatform().logInfo(TabComponent.fromColoredText(EnumChatFormat.YELLOW + "Performing configuration conversion from 3.0.1 to 3.0.2"));
}
}
public void convert331to332(@NotNull ConfigurationFile config) {
if (config.removeOption("scoreboard-teams.unlimited-nametag-mode.use-marker-tag-for-1-8-x-clients")) {
TAB.getInstance().getPlatform().logInfo(new SimpleComponent(EnumChatFormat.YELLOW + "Performing configuration conversion from 3.3.1 to 3.3.2)"));
TAB.getInstance().getPlatform().logInfo(TabComponent.fromColoredText(EnumChatFormat.YELLOW + "Performing configuration conversion from 3.3.1 to 3.3.2)"));
}
}
@@ -360,7 +360,7 @@ public class Converter {
public void convert332to400(@NotNull ConfigurationFile config) throws IOException {
// Removed config options
if (config.hasConfigOption("fix-pet-names")) {
TAB.getInstance().getPlatform().logInfo(new SimpleComponent(EnumChatFormat.YELLOW + "Performing configuration conversion from 3.3.2 to 4.0.0"));
TAB.getInstance().getPlatform().logInfo(TabComponent.fromColoredText(EnumChatFormat.YELLOW + "Performing configuration conversion from 3.3.2 to 4.0.0"));
config.set("fix-pet-names", null);
config.set("bossbar.disable-in-worlds", null);
config.set("bossbar.disable-in-servers", null);
@@ -425,13 +425,13 @@ public class Converter {
public void convert403to404(@NotNull ConfigurationFile config) {
if (config.removeOption("global-playerlist.update-latency")) {
TAB.getInstance().getPlatform().logInfo(new SimpleComponent(EnumChatFormat.YELLOW + "Performing configuration conversion from 4.0.3 to 4.0.4"));
TAB.getInstance().getPlatform().logInfo(TabComponent.fromColoredText(EnumChatFormat.YELLOW + "Performing configuration conversion from 4.0.3 to 4.0.4"));
}
}
public void convert409to410(@NotNull ConfigurationFile config) {
if (config.hasConfigOption("yellow-number-in-tablist")) {
TAB.getInstance().getPlatform().logInfo(new SimpleComponent(EnumChatFormat.YELLOW + "Performing configuration conversion from 4.0.9 to 4.1.0"));
TAB.getInstance().getPlatform().logInfo(TabComponent.fromColoredText(EnumChatFormat.YELLOW + "Performing configuration conversion from 4.0.9 to 4.1.0"));
Map<Object, Object> section = config.getConfigurationSection("yellow-number-in-tablist");
section.put("fancy-value", "&7Ping: %ping%");
config.set("yellow-number-in-tablist", null);
@@ -14,7 +14,7 @@ import java.util.List;
import lombok.NonNull;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.chat.EnumChatFormat;
import me.neznamy.tab.shared.chat.SimpleComponent;
import me.neznamy.tab.shared.chat.TabComponent;
import org.jetbrains.annotations.Nullable;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
@@ -56,13 +56,13 @@ public class YamlConfigurationFile extends ConfigurationFile {
if (input != null) input.close();
TAB tab = TAB.getInstance();
tab.setBrokenFile(destination.getName());
tab.getPlatform().logWarn(new SimpleComponent("File " + destination + " has broken syntax."));
tab.getPlatform().logInfo(new SimpleComponent(EnumChatFormat.GOLD + "Error message from yaml parser: " + e.getMessage()));
tab.getPlatform().logWarn(TabComponent.fromColoredText("File " + destination + " has broken syntax."));
tab.getPlatform().logInfo(TabComponent.fromColoredText(EnumChatFormat.GOLD + "Error message from yaml parser: " + e.getMessage()));
List<String> suggestions = YamlAssist.getSuggestions(file);
if (!suggestions.isEmpty()) {
tab.getPlatform().logInfo(new SimpleComponent(EnumChatFormat.LIGHT_PURPLE + "Suggestions to fix yaml syntax:"));
tab.getPlatform().logInfo(TabComponent.fromColoredText(EnumChatFormat.LIGHT_PURPLE + "Suggestions to fix yaml syntax:"));
for (String suggestion : suggestions) {
tab.getPlatform().logInfo(new SimpleComponent(EnumChatFormat.LIGHT_PURPLE + "- " + suggestion));
tab.getPlatform().logInfo(TabComponent.fromColoredText(EnumChatFormat.LIGHT_PURPLE + "- " + suggestion));
}
}
throw e;
@@ -79,7 +79,7 @@ public class YamlConfigurationFile extends ConfigurationFile {
writer.close();
fixHeader();
} catch (IOException e) {
TAB.getInstance().getPlatform().logWarn(new SimpleComponent("Failed to save yaml file " + file.getPath() + " with content " + values.toString()));
TAB.getInstance().getPlatform().logWarn(TabComponent.fromColoredText("Failed to save yaml file " + file.getPath() + " with content " + values.toString()));
}
}
}
@@ -2,7 +2,7 @@ package me.neznamy.tab.shared.config.helper;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.chat.EnumChatFormat;
import me.neznamy.tab.shared.chat.SimpleComponent;
import me.neznamy.tab.shared.chat.TabComponent;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
@@ -100,6 +100,6 @@ public class HintPrinter {
* Message to log
*/
private void hint(@NotNull String message) {
TAB.getInstance().getPlatform().logInfo(new SimpleComponent(EnumChatFormat.GOLD + "[Hint] " + message));
TAB.getInstance().getPlatform().logInfo(TabComponent.fromColoredText(EnumChatFormat.GOLD + "[Hint] " + message));
}
}
@@ -3,7 +3,7 @@ package me.neznamy.tab.shared.config.helper;
import me.neznamy.tab.api.bossbar.BossBar;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.chat.EnumChatFormat;
import me.neznamy.tab.shared.chat.SimpleComponent;
import me.neznamy.tab.shared.chat.TabComponent;
import me.neznamy.tab.shared.features.sorting.types.SortingType;
import me.neznamy.tab.shared.platform.TabPlayer;
import me.neznamy.tab.shared.proxy.ProxyTabPlayer;
@@ -196,6 +196,6 @@ public class RuntimeErrorPrinter {
* Message to log
*/
private void error(@NotNull String message) {
TAB.getInstance().getPlatform().logWarn(new SimpleComponent(message));
TAB.getInstance().getPlatform().logWarn(TabComponent.fromColoredText(message));
}
}
@@ -4,7 +4,7 @@ import me.neznamy.tab.api.bossbar.BarColor;
import me.neznamy.tab.api.bossbar.BarStyle;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.shared.chat.SimpleComponent;
import me.neznamy.tab.shared.chat.TabComponent;
import me.neznamy.tab.shared.features.layout.GroupPattern;
import me.neznamy.tab.shared.features.layout.LayoutManagerImpl;
import me.neznamy.tab.shared.features.sorting.types.SortingType;
@@ -389,7 +389,7 @@ public class StartupWarnPrinter {
private void startupWarn(@NotNull String... messages) {
warnCount++;
for (String message : messages) {
TAB.getInstance().getPlatform().logWarn(new SimpleComponent(message));
TAB.getInstance().getPlatform().logWarn(TabComponent.fromColoredText(message));
}
}
@@ -398,7 +398,7 @@ public class StartupWarnPrinter {
*/
public void printWarnCount() {
if (warnCount == 0) return;
TAB.getInstance().getPlatform().logWarn(new SimpleComponent("Found a total of " + warnCount + " issues."));
TAB.getInstance().getPlatform().logWarn(TabComponent.fromColoredText("Found a total of " + warnCount + " issues."));
// Reset after printing to prevent count going up on each reload
warnCount = 0;
}
@@ -14,7 +14,7 @@ import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.chat.EnumChatFormat;
import me.neznamy.tab.shared.chat.SimpleComponent;
import me.neznamy.tab.shared.chat.TabComponent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -37,7 +37,7 @@ public class MySQL {
properties.setProperty("useSSL", String.valueOf(useSSL));
properties.setProperty("characterEncoding", "UTF-8");
con = DriverManager.getConnection(String.format("jdbc:mysql://%s:%d/%s", host, port, database), properties);
TAB.getInstance().getPlatform().logInfo(new SimpleComponent(EnumChatFormat.GREEN + "Successfully connected to MySQL"));
TAB.getInstance().getPlatform().logInfo(TabComponent.fromColoredText(EnumChatFormat.GREEN + "Successfully connected to MySQL"));
}
public void closeConnection() throws SQLException {
@@ -111,7 +111,7 @@ public class LayoutPattern extends TabFeature implements Refreshable, Layout {
public void addFixedSlot(int slot, @NonNull String text, @NonNull String skin, int ping) {
ensureActive();
fixedSlots.put(slot, new FixedSlot(manager, slot, this, manager.getUUID(slot), text,
"Layout-" + text + "-SLOT-" + slot, skin, "Layout-" + text + "-SLOT-" + slot+ "-skin", ping));
"Layout-" + name + "-SLOT-" + slot, skin, "Layout-" + name + "-SLOT-" + slot+ "-skin", ping));
}
@Override
@@ -227,6 +227,16 @@ public abstract class RedisSupport extends TabFeature implements JoinListener, Q
}
return count;
});
TAB.getInstance().getPlaceholderManager().registerPlayerPlaceholder(TabConstants.Placeholder.SERVER_ONLINE, 1000, p -> {
int count = 0;
for (TabPlayer player : TAB.getInstance().getOnlinePlayers()) {
if (((TabPlayer)p).getServer().equals(player.getServer()) && !player.isVanished()) count++;
}
for (RedisPlayer player : redisPlayers.values()) {
if (((TabPlayer)p).getServer().equals(player.getServer()) && !player.isVanished()) count++;
}
return count;
});
}
@Override
@@ -61,11 +61,11 @@ public class Placeholder extends SortingType {
@Override
public String getChars(@NotNull TabPlayer p) {
String output = EnumChatFormat.color(setPlaceholders(p));
p.sortingData.teamNameNote += "\n-> " + sortingPlaceholder.getIdentifier() + " returned \"&e" + output + "&r\"";
p.sortingData.teamNameNote += "\n-> " + sortingPlaceholder + " returned \"&e" + output + "&r\"";
int position;
String cleanOutput = output.trim().toLowerCase(Locale.US);
if (!sortingMap.containsKey(cleanOutput)) {
TAB.getInstance().getConfigHelper().runtime().valueNotInPredefinedValues(sortingPlaceholder.getIdentifier(), sortingMap.keySet(), cleanOutput, p);
TAB.getInstance().getConfigHelper().runtime().valueNotInPredefinedValues(sortingPlaceholder, sortingMap.keySet(), cleanOutput, p);
position = sortingMap.size()+1;
p.sortingData.teamNameNote += "&c (not in list)&r. ";
} else {
@@ -24,7 +24,7 @@ public class PlaceholderAtoZ extends SortingType {
@Override
public String getChars(@NotNull TabPlayer p) {
String output = setPlaceholders(p);
p.sortingData.teamNameNote += "\n-> " + sortingPlaceholder.getIdentifier() + " returned \"&e" + output + "&r\". &r";
p.sortingData.teamNameNote += "\n-> " + sortingPlaceholder + " returned \"&e" + output + "&r\". &r";
return sorting.isCaseSensitiveSorting() ? output : output.toLowerCase();
}
}
@@ -24,7 +24,7 @@ public class PlaceholderHighToLow extends SortingType {
@Override
public String getChars(@NotNull TabPlayer p) {
String output = setPlaceholders(p);
p.sortingData.teamNameNote += "\n-> " + sortingPlaceholder.getIdentifier() + " returned \"&e" + output + "&r\". &r";
return compressNumber(DEFAULT_NUMBER - parseDouble(sortingPlaceholder.getIdentifier(), output, 0, p));
p.sortingData.teamNameNote += "\n-> " + sortingPlaceholder + " returned \"&e" + output + "&r\". &r";
return compressNumber(DEFAULT_NUMBER - parseDouble(sortingPlaceholder, output, 0, p));
}
}
@@ -24,7 +24,7 @@ public class PlaceholderLowToHigh extends SortingType {
@Override
public String getChars(@NotNull TabPlayer p) {
String output = setPlaceholders(p);
p.sortingData.teamNameNote += "\n-> " + sortingPlaceholder.getIdentifier() + " returned \"&e" + output + "&r\". &r";
return compressNumber(DEFAULT_NUMBER + parseDouble(sortingPlaceholder.getIdentifier(), output, 0, p));
p.sortingData.teamNameNote += "\n-> " + sortingPlaceholder + " returned \"&e" + output + "&r\". &r";
return compressNumber(DEFAULT_NUMBER + parseDouble(sortingPlaceholder, output, 0, p));
}
}
@@ -24,7 +24,7 @@ public class PlaceholderZtoA extends SortingType {
@Override
public String getChars(@NotNull TabPlayer p) {
char[] chars = setPlaceholders(p).toCharArray();
p.sortingData.teamNameNote += "\n-> " + sortingPlaceholder.getIdentifier() + " returned \"&e" + new String(chars) + "&r\". &r";
p.sortingData.teamNameNote += "\n-> " + sortingPlaceholder + " returned \"&e" + new String(chars) + "&r\". &r";
for (int i=0; i<chars.length; i++) {
char c = chars[i];
if (c >= 65 && c <= 90) {
@@ -28,7 +28,7 @@ public abstract class SortingType {
protected final int DEFAULT_NUMBER = Integer.MAX_VALUE / 2;
/** Placeholder to sort by, if sorting type uses it */
protected TabPlaceholder sortingPlaceholder;
protected String sortingPlaceholder;
/**
* Constructs new instance with given parameter
@@ -43,7 +43,7 @@ public abstract class SortingType {
TAB.getInstance().getConfigHelper().startup().invalidSortingPlaceholder(sortingPlaceholder, this);
} else {
sorting.addUsedPlaceholder(sortingPlaceholder);
this.sortingPlaceholder = TAB.getInstance().getPlaceholderManager().getPlaceholder(sortingPlaceholder);
this.sortingPlaceholder = sortingPlaceholder;
}
}
@@ -56,7 +56,8 @@ public abstract class SortingType {
*/
protected String setPlaceholders(TabPlayer player) {
if (sortingPlaceholder == null) return "";
return sortingPlaceholder.set(sortingPlaceholder.getIdentifier(), player);
TabPlaceholder placeholder = TAB.getInstance().getPlaceholderManager().getPlaceholder(sortingPlaceholder);
return placeholder.set(placeholder.getIdentifier(), player);
}
/**
@@ -84,7 +84,12 @@ public class SpongeTabPlayer extends BackendTabPlayer {
public TabList.Skin getSkin() {
List<ProfileProperty> list = getPlayer().profile().properties();
if (list.isEmpty()) return null; // Offline mode
return new TabList.Skin(list.get(0).value(), list.get(0).signature().orElse(null));
for (ProfileProperty property : list) {
if (property.name().equals(TabList.TEXTURES_PROPERTY)) {
return new TabList.Skin(property.value(), property.signature().orElse(null));
}
}
return null;
}
@Override
@@ -18,12 +18,19 @@ import me.neznamy.tab.shared.platform.EventListener;
import me.neznamy.tab.shared.platform.TabPlayer;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
/**
* The core for Velocity forwarding events into all enabled features
*/
@SuppressWarnings("UnstableApiUsage")
public class VelocityEventListener implements EventListener<Player> {
/** Map for tracking online players */
private final Map<Player, UUID> players = new ConcurrentHashMap<>();
/**
* Listens to player disconnecting from the server.
*
@@ -32,7 +39,10 @@ public class VelocityEventListener implements EventListener<Player> {
*/
@Subscribe
public void onQuit(@NotNull DisconnectEvent e) {
quit(e.getPlayer().getUniqueId());
// Check if the player was actually connected to the server in the first place to avoid processing
// disconnect of an existing player who is still there (because players are mapped by UUID in TAB)
UUID id = players.remove(e.getPlayer());
if (id != null) quit(id);
}
/**
@@ -66,6 +76,7 @@ public class VelocityEventListener implements EventListener<Player> {
tab.getCPUManager().runTask(() -> {
TabPlayer player = tab.getPlayer(e.getPlayer().getUniqueId());
if (player == null) {
players.put(e.getPlayer(), e.getPlayer().getUniqueId());
tab.getFeatureManager().onJoin(createPlayer(e.getPlayer()));
} else {
player.getScoreboard().freeze(); // Prevent server switch listeners from sending packets before re-registering objectives in onLoginPacket
@@ -9,7 +9,6 @@ import me.neznamy.tab.platforms.velocity.features.VelocityRedisSupport;
import me.neznamy.tab.platforms.velocity.hook.VelocityPremiumVanishHook;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.shared.chat.EnumChatFormat;
import me.neznamy.tab.shared.chat.TabComponent;
import me.neznamy.tab.shared.features.injection.PipelineInjector;
import me.neznamy.tab.shared.features.redis.RedisSupport;
@@ -18,6 +17,8 @@ import me.neznamy.tab.shared.hook.PremiumVanishHook;
import me.neznamy.tab.shared.proxy.ProxyPlatform;
import me.neznamy.tab.shared.util.ReflectionUtils;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
import org.bstats.charts.SimplePie;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -32,6 +33,9 @@ public class VelocityPlatform extends ProxyPlatform {
@NotNull
private final VelocityTAB plugin;
/** Logger for components */
private static final ComponentLogger logger = ComponentLogger.logger("TAB");
/** Plugin message channel */
@Getter
private final MinecraftChannelIdentifier MCI = MinecraftChannelIdentifier.from(TabConstants.PLUGIN_MESSAGE_CHANNEL_NAME);
@@ -68,12 +72,12 @@ public class VelocityPlatform extends ProxyPlatform {
@Override
public void logInfo(@NotNull TabComponent message) {
plugin.getLogger().info(message.toLegacyText());
logger.info(AdventureHook.toAdventureComponent(message, true));
}
@Override
public void logWarn(@NotNull TabComponent message) {
plugin.getLogger().warn(EnumChatFormat.RED + message.toLegacyText());
logger.warn(Component.text("").color(NamedTextColor.RED).append(AdventureHook.toAdventureComponent(message, true)));
}
@Override
@@ -7,7 +7,6 @@ import com.velocitypowered.api.event.proxy.ProxyShutdownEvent;
import com.velocitypowered.api.plugin.Plugin;
import com.velocitypowered.api.plugin.annotation.DataDirectory;
import com.velocitypowered.api.proxy.ProxyServer;
import com.velocitypowered.api.proxy.player.TabList;
import lombok.Getter;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
@@ -18,7 +17,6 @@ import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import java.nio.file.Path;
import java.util.UUID;
/**
* Main class for Velocity.
@@ -54,9 +52,8 @@ public class VelocityTAB {
*/
@Subscribe
public void onProxyInitialization(@Nullable ProxyInitializeEvent event) {
if (!ReflectionUtils.methodExists(TabList.class, "getEntry", UUID.class)) {
logger.warn(EnumChatFormat.RED + "The plugin requires Velocity build #229 " +
"(released on February 20th, 2023) and up to work.");
if (!ReflectionUtils.classExists("net.kyori.adventure.text.logger.slf4j.ComponentLogger")) {
logger.warn(EnumChatFormat.RED + "The plugin requires Velocity build #274 (released on October 12th, 2023) and up to work.");
return;
}
TAB.create(new VelocityPlatform(this));
@@ -65,7 +65,12 @@ public class VelocityTabPlayer extends ProxyTabPlayer {
public TabList.Skin getSkin() {
List<GameProfile.Property> properties = getPlayer().getGameProfile().getProperties();
if (properties.isEmpty()) return null; //Offline mode
return new TabList.Skin(properties.get(0).getValue(), properties.get(0).getSignature());
for (GameProfile.Property property : properties) {
if (property.getName().equals(TabList.TEXTURES_PROPERTY)) {
return new TabList.Skin(property.getValue(), property.getSignature());
}
}
return null;
}
@Override