mirror of
https://github.com/NEZNAMY/TAB.git
synced 2026-11-12 20:22:01 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6b9063c789 | ||
|
|
ce0a45b76c | ||
|
|
41a0bd37ce | ||
|
|
449d3cb3ee | ||
|
|
a1a3852b08 | ||
|
|
ef63df5175 | ||
|
|
17e57f9d0c | ||
|
|
949216325f | ||
|
|
dddf0b35a2 | ||
|
|
35ec2bf215 | ||
|
|
607b60b323 | ||
|
|
bb6ad72962 | ||
|
|
4fb8420d69 | ||
|
|
74af19a9d9 | ||
|
|
737ac70e6e | ||
|
|
bfc72b735c | ||
|
|
323412f935 | ||
|
|
db34ba4995 | ||
|
|
15d7eb6d91 | ||
|
|
e2b95df2e4 | ||
|
|
1117094412 | ||
|
|
4bab076642 | ||
|
|
d602818f67 | ||
|
|
1a76321062 | ||
|
|
4b056529dd | ||
|
|
bdbf3ba5b1 | ||
|
|
aab9a650b0 | ||
|
|
f8487f07a6 | ||
|
|
e38721fa69 | ||
|
|
18e52f2f10 | ||
|
|
f1300410b8 | ||
|
|
e17059f1f7 | ||
|
|
f3e9f7cf06 | ||
|
|
63ed24d136 | ||
|
|
66008cd767 | ||
|
|
1852c1b5c4 | ||
|
|
9a4fc2fc73 | ||
|
|
6846a78833 | ||
|
|
d3d9e85a7f | ||
|
|
f867b6b2ea | ||
|
|
639aa5e251 | ||
|
|
f089e26998 | ||
|
|
9390a402ff | ||
|
|
7fda2c5f88 | ||
|
|
7f0b2e2b13 | ||
|
|
bdc44d46c8 | ||
|
|
8d8480469a | ||
|
|
a91fe6db36 | ||
|
|
20d734aa80 | ||
|
|
f053bbd544 | ||
|
|
7eba26cab1 | ||
|
|
36006045e2 | ||
|
|
d5d025c2c9 | ||
|
|
5b7053d500 | ||
|
|
ce2e60c268 |
No files matched your search
@@ -18,6 +18,14 @@ body:
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Plugin list
|
||||
description: Full list of plugins (output of /plugins)
|
||||
placeholder: ...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe the bug
|
||||
|
||||
@@ -205,7 +205,7 @@ public interface BossBar {
|
||||
* Player to check
|
||||
* @return {@code true} if player is allowed to see this Boss Bar, {@code false} if not.
|
||||
*/
|
||||
boolean containsPlayer(TabPlayer player);
|
||||
boolean containsPlayer(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this boss bar is configured as announcement-only bar,
|
||||
|
||||
+3
-2
@@ -4,7 +4,7 @@ plugins {
|
||||
|
||||
allprojects {
|
||||
group = "me.neznamy"
|
||||
version = "4.1.4"
|
||||
version = "4.1.5"
|
||||
description = "An all-in-one solution that works"
|
||||
|
||||
ext.set("id", "tab")
|
||||
@@ -19,7 +19,8 @@ val platforms = setOf(
|
||||
projects.sponge7,
|
||||
projects.sponge8,
|
||||
projects.fabric,
|
||||
projects.fabric.v1144
|
||||
projects.fabric.v1144,
|
||||
projects.fabric.v1182
|
||||
).map { it.dependencyProject }
|
||||
|
||||
val special = setOf(
|
||||
|
||||
@@ -110,7 +110,7 @@ public class DataWatcher implements EntityData {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets value into data values
|
||||
*
|
||||
@@ -270,4 +270,4 @@ public class DataWatcher implements EntityData {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-6
@@ -20,10 +20,6 @@ import java.util.*;
|
||||
@Getter
|
||||
public class BukkitTabExpansion extends PlaceholderExpansion implements TabExpansion {
|
||||
|
||||
/** Map holding all values for all players for easy and high-performance access */
|
||||
@NotNull
|
||||
private final WeakHashMap<TabPlayer, Map<String, String>> values = new WeakHashMap<>();
|
||||
|
||||
/** List of all placeholders offered by the plugin for command suggestions */
|
||||
@NotNull
|
||||
private final List<String> placeholders = Collections.unmodifiableList(Arrays.asList(
|
||||
@@ -102,12 +98,12 @@ public class BukkitTabExpansion extends PlaceholderExpansion implements TabExpan
|
||||
if (player == null) return "<Player cannot be null>";
|
||||
TabPlayer p = TAB.getInstance().getPlayer(player.getUniqueId());
|
||||
if (p == null || !p.isLoaded()) return "<Player is not loaded>";
|
||||
return values.get(p).get(identifier);
|
||||
return p.expansionValues.values.get(identifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(@NotNull TabPlayer player, @NotNull String key, @NotNull String value) {
|
||||
values.computeIfAbsent(player, p -> new HashMap<>()).put(key, value);
|
||||
player.expansionValues.values.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -41,7 +41,7 @@ public class ComponentConverter {
|
||||
|
||||
// 1.16+
|
||||
private Method ChatHexColor_fromRGB;
|
||||
private Constructor<?> newMinecraftKey;
|
||||
private Method ResourceLocation_tryParse;
|
||||
|
||||
/**
|
||||
* Constructs new instance and loads all NMS classes, constructors and methods.
|
||||
@@ -67,13 +67,13 @@ public class ComponentConverter {
|
||||
}
|
||||
if (BukkitReflection.getMinorVersion() >= 16) {
|
||||
Class<?> chatHexColor = BukkitReflection.getClass("network.chat.ChatHexColor", "ChatHexColor");
|
||||
Class<?> MinecraftKey = BukkitReflection.getClass("resources.MinecraftKey", "MinecraftKey");
|
||||
Class<?> ResourceLocation = BukkitReflection.getClass("resources.MinecraftKey", "MinecraftKey");
|
||||
Class<?> chatClickable = BukkitReflection.getClass("network.chat.ChatClickable", "ChatClickable");
|
||||
Class<?> chatHoverable = BukkitReflection.getClass("network.chat.ChatHoverable", "ChatHoverable");
|
||||
newMinecraftKey = MinecraftKey.getConstructor(String.class);
|
||||
ResourceLocation_tryParse = ReflectionUtils.getMethod(ResourceLocation, new String[]{"tryParse", "m_135820_", "a"}, String.class);
|
||||
ChatHexColor_fromRGB = ReflectionUtils.getOnlyMethod(chatHexColor, chatHexColor, int.class);
|
||||
newChatModifier = ReflectionUtils.setAccessible(ChatModifier.getDeclaredConstructor(chatHexColor, Boolean.class, Boolean.class, Boolean.class,
|
||||
Boolean.class, Boolean.class, chatClickable, chatHoverable, String.class, MinecraftKey));
|
||||
Boolean.class, Boolean.class, chatClickable, chatHoverable, String.class, ResourceLocation));
|
||||
convertModifier = this::createModifierModern;
|
||||
} else {
|
||||
newChatModifier = ChatModifier.getConstructor();
|
||||
@@ -124,7 +124,7 @@ public class ComponentConverter {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
modifier.getFont() == null ? null : newMinecraftKey.newInstance(modifier.getFont())
|
||||
modifier.getFont() == null ? null : ResourceLocation_tryParse.invoke(null, modifier.getFont())
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ public class PingRetriever {
|
||||
*/
|
||||
public static void tryLoad() {
|
||||
try {
|
||||
if (BukkitReflection.getMinorVersion() >= 17) {
|
||||
if (ReflectionUtils.methodExists(Player.class, "getPing")) {
|
||||
getPing = Player::getPing;
|
||||
} else {
|
||||
Method getHandle = BukkitReflection.getBukkitClass("entity.CraftPlayer").getMethod("getHandle");
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package me.neznamy.tab.platforms.bukkit.platform;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.SneakyThrows;
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import me.neznamy.tab.platforms.bukkit.*;
|
||||
import me.neznamy.tab.platforms.bukkit.entity.PacketEntityView;
|
||||
@@ -50,7 +49,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* Implementation of Platform interface for Bukkit platform
|
||||
@@ -69,13 +67,8 @@ public class BukkitPlatform implements BackendPlatform {
|
||||
/** Variables checking presence of other plugins to hook into */
|
||||
private final boolean placeholderAPI = ReflectionUtils.classExists("me.clip.placeholderapi.PlaceholderAPI");
|
||||
|
||||
/** NMS server to get TPS from on spigot */
|
||||
@Nullable
|
||||
private Object server;
|
||||
|
||||
/** TPS field */
|
||||
@Nullable
|
||||
private Field spigotTps;
|
||||
/** Spigot field for tracking TPS, the array is final and only being modified instead of re-instantiated */
|
||||
private double[] recentTps;
|
||||
|
||||
/** Detection for presence of Paper's TPS getter */
|
||||
private final boolean paperTps = ReflectionUtils.methodExists(Bukkit.class, "getTPS");
|
||||
@@ -93,8 +86,8 @@ public class BukkitPlatform implements BackendPlatform {
|
||||
this.plugin = plugin;
|
||||
long time = System.currentTimeMillis();
|
||||
try {
|
||||
server = Bukkit.getServer().getClass().getMethod("getServer").invoke(Bukkit.getServer());
|
||||
spigotTps = server.getClass().getField("recentTps");
|
||||
Object server = Bukkit.getServer().getClass().getMethod("getServer").invoke(Bukkit.getServer());
|
||||
recentTps = ((double[]) server.getClass().getField("recentTps").get(server));
|
||||
} catch (ReflectiveOperationException ignored) {
|
||||
//not spigot
|
||||
}
|
||||
@@ -298,12 +291,11 @@ public class BukkitPlatform implements BackendPlatform {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public double getTPS() {
|
||||
if (paperTps) {
|
||||
if (recentTps != null) {
|
||||
return recentTps[0];
|
||||
} else if (paperTps) {
|
||||
return Bukkit.getTPS()[0];
|
||||
} else if (spigotTps != null) {
|
||||
return ((double[]) spigotTps.get(server))[0];
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
@@ -315,18 +307,6 @@ public class BukkitPlatform implements BackendPlatform {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs task in the main thread for given entity.
|
||||
*
|
||||
* @param entity
|
||||
* Entity's main thread
|
||||
* @param task
|
||||
* Task to run
|
||||
*/
|
||||
public void runSync(@NotNull Entity entity, @NotNull Runnable task) {
|
||||
Bukkit.getScheduler().runTask(plugin, task);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs an entity task that may or may not need to use its main thread.
|
||||
*
|
||||
|
||||
@@ -80,7 +80,6 @@ public class FoliaPlatform extends BukkitPlatform {
|
||||
* @param task
|
||||
* Task to run
|
||||
*/
|
||||
@Override
|
||||
@SneakyThrows
|
||||
@SuppressWarnings("JavaReflectionMemberAccess")
|
||||
public void runSync(@NotNull Entity entity, @NotNull Runnable task) {
|
||||
|
||||
+1
-4
@@ -29,7 +29,6 @@ public class TeamPacketData {
|
||||
/** First version with static constructor-like methods */
|
||||
private final int STATIC_CONSTRUCTOR_VERSION = 17;
|
||||
|
||||
private Class<?> Component;
|
||||
private final Object emptyScoreboard;
|
||||
@Getter private final Class<?> TeamPacketClass;
|
||||
private Constructor<?> newTeamPacket;
|
||||
@@ -85,12 +84,10 @@ public class TeamPacketData {
|
||||
new String[]{"func_98300_b", "setCanSeeFriendlyInvisibles", "b", "m_83362_", "setSeeFriendlyInvisibles"}, // {Thermos, 1.5.1+, 1.5 & 1.18+, Mohist 1.18.2, 1.20.2+}
|
||||
boolean.class
|
||||
);
|
||||
if (minorVersion >= 7) {
|
||||
Component = BukkitReflection.getClass("network.chat.Component", "network.chat.IChatBaseComponent", "IChatBaseComponent");
|
||||
}
|
||||
if (minorVersion >= 8) loadVisibility(scoreboardTeam);
|
||||
if (minorVersion >= 9) loadCollision(scoreboardTeam);
|
||||
if (minorVersion >= MODERN_TEAM_DATA_VERSION) {
|
||||
Class<?> Component = BukkitReflection.getClass("network.chat.Component", "network.chat.IChatBaseComponent", "IChatBaseComponent");
|
||||
ScoreboardTeam_setColor = ReflectionUtils.getOnlyMethod(scoreboardTeam, void.class, enumChatFormatClass);
|
||||
ScoreboardTeam_setPrefix = ReflectionUtils.getMethod(
|
||||
scoreboardTeam,
|
||||
|
||||
@@ -48,7 +48,12 @@ public class BukkitTabList extends TabListBase<String> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEntry0(@NonNull UUID id, @NonNull String name, @Nullable Skin skin, int latency, int gameMode, @Nullable String displayName) {
|
||||
public void updateListed(@NonNull UUID entry, boolean listed) {
|
||||
// Shrug
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEntry0(@NonNull UUID id, @NonNull String name, @Nullable Skin skin, boolean listed, int latency, int gameMode, @Nullable String displayName) {
|
||||
// Shrug
|
||||
}
|
||||
|
||||
|
||||
+14
-5
@@ -51,6 +51,8 @@ public class PacketTabList1193 extends PacketTabList18 {
|
||||
* If something goes wrong
|
||||
*/
|
||||
public static void loadNew() throws ReflectiveOperationException {
|
||||
Class<?> IChatBaseComponent = BukkitReflection.getClass("network.chat.Component", "network.chat.IChatBaseComponent", "IChatBaseComponent");
|
||||
Class<?> RemoteChatSession$Data = BukkitReflection.getClass("network.chat.RemoteChatSession$Data", "network.chat.RemoteChatSession$a");
|
||||
Class<Enum> EnumGamemodeClass = (Class<Enum>) BukkitReflection.getClass("world.level.GameType", "world.level.EnumGamemode");
|
||||
ActionClass = (Class<Enum>) BukkitReflection.getClass(
|
||||
"network.protocol.game.ClientboundPlayerInfoUpdatePacket$Action", // Mojang
|
||||
@@ -67,9 +69,10 @@ public class PacketTabList1193 extends PacketTabList18 {
|
||||
|
||||
loadSharedContent(playerInfoDataClass, EnumGamemodeClass);
|
||||
|
||||
newPlayerInfoData = playerInfoDataClass.getConstructor(UUID.class, GameProfile.class, boolean.class, int.class, EnumGamemodeClass, IChatBaseComponent, RemoteChatSession$Data);
|
||||
|
||||
PlayerInfoData_Listed = ReflectionUtils.getOnlyField(playerInfoDataClass, boolean.class);
|
||||
PlayerInfoData_GameMode = ReflectionUtils.getOnlyField(playerInfoDataClass, EnumGamemodeClass);
|
||||
Class<?> RemoteChatSession$Data = BukkitReflection.getClass("network.chat.RemoteChatSession$Data", "network.chat.RemoteChatSession$a");
|
||||
PlayerInfoData_RemoteChatSession = ReflectionUtils.getOnlyField(playerInfoDataClass, RemoteChatSession$Data);
|
||||
PlayerInfoData_UUID = ReflectionUtils.getOnlyField(playerInfoDataClass, UUID.class);
|
||||
newRemovePacket = BukkitReflection.getClass("network.protocol.game.ClientboundPlayerInfoRemovePacket").getConstructor(List.class);
|
||||
@@ -77,12 +80,12 @@ public class PacketTabList1193 extends PacketTabList18 {
|
||||
actionAddPlayer = Enum.valueOf(ActionClass, Action.ADD_PLAYER.name());
|
||||
actionUpdateDisplayName = Enum.valueOf(ActionClass, Action.UPDATE_DISPLAY_NAME.name());
|
||||
actionUpdateLatency = Enum.valueOf(ActionClass, Action.UPDATE_LATENCY.name());
|
||||
Enum actionUpdateGameMode = Enum.valueOf(ActionClass, Action.UPDATE_GAME_MODE.name());
|
||||
|
||||
actionToEnumSet.put(Action.ADD_PLAYER, EnumSet.allOf(ActionClass));
|
||||
actionToEnumSet.put(Action.UPDATE_GAME_MODE, EnumSet.of(actionUpdateGameMode));
|
||||
actionToEnumSet.put(Action.UPDATE_GAME_MODE, EnumSet.of(Enum.valueOf(ActionClass, Action.UPDATE_GAME_MODE.name())));
|
||||
actionToEnumSet.put(Action.UPDATE_DISPLAY_NAME, EnumSet.of(actionUpdateDisplayName));
|
||||
actionToEnumSet.put(Action.UPDATE_LATENCY, EnumSet.of(actionUpdateLatency));
|
||||
actionToEnumSet.put(Action.UPDATE_LISTED, EnumSet.of(Enum.valueOf(ActionClass, Action.UPDATE_LISTED.name())));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -91,16 +94,22 @@ public class PacketTabList1193 extends PacketTabList18 {
|
||||
packetSender.sendPacket(player.getPlayer(), newRemovePacket.newInstance(Collections.singletonList(entry)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateListed(@NonNull UUID entry, boolean listed) {
|
||||
packetSender.sendPacket(player.getPlayer(),
|
||||
createPacket(Action.UPDATE_LISTED, entry, "", null, listed, 0, 0, null));
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@NonNull
|
||||
@Override
|
||||
public Object createPacket(@NonNull Action action, @NonNull UUID id, @NonNull String name, @Nullable Skin skin,
|
||||
int latency, int gameMode, @Nullable Object displayName) {
|
||||
boolean listed, int latency, int gameMode, @Nullable Object displayName) {
|
||||
Object packet = newPlayerInfo.newInstance(actionToEnumSet.get(action), Collections.emptyList());
|
||||
PLAYERS.set(packet, Collections.singletonList(newPlayerInfoData.newInstance(
|
||||
id,
|
||||
action == Action.ADD_PLAYER ? createProfile(id, name, skin) : null,
|
||||
true,
|
||||
listed,
|
||||
latency,
|
||||
gameModes[gameMode],
|
||||
displayName,
|
||||
|
||||
@@ -85,7 +85,7 @@ public class PacketTabList17 extends TabListBase<String> {
|
||||
public void updateDisplayName0(@NonNull UUID entry, @Nullable String displayName) {
|
||||
if (!displayNames.containsKey(entry)) return; // Entry not tracked by TAB
|
||||
packetSender.sendPacket(player.getPlayer(), newPacket.apply(displayNames.get(entry), false, 0));
|
||||
addEntry0(entry, userNames.get(entry), null, 0, 0, displayName);
|
||||
addEntry0(entry, userNames.get(entry), null, false, 0, 0, displayName);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -100,9 +100,14 @@ public class PacketTabList17 extends TabListBase<String> {
|
||||
// Added in 1.8
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateListed(@NonNull UUID entry, boolean listed) {
|
||||
// Added in 1.19.3
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void addEntry0(@NonNull UUID id, @NonNull String name, @Nullable Skin skin, int latency, int gameMode, @Nullable String displayName) {
|
||||
public void addEntry0(@NonNull UUID id, @NonNull String name, @Nullable Skin skin, boolean listed, int latency, int gameMode, @Nullable String displayName) {
|
||||
String display = displayName == null ? name : displayName;
|
||||
packetSender.sendPacket(player.getPlayer(), newPacket.apply(display, true, latency));
|
||||
userNames.put(id, name);
|
||||
|
||||
@@ -82,11 +82,12 @@ public class PacketTabList18 extends TabListBase<Object> {
|
||||
ACTION = ReflectionUtils.getOnlyField(PlayerInfoClass, ActionClass);
|
||||
|
||||
loadSharedContent(playerInfoDataClass, EnumGamemodeClass);
|
||||
|
||||
newPlayerInfoData = playerInfoDataClass.getConstructors()[0]; // #1105, a specific 1.8.8 fork has 2 constructors
|
||||
}
|
||||
|
||||
protected static void loadSharedContent(Class<?> infoData, Class<Enum> gameMode) throws ReflectiveOperationException {
|
||||
Class<?> IChatBaseComponent = BukkitReflection.getClass("network.chat.Component", "network.chat.IChatBaseComponent", "IChatBaseComponent");
|
||||
newPlayerInfoData = infoData.getConstructors()[0]; // #1105, a specific 1.8.8 fork has 2 constructors
|
||||
PLAYERS = ReflectionUtils.getOnlyField(PlayerInfoClass, List.class);
|
||||
PlayerInfoData_Profile = ReflectionUtils.getOnlyField(infoData, GameProfile.class);
|
||||
PlayerInfoData_Latency = ReflectionUtils.getOnlyField(infoData, int.class);
|
||||
@@ -110,31 +111,36 @@ public class PacketTabList18 extends TabListBase<Object> {
|
||||
@Override
|
||||
public void removeEntry(@NonNull UUID entry) {
|
||||
packetSender.sendPacket(player.getPlayer(),
|
||||
createPacket(Action.REMOVE_PLAYER, entry, "", null, 0, 0, null));
|
||||
createPacket(Action.REMOVE_PLAYER, entry, "", null, false, 0, 0, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDisplayName0(@NonNull UUID entry, @Nullable Object displayName) {
|
||||
packetSender.sendPacket(player.getPlayer(),
|
||||
createPacket(Action.UPDATE_DISPLAY_NAME, entry, "", null, 0, 0, displayName));
|
||||
createPacket(Action.UPDATE_DISPLAY_NAME, entry, "", null, false, 0, 0, displayName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLatency(@NonNull UUID entry, int latency) {
|
||||
packetSender.sendPacket(player.getPlayer(),
|
||||
createPacket(Action.UPDATE_LATENCY, entry, "", null, latency, 0, null));
|
||||
createPacket(Action.UPDATE_LATENCY, entry, "", null, false, latency, 0, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateGameMode(@NonNull UUID entry, int gameMode) {
|
||||
packetSender.sendPacket(player.getPlayer(),
|
||||
createPacket(Action.UPDATE_GAME_MODE, entry, "", null, 0, gameMode, null));
|
||||
createPacket(Action.UPDATE_GAME_MODE, entry, "", null, false, 0, gameMode, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEntry0(@NonNull UUID id, @NonNull String name, @Nullable Skin skin, int latency, int gameMode, @Nullable Object displayName) {
|
||||
public void updateListed(@NonNull UUID entry, boolean listed) {
|
||||
// Added in 1.19.3
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEntry0(@NonNull UUID id, @NonNull String name, @Nullable Skin skin, boolean listed, int latency, int gameMode, @Nullable Object displayName) {
|
||||
packetSender.sendPacket(player.getPlayer(),
|
||||
createPacket(Action.ADD_PLAYER, id, name, skin, latency, gameMode, displayName));
|
||||
createPacket(Action.ADD_PLAYER, id, name, skin, listed, latency, gameMode, displayName));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,6 +154,8 @@ public class PacketTabList18 extends TabListBase<Object> {
|
||||
* Entry name
|
||||
* @param skin
|
||||
* Entry skin
|
||||
* @param listed
|
||||
* Whether entry should be listed or not
|
||||
* @param latency
|
||||
* Entry latency
|
||||
* @param gameMode
|
||||
@@ -159,7 +167,7 @@ public class PacketTabList18 extends TabListBase<Object> {
|
||||
@SneakyThrows
|
||||
@NonNull
|
||||
public Object createPacket(@NonNull Action action, @NonNull UUID id, @NonNull String name, @Nullable Skin skin,
|
||||
int latency, int gameMode, @Nullable Object displayName) {
|
||||
boolean listed, int latency, int gameMode, @Nullable Object displayName) {
|
||||
Object packet = newPlayerInfo.newInstance(Enum.valueOf(ActionClass, action.name()), Collections.emptyList());
|
||||
List<Object> parameters = new ArrayList<>();
|
||||
if (newPlayerInfoData.getParameterTypes()[0] == PlayerInfoClass) {
|
||||
|
||||
@@ -29,10 +29,12 @@ public class BungeeBossBar implements BossBar {
|
||||
@NotNull
|
||||
private final Map<UUID, Integer> styles = new HashMap<>();
|
||||
|
||||
/** Flag tracking whether boss bars should be frozen or not */
|
||||
private boolean frozen;
|
||||
|
||||
@Override
|
||||
public void create(@NotNull UUID id, @NotNull String title, float progress, @NotNull BarColor color, @NotNull BarStyle style) {
|
||||
if (player.getVersion().getMinorVersion() < 9) return;
|
||||
|
||||
if (frozen) return; // Server switch
|
||||
net.md_5.bungee.protocol.packet.BossBar packet = new net.md_5.bungee.protocol.packet.BossBar(id, 0);
|
||||
packet.setHealth(progress);
|
||||
packet.setTitle(TabComponent.optimized(title).convert(player.getVersion()));
|
||||
@@ -46,8 +48,7 @@ public class BungeeBossBar implements BossBar {
|
||||
|
||||
@Override
|
||||
public void update(@NotNull UUID id, @NotNull String title) {
|
||||
if (player.getVersion().getMinorVersion() < 9) return;
|
||||
|
||||
if (frozen) return; // Server switch
|
||||
net.md_5.bungee.protocol.packet.BossBar packet = new net.md_5.bungee.protocol.packet.BossBar(id, 3);
|
||||
packet.setTitle(TabComponent.optimized(title).convert(player.getVersion()));
|
||||
player.sendPacket(packet);
|
||||
@@ -55,8 +56,7 @@ public class BungeeBossBar implements BossBar {
|
||||
|
||||
@Override
|
||||
public void update(@NotNull UUID id, float progress) {
|
||||
if (player.getVersion().getMinorVersion() < 9) return;
|
||||
|
||||
if (frozen) return; // Server switch
|
||||
net.md_5.bungee.protocol.packet.BossBar packet = new net.md_5.bungee.protocol.packet.BossBar(id, 2);
|
||||
packet.setHealth(progress);
|
||||
player.sendPacket(packet);
|
||||
@@ -64,8 +64,7 @@ public class BungeeBossBar implements BossBar {
|
||||
|
||||
@Override
|
||||
public void update(@NotNull UUID id, @NotNull BarStyle style) {
|
||||
if (player.getVersion().getMinorVersion() < 9) return;
|
||||
|
||||
if (frozen) return; // Server switch
|
||||
net.md_5.bungee.protocol.packet.BossBar packet = new net.md_5.bungee.protocol.packet.BossBar(id, 4);
|
||||
packet.setDivision(style.ordinal());
|
||||
packet.setColor(colors.get(id));
|
||||
@@ -76,8 +75,7 @@ public class BungeeBossBar implements BossBar {
|
||||
|
||||
@Override
|
||||
public void update(@NotNull UUID id, @NotNull BarColor color) {
|
||||
if (player.getVersion().getMinorVersion() < 9) return;
|
||||
|
||||
if (frozen) return; // Server switch
|
||||
net.md_5.bungee.protocol.packet.BossBar packet = new net.md_5.bungee.protocol.packet.BossBar(id, 4);
|
||||
packet.setDivision(styles.get(id));
|
||||
packet.setColor(color.ordinal());
|
||||
@@ -88,11 +86,20 @@ public class BungeeBossBar implements BossBar {
|
||||
|
||||
@Override
|
||||
public void remove(@NotNull UUID id) {
|
||||
if (player.getVersion().getMinorVersion() < 9) return;
|
||||
|
||||
if (frozen) return; // Server switch
|
||||
player.sendPacket(new net.md_5.bungee.protocol.packet.BossBar(id, 1));
|
||||
|
||||
colors.remove(id);
|
||||
styles.remove(id);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeze() {
|
||||
frozen = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unfreeze() {
|
||||
frozen = false;
|
||||
}
|
||||
}
|
||||
+4
-2
@@ -42,10 +42,12 @@ public class BungeeEventListener implements EventListener<ProxiedPlayer>, Listen
|
||||
TAB tab = TAB.getInstance();
|
||||
if (tab.isPluginDisabled()) return;
|
||||
|
||||
// Avoid 1.20.3 client crash on scoreboard packets, do it sync to prevent packet being sent after event, but before processing
|
||||
// Avoid 1.20.3+ client crash on scoreboard packets, do it sync to prevent packet being sent after event, but before processing
|
||||
// Avoid 1.20.5+ client disconnect with "Network Protocol Error"
|
||||
TabPlayer p = tab.getPlayer(e.getPlayer().getUniqueId());
|
||||
if (p != null && p.getVersion().getNetworkId() >= ProtocolVersion.V1_20_3.getNetworkId()) {
|
||||
if (p != null && p.getVersion().getNetworkId() >= ProtocolVersion.V1_20_2.getNetworkId()) {
|
||||
p.getScoreboard().freeze();
|
||||
p.getBossBar().freeze();
|
||||
}
|
||||
|
||||
tab.getCPUManager().runTask(() -> {
|
||||
|
||||
@@ -9,7 +9,6 @@ import me.neznamy.tab.shared.chat.*;
|
||||
import me.neznamy.tab.shared.features.injection.PipelineInjector;
|
||||
import me.neznamy.tab.shared.features.redis.RedisSupport;
|
||||
import me.neznamy.tab.shared.hook.PremiumVanishHook;
|
||||
import me.neznamy.tab.shared.hook.ViaVersionHook;
|
||||
import me.neznamy.tab.shared.proxy.ProxyPlatform;
|
||||
import me.neznamy.tab.shared.util.ReflectionUtils;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
@@ -51,7 +50,6 @@ public class BungeePlatform extends ProxyPlatform {
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void loadPlayers() {
|
||||
ViaVersionHook.getInstance().printProxyWarn();
|
||||
try {
|
||||
ProxyConfig config = ProxyServer.getInstance().getConfig();
|
||||
if ((boolean) config.getClass().getMethod("isDisableTabListRewrite").invoke(config)) {
|
||||
|
||||
@@ -56,7 +56,7 @@ public class BungeeTabPlayer extends ProxyTabPlayer {
|
||||
* BungeeCord player
|
||||
*/
|
||||
public BungeeTabPlayer(@NotNull BungeePlatform platform, @NotNull ProxiedPlayer p) {
|
||||
super(platform, p, p.getUniqueId(), p.getName(), p.getServer() != null ? p.getServer().getInfo().getName() : "-", -1);
|
||||
super(platform, p, p.getUniqueId(), p.getName(), p.getServer() != null ? p.getServer().getInfo().getName() : "-", p.getPendingConnection().getVersion());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -112,19 +112,6 @@ public class BungeeTabPlayer extends ProxyTabPlayer {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If ViaVersion is installed on BungeeCord, it changes protocol to match version
|
||||
* of server to which player is connected to. For that reason, we need to retrieve
|
||||
* the field more often than just on join.
|
||||
*
|
||||
* @return Player's current protocol version
|
||||
*/
|
||||
@Override
|
||||
@NotNull
|
||||
public ProtocolVersion getVersion() {
|
||||
return ProtocolVersion.fromNetworkId(getPlayer().getPendingConnection().getVersion());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVanished() {
|
||||
if (PremiumVanishHook.getInstance() != null && PremiumVanishHook.getInstance().isVanished(this)) return true;
|
||||
|
||||
+4
-2
@@ -69,6 +69,8 @@ public abstract class BungeeTabList extends TabList<BungeeTabPlayer, BaseCompone
|
||||
* Entry name
|
||||
* @param skin
|
||||
* Entry skin
|
||||
* @param listed
|
||||
* Whether entry should be listed or not
|
||||
* @param latency
|
||||
* Entry latency
|
||||
* @param gameMode
|
||||
@@ -78,12 +80,12 @@ public abstract class BungeeTabList extends TabList<BungeeTabPlayer, BaseCompone
|
||||
* @return Converted item from parameters
|
||||
*/
|
||||
@NonNull
|
||||
public Item entryToItem(@NonNull UUID id, @NonNull String name, @Nullable Skin skin, int latency, int gameMode, @Nullable BaseComponent displayName) {
|
||||
public Item entryToItem(@NonNull UUID id, @NonNull String name, @Nullable Skin skin, boolean listed, int latency, int gameMode, @Nullable BaseComponent displayName) {
|
||||
Item item = item(id);
|
||||
item.setUsername(name);
|
||||
item.setDisplayName(displayName);
|
||||
item.setGamemode(gameMode);
|
||||
item.setListed(true);
|
||||
item.setListed(listed);
|
||||
item.setPing(latency);
|
||||
if (skin != null) {
|
||||
item.setProperties(new Property[]{new Property(TEXTURES_PROPERTY, skin.getValue(), skin.getSignature())});
|
||||
|
||||
+10
-2
@@ -24,6 +24,7 @@ public class BungeeTabList1193 extends BungeeTabList {
|
||||
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));
|
||||
actions.put(Action.UPDATE_LISTED, EnumSet.of(PlayerListItemUpdate.Action.UPDATE_LISTED));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -66,9 +67,16 @@ public class BungeeTabList1193 extends BungeeTabList {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEntry0(@NonNull UUID id, @NonNull String name, @Nullable Skin skin, int latency, int gameMode, @Nullable BaseComponent displayName) {
|
||||
public void updateListed(@NonNull UUID entry, boolean listed) {
|
||||
Item item = item(entry);
|
||||
item.setListed(listed);
|
||||
sendPacket(Action.UPDATE_LISTED, item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEntry0(@NonNull UUID id, @NonNull String name, @Nullable Skin skin, boolean listed, int latency, int gameMode, @Nullable BaseComponent displayName) {
|
||||
addUuid(id);
|
||||
sendPacket(Action.ADD_PLAYER, entryToItem(id, name, skin, latency, gameMode, displayName));
|
||||
sendPacket(Action.ADD_PLAYER, entryToItem(id, name, skin, listed, latency, gameMode, displayName));
|
||||
}
|
||||
|
||||
private void sendPacket(@NonNull Action action, @NonNull Item item) {
|
||||
|
||||
+10
-3
@@ -56,7 +56,7 @@ public class BungeeTabList17 extends BungeeTabList {
|
||||
public void updateDisplayName0(@NonNull UUID entry, @Nullable BaseComponent displayName) {
|
||||
if (!displayNames.containsKey(entry)) return; // Entry not tracked by TAB
|
||||
update(PlayerListItem.Action.REMOVE_PLAYER, createItem(null, displayNames.get(entry), 0));
|
||||
addEntry0(entry, userNames.get(entry), null, 0, 0, displayName);
|
||||
addEntry0(entry, userNames.get(entry), null, false, 0, 0, displayName);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -66,10 +66,17 @@ public class BungeeTabList17 extends BungeeTabList {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateGameMode(@NonNull UUID entry, int gameMode) {/*Added in 1.8*/}
|
||||
public void updateGameMode(@NonNull UUID entry, int gameMode) {
|
||||
// Added in 1.8
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEntry0(@NonNull UUID id, @NonNull String name, @Nullable Skin skin, int latency, int gameMode, @Nullable BaseComponent displayName) {
|
||||
public void updateListed(@NonNull UUID entry, boolean listed) {
|
||||
// Added in 1.19.3
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEntry0(@NonNull UUID id, @NonNull String name, @Nullable Skin skin, boolean listed, int latency, int gameMode, @Nullable BaseComponent displayName) {
|
||||
addUuid(id);
|
||||
update(PlayerListItem.Action.ADD_PLAYER, createItem(name, displayName == null ? new TextComponent(name) : displayName, latency));
|
||||
|
||||
|
||||
+7
-2
@@ -53,9 +53,14 @@ public class BungeeTabList18 extends BungeeTabList {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEntry0(@NonNull UUID id, @NonNull String name, @Nullable Skin skin, int latency, int gameMode, @Nullable BaseComponent displayName) {
|
||||
public void updateListed(@NonNull UUID entry, boolean listed) {
|
||||
// Added in 1.19.3
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEntry0(@NonNull UUID id, @NonNull String name, @Nullable Skin skin, boolean listed, int latency, int gameMode, @Nullable BaseComponent displayName) {
|
||||
addUuid(id);
|
||||
sendPacket(PlayerListItem.Action.ADD_PLAYER, entryToItem(id, name, skin, latency, gameMode, displayName));
|
||||
sendPacket(PlayerListItem.Action.ADD_PLAYER, entryToItem(id, name, skin, listed, latency, gameMode, displayName));
|
||||
}
|
||||
|
||||
private void sendPacket(@NonNull PlayerListItem.Action action, @NonNull Item item) {
|
||||
|
||||
@@ -12,11 +12,11 @@ repositories {
|
||||
|
||||
dependencies {
|
||||
api(projects.shared)
|
||||
minecraft("com.mojang:minecraft:1.20.5")
|
||||
minecraft("com.mojang:minecraft:24w19a")
|
||||
mappings(loom.officialMojangMappings())
|
||||
modImplementation("me.lucko:fabric-permissions-api:0.2-SNAPSHOT")
|
||||
modImplementation("net.fabricmc:fabric-loader:0.15.9")
|
||||
val version = "0.96.14+1.20.5"
|
||||
val version = "0.97.8+1.20.6"
|
||||
modImplementation(fabricApi.module("fabric-api-base", version))
|
||||
modImplementation(fabricApi.module("fabric-lifecycle-events-v1", version))
|
||||
modImplementation(fabricApi.module("fabric-networking-api-v1", version))
|
||||
|
||||
@@ -3,6 +3,7 @@ package me.neznamy.tab.platforms.fabric;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.platform.EventListener;
|
||||
import me.neznamy.tab.shared.platform.TabPlayer;
|
||||
import me.neznamy.tab.shared.util.ReflectionUtils;
|
||||
import net.fabricmc.fabric.api.entity.event.v1.ServerEntityWorldChangeEvents;
|
||||
import net.fabricmc.fabric.api.entity.event.v1.ServerPlayerEvents;
|
||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
||||
@@ -21,7 +22,7 @@ public class FabricEventListener implements EventListener<ServerPlayer> {
|
||||
ServerPlayConnectionEvents.DISCONNECT.register((connection, $) -> quit(connection.player.getUUID()));
|
||||
ServerPlayConnectionEvents.JOIN.register((connection, $, $$) -> join(connection.player));
|
||||
//TODO command preprocess
|
||||
if (FabricTAB.supportsEntityEvents()) {
|
||||
if (ReflectionUtils.classExists("net.fabricmc.fabric.api.entity.event.v1.ServerPlayerEvents")) {
|
||||
// Added in 1.16
|
||||
ServerPlayerEvents.AFTER_RESPAWN.register(
|
||||
(oldPlayer, newPlayer, alive) -> {
|
||||
|
||||
@@ -34,226 +34,538 @@ import java.util.UUID;
|
||||
*/
|
||||
public class FabricMultiVersion {
|
||||
|
||||
public static final ProtocolVersion serverVersion = ProtocolVersion.fromFriendlyName(FabricTAB.minecraftVersion);
|
||||
public static final Loader loaderNew = new Loader_1_20_5();
|
||||
public static final Loader loaderOld = createOldLoader();
|
||||
/** Server version */
|
||||
private static final ProtocolVersion serverVersion = ProtocolVersion.fromFriendlyName(FabricTAB.minecraftVersion);
|
||||
|
||||
/** Method loader using latest supported MC version */
|
||||
private static final Loader loaderNew = new Loader_1_20_5();
|
||||
|
||||
/** Method loader using 1.18.2 */
|
||||
private static final Loader loader1_18_2 = createLoader("1_18_2");
|
||||
|
||||
/** Method loader using 1.14.4 */
|
||||
private static final Loader loader1_14_4 = createLoader("1_14_4");
|
||||
|
||||
@SneakyThrows
|
||||
private static Loader createOldLoader() {
|
||||
return (Loader) Class.forName("me.neznamy.tab.platforms.fabric.loader.Loader_1_14_4")
|
||||
private static Loader createLoader(@NotNull String version) {
|
||||
return (Loader) Class.forName("me.neznamy.tab.platforms.fabric.loader.Loader_" + version)
|
||||
.getConstructor(ProtocolVersion.class).newInstance(serverVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if player is sneaking, {@code false} if not.
|
||||
*
|
||||
* @param player
|
||||
* Player to check sneak status of
|
||||
* @return {@code true} if player is sneaking, {@code false} if not
|
||||
*/
|
||||
public static boolean isSneaking(@NotNull ServerPlayer player) {
|
||||
if (serverVersion.getMinorVersion() >= 15) return loaderNew.isSneaking(player);
|
||||
return loaderOld.isSneaking(player);
|
||||
return loader1_14_4.isSneaking(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns name of specified world.
|
||||
*
|
||||
* @param level
|
||||
* World to get name of
|
||||
* @return Name of the world
|
||||
*/
|
||||
@NotNull
|
||||
public static String getLevelName(@NotNull Level level) {
|
||||
if (serverVersion.getMinorVersion() >= 16) return loaderNew.getLevelName(level);
|
||||
return loaderOld.getLevelName(level);
|
||||
return loader1_14_4.getLevelName(level);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds sibling to a component.
|
||||
*
|
||||
* @param parent
|
||||
* Parent to add sibling to
|
||||
* @param child
|
||||
* Sibling to add
|
||||
*/
|
||||
public static void addSibling(@NotNull Component parent, @NotNull Component child) {
|
||||
if (serverVersion.getMinorVersion() >= 16) loaderNew.addSibling(parent, child);
|
||||
else loaderOld.addSibling(parent, child);
|
||||
else loader1_14_4.addSibling(parent, child);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts TAB's ChatModifier class to Minecraft Style class.
|
||||
*
|
||||
* @param modifier
|
||||
* Modifier to convert
|
||||
* @param modern
|
||||
* Whether RGB should be supported or not
|
||||
* @return Converted style
|
||||
*/
|
||||
@NotNull
|
||||
public static Style convertModifier(@NotNull ChatModifier modifier, boolean modern) {
|
||||
if (serverVersion.getMinorVersion() >= 16) return loaderNew.convertModifier(modifier, modern);
|
||||
return loaderOld.convertModifier(modifier, modern);
|
||||
return loader1_14_4.convertModifier(modifier, modern);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new Header/Footer packet with given parameters.
|
||||
*
|
||||
* @param header
|
||||
* Header to use
|
||||
* @param footer
|
||||
* Footer to use
|
||||
* @return Packet with given parameters
|
||||
*/
|
||||
@NotNull
|
||||
public static Packet<?> newHeaderFooter(@NotNull Component header, @NotNull Component footer) {
|
||||
if (serverVersion.getMinorVersion() >= 17) return loaderNew.newHeaderFooter(header, footer);
|
||||
return loaderOld.newHeaderFooter(header, footer);
|
||||
return loader1_14_4.newHeaderFooter(header, footer);
|
||||
}
|
||||
|
||||
public static boolean isTeamPacket(@NotNull Packet<?> packet) {
|
||||
if (serverVersion.getMinorVersion() >= 17) return loaderNew.isTeamPacket(packet);
|
||||
return loaderOld.isTeamPacket(packet);
|
||||
/**
|
||||
* Checks outgoing team packet in pipeline to potentially remove players from it.
|
||||
*
|
||||
* @param packet
|
||||
* Packet to check
|
||||
* @param scoreboard
|
||||
* Scoreboard of player who received the packet
|
||||
*/
|
||||
public static void checkTeamPacket(@NotNull Packet<?> packet, @NotNull FabricScoreboard scoreboard) {
|
||||
if (serverVersion.getMinorVersion() >= 17) loaderNew.checkTeamPacket(packet, scoreboard);
|
||||
else loader1_14_4.checkTeamPacket(packet, scoreboard);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates team register packet using given team.
|
||||
*
|
||||
* @param team
|
||||
* Team to register
|
||||
* @return Team register packet using given team
|
||||
*/
|
||||
@NotNull
|
||||
public static Packet<?> registerTeam(@NotNull PlayerTeam team) {
|
||||
if (serverVersion.getMinorVersion() >= 17) return loaderNew.registerTeam(team);
|
||||
return loaderOld.registerTeam(team);
|
||||
return loader1_14_4.registerTeam(team);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates team unregister packet using given team.
|
||||
*
|
||||
* @param team
|
||||
* Team to unregister
|
||||
* @return Team unregister packet using given team
|
||||
*/
|
||||
@NotNull
|
||||
public static Packet<?> unregisterTeam(@NotNull PlayerTeam team) {
|
||||
if (serverVersion.getMinorVersion() >= 17) return loaderNew.unregisterTeam(team);
|
||||
return loaderOld.unregisterTeam(team);
|
||||
return loader1_14_4.unregisterTeam(team);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates team update packet using given team.
|
||||
*
|
||||
* @param team
|
||||
* Team to update
|
||||
* @return Team update packet using given team
|
||||
*/
|
||||
@NotNull
|
||||
public static Packet<?> updateTeam(@NotNull PlayerTeam team) {
|
||||
if (serverVersion.getMinorVersion() >= 17) return loaderNew.updateTeam(team);
|
||||
return loaderOld.updateTeam(team);
|
||||
return loader1_14_4.updateTeam(team);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public static int[] getDestroyedEntities(Packet<?> destroyPacket) {
|
||||
/**
|
||||
* Returns destroyed entities from destroy entity packet.
|
||||
*
|
||||
* @param destroyPacket
|
||||
* Entity destroy packet
|
||||
* @return Destroyed entities
|
||||
*/
|
||||
public static int[] getDestroyedEntities(@NotNull Packet<?> destroyPacket) {
|
||||
if (serverVersion.getMinorVersion() >= 17) return loaderNew.getDestroyedEntities(destroyPacket);
|
||||
return loaderOld.getDestroyedEntities(destroyPacket);
|
||||
return loader1_14_4.getDestroyedEntities(destroyPacket);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs console message as info.
|
||||
*
|
||||
* @param message
|
||||
* Message to log
|
||||
*/
|
||||
public static void logInfo(@NotNull TabComponent message) {
|
||||
if (serverVersion.getNetworkId() >= ProtocolVersion.V1_18_2.getNetworkId()) loaderNew.logInfo(message);
|
||||
else loaderOld.logInfo(message);
|
||||
else loader1_14_4.logInfo(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs console message as warn.
|
||||
*
|
||||
* @param message
|
||||
* Message to log
|
||||
*/
|
||||
public static void logWarn(@NotNull TabComponent message) {
|
||||
if (serverVersion.getNetworkId() >= ProtocolVersion.V1_18_2.getNetworkId()) loaderNew.logWarn(message);
|
||||
else loaderOld.logWarn(message);
|
||||
else loader1_14_4.logWarn(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new text component using given text.
|
||||
*
|
||||
* @param text
|
||||
* Component text
|
||||
* @return Text component with given text
|
||||
*/
|
||||
@NotNull
|
||||
public static Component newTextComponent(@NotNull String text) {
|
||||
if (serverVersion.getMinorVersion() >= 19) return loaderNew.newTextComponent(text);
|
||||
return loaderOld.newTextComponent(text);
|
||||
return loader1_14_4.newTextComponent(text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends message to command source.
|
||||
*
|
||||
* @param source
|
||||
* Command source to send message to
|
||||
* @param message
|
||||
* Message to send
|
||||
*/
|
||||
public static void sendMessage(@NotNull CommandSourceStack source, @NotNull Component message) {
|
||||
if (serverVersion.getMinorVersion() >= 19) loaderNew.sendMessage(source, message);
|
||||
else loaderOld.sendMessage(source, message);
|
||||
else loader1_14_4.sendMessage(source, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates spawn entity packet with given parameters.
|
||||
*
|
||||
* @param level
|
||||
* World to fill for dummy entity
|
||||
* @param id
|
||||
* Entity ID
|
||||
* @param uuid
|
||||
* Entity UUID
|
||||
* @param type
|
||||
* Entity type
|
||||
* @param location
|
||||
* Spawn location
|
||||
* @return Spawn entity packet with given parameters
|
||||
*/
|
||||
@NotNull
|
||||
public static Packet<ClientGamePacketListener> spawnEntity(Level level, int id, UUID uuid, Object type, Location location) {
|
||||
public static Packet<ClientGamePacketListener> spawnEntity(@NotNull Level level, int id, @NotNull UUID uuid, @NotNull Object type, @NotNull Location location) {
|
||||
if (serverVersion.getMinorVersion() >= 19) return loaderNew.spawnEntity(level, id, uuid, type, location);
|
||||
return loaderOld.spawnEntity(level, id, uuid, type, location);
|
||||
return loader1_14_4.spawnEntity(level, id, uuid, type, location);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets style in a component to specified style.
|
||||
*
|
||||
* @param component
|
||||
* Component to change style of
|
||||
* @param style
|
||||
* Style to use
|
||||
*/
|
||||
@SneakyThrows
|
||||
public static void setStyle(@NotNull Component component, @NotNull Style style) {
|
||||
if (serverVersion.getMinorVersion() >= 19) loaderNew.setStyle(component, style);
|
||||
else if (serverVersion.getMinorVersion() >= 16) component.getClass().getMethod("method_10862", Style.class).invoke(component, style);
|
||||
else loaderOld.setStyle(component, style);
|
||||
else if (serverVersion.getMinorVersion() >= 16) loader1_18_2.setStyle(component, style);
|
||||
else loader1_14_4.setStyle(component, style);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends message to player.
|
||||
*
|
||||
* @param player
|
||||
* Player to send message to
|
||||
* @param message
|
||||
* Message to send
|
||||
*/
|
||||
@SneakyThrows
|
||||
public static void sendMessage(@NotNull ServerPlayer player, @NotNull Component message) {
|
||||
if (serverVersion.getMinorVersion() >= 19) loaderNew.sendMessage(player, message);
|
||||
else if (serverVersion.getMinorVersion() >= 16)
|
||||
player.getClass().getMethod("method_9203", Component.class, UUID.class).invoke(player, message, new UUID(0, 0));
|
||||
else loaderOld.sendMessage(player, message);
|
||||
else if (serverVersion.getMinorVersion() >= 16) loader1_18_2.sendMessage(player, message);
|
||||
else loader1_14_4.sendMessage(player, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates entity metadata packet with given metadata.
|
||||
*
|
||||
* @param entityId
|
||||
* Entity ID to change metadata of
|
||||
* @param data
|
||||
* Metadata to change
|
||||
* @return Entity metadata packet with given parameters
|
||||
*/
|
||||
@NotNull
|
||||
public static Packet<ClientGamePacketListener> newEntityMetadata(int entityId, @NotNull EntityData data) {
|
||||
if (serverVersion.getNetworkId() >= ProtocolVersion.V1_19_3.getNetworkId()) return loaderNew.newEntityMetadata(entityId, data);
|
||||
return loaderOld.newEntityMetadata(entityId, data);
|
||||
return loader1_14_4.newEntityMetadata(entityId, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates entity data with given parameters.
|
||||
*
|
||||
* @param viewer
|
||||
* Viewer of custom name
|
||||
* @param flags
|
||||
* Entity flags
|
||||
* @param displayName
|
||||
* Custom name
|
||||
* @param nameVisible
|
||||
* Custom name visibility
|
||||
* @return Entity data with given parameters
|
||||
*/
|
||||
@NotNull
|
||||
public static EntityData createDataWatcher(@NotNull TabPlayer viewer, byte flags, @NotNull String displayName, boolean nameVisible) {
|
||||
int position = EntityData.getArmorStandFlagsPosition(serverVersion.getMinorVersion());
|
||||
if (serverVersion.getNetworkId() >= ProtocolVersion.V1_19_3.getNetworkId()) return loaderNew.createDataWatcher(viewer, flags, displayName, nameVisible, position);
|
||||
return loaderOld.createDataWatcher(viewer, flags, displayName, nameVisible, position);
|
||||
return loader1_14_4.createDataWatcher(viewer, flags, displayName, nameVisible, position);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if packet is player info packet, {@code false} if not.
|
||||
*
|
||||
* @param packet
|
||||
* Packet to check
|
||||
* @return {@code true} if packet is player info packet, {@code false} if not
|
||||
*/
|
||||
public static boolean isPlayerInfo(@NotNull Packet<?> packet) {
|
||||
if (serverVersion.getNetworkId() >= ProtocolVersion.V1_19_3.getNetworkId()) return loaderNew.isPlayerInfo(packet);
|
||||
return loaderOld.isPlayerInfo(packet);
|
||||
return loader1_14_4.isPlayerInfo(packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processed player info packet for anti-override and similar.
|
||||
*
|
||||
* @param receiver
|
||||
* Player who received the packet
|
||||
* @param packet
|
||||
* Received packet
|
||||
*/
|
||||
public static void onPlayerInfo(@NotNull TabPlayer receiver, @NotNull Object packet) {
|
||||
if (serverVersion.getNetworkId() >= ProtocolVersion.V1_19_3.getNetworkId()) loaderNew.onPlayerInfo(receiver, packet);
|
||||
else loaderOld.onPlayerInfo(receiver, packet);
|
||||
else if (serverVersion.getMinorVersion() >= 17) loader1_18_2.onPlayerInfo(receiver, packet);
|
||||
else loader1_14_4.onPlayerInfo(receiver, packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates tablist entry packet using given parameters.
|
||||
*
|
||||
* @param action
|
||||
* Tablist action
|
||||
* @param builder
|
||||
* Entry data
|
||||
* @return Tablist entry packet with given parameters
|
||||
*/
|
||||
@NotNull
|
||||
public static Packet<?> buildTabListPacket(@NotNull TabList.Action action, @NotNull FabricTabList.Builder builder) {
|
||||
if (serverVersion.getNetworkId() >= ProtocolVersion.V1_19_3.getNetworkId()) return loaderNew.buildTabListPacket(action, builder);
|
||||
return loaderOld.buildTabListPacket(action, builder);
|
||||
else if (serverVersion.getMinorVersion() >= 17) return loader1_18_2.buildTabListPacket(action, builder);
|
||||
return loader1_14_4.buildTabListPacket(action, builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if packet is bundle packet, {@code false} if not.
|
||||
*
|
||||
* @param packet
|
||||
* Packet to check
|
||||
* @return {@code true} if packet is bundle packet, {@code false} if not
|
||||
*/
|
||||
public static boolean isBundlePacket(@NotNull Packet<?> packet) {
|
||||
if (serverVersion.getNetworkId() >= ProtocolVersion.V1_19_4.getNetworkId()) return loaderNew.isBundlePacket(packet);
|
||||
return loaderOld.isBundlePacket(packet);
|
||||
return loader1_14_4.isBundlePacket(packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns packets bundled in given bundle packet.
|
||||
*
|
||||
* @param bundlePacket
|
||||
* Bundle packet
|
||||
* @return Bundled packets
|
||||
*/
|
||||
@NotNull
|
||||
public static Iterable<Object> getBundledPackets(@NotNull Packet<?> bundlePacket) {
|
||||
if (serverVersion.getNetworkId() >= ProtocolVersion.V1_19_4.getNetworkId()) return loaderNew.getBundledPackets(bundlePacket);
|
||||
return loaderOld.getBundledPackets(bundlePacket);
|
||||
return loader1_14_4.getBundledPackets(bundlePacket);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends packets to player as a bundle.
|
||||
*
|
||||
* @param player
|
||||
* Player to send packets to
|
||||
* @param packets
|
||||
* Packets to send
|
||||
*/
|
||||
public static void sendPackets(@NotNull ServerPlayer player, @NotNull Iterable<Packet<ClientGamePacketListener>> packets) {
|
||||
if (serverVersion.getNetworkId() >= ProtocolVersion.V1_19_4.getNetworkId()) loaderNew.sendPackets(player, packets);
|
||||
else loaderOld.sendPackets(player, packets);
|
||||
else loader1_14_4.sendPackets(player, packets);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns player's world
|
||||
*
|
||||
* @param player
|
||||
* Player to get world of
|
||||
* @return Player's world
|
||||
*/
|
||||
@NotNull
|
||||
public static Level getLevel(@NotNull ServerPlayer player) {
|
||||
if (serverVersion.getMinorVersion() >= 20) return loaderNew.getLevel(player);
|
||||
return loaderOld.getLevel(player);
|
||||
return loader1_14_4.getLevel(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts minecraft property class into TAB skin class.
|
||||
*
|
||||
* @param property
|
||||
* Property to convert
|
||||
* @return Converted skin
|
||||
*/
|
||||
@NotNull
|
||||
public static TabList.Skin propertyToSkin(@NotNull Property property) {
|
||||
if (serverVersion.getNetworkId() >= ProtocolVersion.V1_20_2.getNetworkId()) return loaderNew.propertyToSkin(property);
|
||||
return loaderOld.propertyToSkin(property);
|
||||
return loader1_14_4.propertyToSkin(property);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if packet is player spawn packet, {@code false} if not.
|
||||
*
|
||||
* @param packet
|
||||
* Packet to check
|
||||
* @return {@code true} if packet is player spawn packet, {@code false} if not
|
||||
*/
|
||||
public static boolean isSpawnPlayerPacket(@NotNull Packet<?> packet) {
|
||||
if (serverVersion.getNetworkId() >= ProtocolVersion.V1_20_2.getNetworkId()) return loaderNew.isSpawnPlayerPacket(packet);
|
||||
return loaderOld.isSpawnPlayerPacket(packet);
|
||||
return loader1_14_4.isSpawnPlayerPacket(packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns player ID of given player spawn packet.
|
||||
*
|
||||
* @param packet
|
||||
* Player spawn packet
|
||||
* @return Player ID
|
||||
*/
|
||||
public static int getSpawnedPlayerId(@NotNull Packet<?> packet) {
|
||||
if (serverVersion.getNetworkId() >= ProtocolVersion.V1_20_2.getNetworkId()) return loaderNew.getSpawnedPlayerId(packet);
|
||||
return loaderOld.getSpawnedPlayerId(packet);
|
||||
return loader1_14_4.getSpawnedPlayerId(packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns player's ping.
|
||||
*
|
||||
* @param player
|
||||
* Player to get ping of
|
||||
* @return Player's ping
|
||||
*/
|
||||
public static int getPing(@NotNull ServerPlayer player) {
|
||||
if (serverVersion.getNetworkId() >= ProtocolVersion.V1_20_2.getNetworkId()) return loaderNew.getPing(player);
|
||||
return loaderOld.getPing(player);
|
||||
return loader1_14_4.getPing(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns display slot of given display objective packet.
|
||||
*
|
||||
* @param packet
|
||||
* Display objective packet
|
||||
* @return Display slot of packet
|
||||
*/
|
||||
public static int getDisplaySlot(@NotNull ClientboundSetDisplayObjectivePacket packet) {
|
||||
if (serverVersion.getNetworkId() >= ProtocolVersion.V1_20_2.getNetworkId()) return loaderNew.getDisplaySlot(packet);
|
||||
return loaderOld.getDisplaySlot(packet);
|
||||
return loader1_14_4.getDisplaySlot(packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates display objective packet with given parameters.
|
||||
*
|
||||
* @param slot
|
||||
* Display slot
|
||||
* @param objective
|
||||
* Objective to display
|
||||
* @return Display objective packet with given parameters
|
||||
*/
|
||||
@NotNull
|
||||
public static Packet<?> setDisplaySlot(int slot, @NotNull Objective objective) {
|
||||
if (serverVersion.getNetworkId() >= ProtocolVersion.V1_20_2.getNetworkId()) return loaderNew.setDisplaySlot(slot, objective);
|
||||
return loaderOld.setDisplaySlot(slot, objective);
|
||||
return loader1_14_4.setDisplaySlot(slot, objective);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns player's network channel.
|
||||
*
|
||||
* @param player
|
||||
* Player to get channel of
|
||||
* @return Player's channel
|
||||
*/
|
||||
@NotNull
|
||||
public static Channel getChannel(@NotNull ServerPlayer player) {
|
||||
if (serverVersion.getNetworkId() >= ProtocolVersion.V1_20_2.getNetworkId()) return loaderNew.getChannel(player);
|
||||
return loaderOld.getChannel(player);
|
||||
return loader1_14_4.getChannel(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns server's current milliseconds per tick.
|
||||
*
|
||||
* @param server
|
||||
* Server to get MSPT value from
|
||||
* @return Server's milliseconds per tick
|
||||
*/
|
||||
public static float getMSPT(@NotNull MinecraftServer server) {
|
||||
if (serverVersion.getNetworkId() >= ProtocolVersion.V1_20_3.getNetworkId()) return loaderNew.getMSPT(server);
|
||||
return loaderOld.getMSPT(server);
|
||||
return loader1_14_4.getMSPT(server);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new remove score packet with given parameters.
|
||||
*
|
||||
* @param objective
|
||||
* Objective to remove score from
|
||||
* @param holder
|
||||
* Score holder to remove
|
||||
* @return Remove score packet with given parameters
|
||||
*/
|
||||
@NotNull
|
||||
public static Packet<?> removeScore(@NotNull String objective, @NotNull String holder) {
|
||||
if (serverVersion.getNetworkId() >= ProtocolVersion.V1_20_3.getNetworkId()) return loaderNew.removeScore(objective, holder);
|
||||
return loaderOld.removeScore(objective, holder);
|
||||
return loader1_14_4.removeScore(objective, holder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new objective with given parameters.
|
||||
*
|
||||
* @param name
|
||||
* Objective name
|
||||
* @param displayName
|
||||
* Objective display name
|
||||
* @param renderType
|
||||
* Score render type
|
||||
* @param numberFormat
|
||||
* Score number format (1.20.3+)
|
||||
* @return New objective with given parameters
|
||||
*/
|
||||
@NotNull
|
||||
public static Objective newObjective(@NotNull String name, @NotNull Component displayName,
|
||||
@NotNull RenderType renderType, @Nullable Component numberFormat) {
|
||||
if (serverVersion.getNetworkId() >= ProtocolVersion.V1_20_3.getNetworkId()) return loaderNew.newObjective(name, displayName, renderType, numberFormat);
|
||||
return loaderOld.newObjective(name, displayName, renderType, numberFormat);
|
||||
return loader1_14_4.newObjective(name, displayName, renderType, numberFormat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new set score packet with given parameters.
|
||||
*
|
||||
* @param objective
|
||||
* Objective to set score in
|
||||
* @param holder
|
||||
* Score holder
|
||||
* @param score
|
||||
* Score value
|
||||
* @param displayName
|
||||
* Display name of score holder (1.20.3+)
|
||||
* @param numberFormat
|
||||
* Number format of score value (1.20.3+)
|
||||
* @return New set score packet with given parameters
|
||||
*/
|
||||
@NotNull
|
||||
public static Packet<?> setScore(@NotNull String objective, @NotNull String holder, int score,
|
||||
@Nullable Component displayName, @Nullable Component numberFormat) {
|
||||
if (serverVersion.getNetworkId() >= ProtocolVersion.V1_20_3.getNetworkId()) return loaderNew.setScore(objective, holder, score, displayName, numberFormat);
|
||||
return loaderOld.setScore(objective, holder, score, displayName, numberFormat);
|
||||
return loader1_14_4.setScore(objective, holder, score, displayName, numberFormat);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,10 @@
|
||||
package me.neznamy.tab.platforms.fabric;
|
||||
|
||||
import lombok.NonNull;
|
||||
import lombok.SneakyThrows;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.chat.EnumChatFormat;
|
||||
import me.neznamy.tab.shared.chat.TabComponent;
|
||||
import me.neznamy.tab.shared.platform.Scoreboard;
|
||||
import me.neznamy.tab.shared.util.ReflectionUtils;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
@@ -18,7 +16,6 @@ import net.minecraft.world.scores.Team;
|
||||
import net.minecraft.world.scores.criteria.ObjectiveCriteria.RenderType;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -121,9 +118,7 @@ public class FabricScoreboard extends Scoreboard<FabricTabPlayer, Component> {
|
||||
player.sendPacket(FabricMultiVersion.removeScore(objective, scoreHolder));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void onPacketSend(@NonNull Object packet) {
|
||||
if (packet instanceof ClientboundSetDisplayObjectivePacket display) {
|
||||
TAB.getInstance().getFeatureManager().onDisplayObjective(player, FabricMultiVersion.getDisplaySlot(display), display.objectiveName);
|
||||
@@ -131,13 +126,8 @@ public class FabricScoreboard extends Scoreboard<FabricTabPlayer, Component> {
|
||||
if (packet instanceof ClientboundSetObjectivePacket objective) {
|
||||
TAB.getInstance().getFeatureManager().onObjective(player, objective.method, objective.objectiveName);
|
||||
}
|
||||
if (isAntiOverrideTeams() && FabricMultiVersion.isTeamPacket((Packet<?>) packet)) {
|
||||
int action = ReflectionUtils.getInstanceFields(packet.getClass(), int.class).get(0).getInt(packet);
|
||||
if (action == TeamAction.REMOVE || action == TeamAction.UPDATE) return;
|
||||
Field playersField = ReflectionUtils.getFields(packet.getClass(), Collection.class).get(0);
|
||||
Collection<String> players = (Collection<String>) playersField.get(packet);
|
||||
String teamName = String.valueOf(ReflectionUtils.getFields(packet.getClass(), String.class).get(0).get(packet));
|
||||
playersField.set(packet, onTeamPacket(action, teamName, players));
|
||||
if (isAntiOverrideTeams()) {
|
||||
FabricMultiVersion.checkTeamPacket((Packet<?>) packet, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package me.neznamy.tab.platforms.fabric;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import me.neznamy.tab.shared.ProtocolVersion;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.util.ReflectionUtils;
|
||||
import net.fabricmc.api.DedicatedServerModInitializer;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
||||
import net.minecraft.SharedConstants;
|
||||
@@ -17,7 +17,7 @@ public class FabricTAB implements DedicatedServerModInitializer {
|
||||
|
||||
@Override
|
||||
public void onInitializeServer() {
|
||||
if (ProtocolVersion.fromFriendlyName(minecraftVersion).getMinorVersion() >= 19) {
|
||||
if (ReflectionUtils.classExists("net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback")) {
|
||||
net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback.EVENT.register((dispatcher, $, $$) -> new FabricTabCommand().onRegisterCommands(dispatcher));
|
||||
} else {
|
||||
net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback.EVENT.register((dispatcher, $) -> new FabricTabCommand().onRegisterCommands(dispatcher));
|
||||
@@ -38,13 +38,4 @@ public class FabricTAB implements DedicatedServerModInitializer {
|
||||
return (String) gameVersion.getClass().getMethod("getName").invoke(gameVersion);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if fabric api contains entity events, {@code false} if not.
|
||||
*
|
||||
* @return {@code true} if supports entity events, {@code false} if not
|
||||
*/
|
||||
public static boolean supportsEntityEvents() {
|
||||
return ProtocolVersion.fromFriendlyName(minecraftVersion).getMinorVersion() >= 16;
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package me.neznamy.tab.platforms.fabric;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import lombok.*;
|
||||
import me.neznamy.tab.shared.ProtocolVersion;
|
||||
import me.neznamy.tab.shared.platform.TabList;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
@@ -29,31 +30,39 @@ public class FabricTabList extends TabList<FabricTabPlayer, Component> {
|
||||
@Override
|
||||
public void removeEntry(@NonNull UUID entry) {
|
||||
player.sendPacket(FabricMultiVersion.buildTabListPacket(Action.REMOVE_PLAYER,
|
||||
new Builder(entry, "", null, 0, 0, null)));
|
||||
new Builder(entry, "", null, false, 0, 0, null)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDisplayName0(@NonNull UUID entry, @Nullable Component displayName) {
|
||||
player.sendPacket(FabricMultiVersion.buildTabListPacket(Action.UPDATE_DISPLAY_NAME,
|
||||
new Builder(entry, "", null, 0, 0, displayName)));
|
||||
new Builder(entry, "", null, false, 0, 0, displayName)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLatency(@NonNull UUID entry, int latency) {
|
||||
player.sendPacket(FabricMultiVersion.buildTabListPacket(Action.UPDATE_LATENCY,
|
||||
new Builder(entry, "", null, latency, 0, null)));
|
||||
new Builder(entry, "", null, false, latency, 0, null)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateGameMode(@NonNull UUID entry, int gameMode) {
|
||||
player.sendPacket(FabricMultiVersion.buildTabListPacket(Action.UPDATE_GAME_MODE,
|
||||
new Builder(entry, "", null, 0, gameMode, null)));
|
||||
new Builder(entry, "", null, false, 0, gameMode, null)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEntry0(@NonNull UUID id, @NonNull String name, @Nullable Skin skin, int latency, int gameMode, @Nullable Component displayName) {
|
||||
public void updateListed(@NonNull UUID entry, boolean listed) {
|
||||
if (player.getPlatform().getServerVersion().getNetworkId() >= ProtocolVersion.V1_19_3.getNetworkId()) {
|
||||
player.sendPacket(FabricMultiVersion.buildTabListPacket(Action.UPDATE_LISTED,
|
||||
new Builder(entry, "", null, listed, 0, 0, null)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEntry0(@NonNull UUID id, @NonNull String name, @Nullable Skin skin, boolean listed, int latency, int gameMode, @Nullable Component displayName) {
|
||||
player.sendPacket(FabricMultiVersion.buildTabListPacket(Action.ADD_PLAYER,
|
||||
new Builder(id, name, skin, latency, gameMode, displayName)));
|
||||
new Builder(id, name, skin, listed, latency, gameMode, displayName)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -83,6 +92,7 @@ public class FabricTabList extends TabList<FabricTabPlayer, Component> {
|
||||
@NonNull private final UUID id;
|
||||
@NonNull private String name;
|
||||
@Nullable private Skin skin;
|
||||
private boolean listed;
|
||||
private int latency;
|
||||
private int gameMode;
|
||||
@Nullable private Component displayName;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package me.neznamy.tab.platforms.fabric.features;
|
||||
|
||||
import me.neznamy.tab.platforms.fabric.FabricMultiVersion;
|
||||
import me.neznamy.tab.platforms.fabric.FabricTAB;
|
||||
import me.neznamy.tab.platforms.fabric.FabricTabPlayer;
|
||||
import me.neznamy.tab.shared.backend.EntityData;
|
||||
import me.neznamy.tab.shared.backend.features.unlimitedtags.BackendNameTagX;
|
||||
import me.neznamy.tab.shared.platform.TabPlayer;
|
||||
import me.neznamy.tab.shared.util.ReflectionUtils;
|
||||
import net.fabricmc.fabric.api.entity.event.v1.ServerPlayerEvents;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
@@ -28,7 +28,7 @@ public class FabricNameTagX extends BackendNameTagX {
|
||||
* Constructs new instance and registers event listener.
|
||||
*/
|
||||
public FabricNameTagX() {
|
||||
if (FabricTAB.supportsEntityEvents()) {
|
||||
if (ReflectionUtils.classExists("net.fabricmc.fabric.api.entity.event.v1.ServerPlayerEvents")) {
|
||||
// Added in 1.16
|
||||
ServerPlayerEvents.AFTER_RESPAWN.register((oldPlayer, newPlayer, alive) -> {
|
||||
if (enabled) respawn(oldPlayer.getUUID());
|
||||
|
||||
@@ -2,6 +2,7 @@ package me.neznamy.tab.platforms.fabric.loader;
|
||||
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import io.netty.channel.Channel;
|
||||
import me.neznamy.tab.platforms.fabric.FabricScoreboard;
|
||||
import me.neznamy.tab.platforms.fabric.FabricTabList;
|
||||
import me.neznamy.tab.shared.backend.EntityData;
|
||||
import me.neznamy.tab.shared.backend.Location;
|
||||
@@ -27,100 +28,413 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Interface for executing methods that have changed over the versions.
|
||||
* Each implementation of this interface is compiled for a different version of Minecraft.
|
||||
* Then, internal logic is used to decide which implementation to use for each method
|
||||
* based on server version.
|
||||
*/
|
||||
public interface Loader {
|
||||
|
||||
/** Dummy scoreboard for objectives */
|
||||
Scoreboard dummyScoreboard = new Scoreboard();
|
||||
|
||||
/**
|
||||
* Returns name of specified world.
|
||||
*
|
||||
* @param level
|
||||
* World to get name of
|
||||
* @return Name of the world
|
||||
*/
|
||||
@NotNull
|
||||
String getLevelName(@NotNull Level level);
|
||||
|
||||
/**
|
||||
* Converts minecraft property class into TAB skin class.
|
||||
*
|
||||
* @param property
|
||||
* Property to convert
|
||||
* @return Converted skin
|
||||
*/
|
||||
@NotNull
|
||||
TabList.Skin propertyToSkin(@NotNull Property property);
|
||||
|
||||
/**
|
||||
* Creates new text component using given text.
|
||||
*
|
||||
* @param text
|
||||
* Component text
|
||||
* @return Text component with given text
|
||||
*/
|
||||
@NotNull
|
||||
Component newTextComponent(@NotNull String text);
|
||||
|
||||
/**
|
||||
* Converts TAB's ChatModifier class to Minecraft Style class.
|
||||
*
|
||||
* @param modifier
|
||||
* Modifier to convert
|
||||
* @param modern
|
||||
* Whether RGB should be supported or not
|
||||
* @return Converted style
|
||||
*/
|
||||
@NotNull
|
||||
Style convertModifier(@NotNull ChatModifier modifier, boolean modern);
|
||||
|
||||
/**
|
||||
* Adds sibling to a component.
|
||||
*
|
||||
* @param parent
|
||||
* Parent to add sibling to
|
||||
* @param child
|
||||
* Sibling to add
|
||||
*/
|
||||
void addSibling(@NotNull Component parent, @NotNull Component child);
|
||||
|
||||
/**
|
||||
* Creates team register packet using given team.
|
||||
*
|
||||
* @param team
|
||||
* Team to register
|
||||
* @return Team register packet using given team
|
||||
*/
|
||||
@NotNull
|
||||
Packet<?> registerTeam(@NotNull PlayerTeam team);
|
||||
|
||||
/**
|
||||
* Creates team unregister packet using given team.
|
||||
*
|
||||
* @param team
|
||||
* Team to unregister
|
||||
* @return Team unregister packet using given team
|
||||
*/
|
||||
@NotNull
|
||||
Packet<?> unregisterTeam(@NotNull PlayerTeam team);
|
||||
|
||||
/**
|
||||
* Creates team update packet using given team.
|
||||
*
|
||||
* @param team
|
||||
* Team to update
|
||||
* @return Team update packet using given team
|
||||
*/
|
||||
@NotNull
|
||||
Packet<?> updateTeam(@NotNull PlayerTeam team);
|
||||
|
||||
/**
|
||||
* Returns {@code true} if player is sneaking, {@code false} if not.
|
||||
*
|
||||
* @param player
|
||||
* Player to check sneak status of
|
||||
* @return {@code true} if player is sneaking, {@code false} if not
|
||||
*/
|
||||
boolean isSneaking(@NotNull ServerPlayer player);
|
||||
|
||||
/**
|
||||
* Sends message to player.
|
||||
*
|
||||
* @param player
|
||||
* Player to send message to
|
||||
* @param message
|
||||
* Message to send
|
||||
*/
|
||||
void sendMessage(@NotNull ServerPlayer player, @NotNull Component message);
|
||||
|
||||
/**
|
||||
* Sends message to command source.
|
||||
*
|
||||
* @param source
|
||||
* Command source to send message to
|
||||
* @param message
|
||||
* Message to send
|
||||
*/
|
||||
void sendMessage(@NotNull CommandSourceStack source, @NotNull Component message);
|
||||
|
||||
/**
|
||||
* Creates new Header/Footer packet with given parameters.
|
||||
*
|
||||
* @param header
|
||||
* Header to use
|
||||
* @param footer
|
||||
* Footer to use
|
||||
* @return Packet with given parameters
|
||||
*/
|
||||
@NotNull
|
||||
Packet<?> newHeaderFooter(@NotNull Component header, @NotNull Component footer);
|
||||
|
||||
boolean isTeamPacket(@NotNull Packet<?> packet);
|
||||
/**
|
||||
* Checks outgoing team packet in pipeline to potentially remove players from it.
|
||||
*
|
||||
* @param packet
|
||||
* Packet to check
|
||||
* @param scoreboard
|
||||
* Scoreboard of player who received the packet
|
||||
*/
|
||||
void checkTeamPacket(@NotNull Packet<?> packet, @NotNull FabricScoreboard scoreboard);
|
||||
|
||||
/**
|
||||
* Creates spawn entity packet with given parameters.
|
||||
*
|
||||
* @param level
|
||||
* World to fill for dummy entity
|
||||
* @param id
|
||||
* Entity ID
|
||||
* @param uuid
|
||||
* Entity UUID
|
||||
* @param type
|
||||
* Entity type
|
||||
* @param location
|
||||
* Spawn location
|
||||
* @return Spawn entity packet with given parameters
|
||||
*/
|
||||
@NotNull
|
||||
Packet<ClientGamePacketListener> spawnEntity(@NotNull Level level, int id, @NotNull UUID uuid, @NotNull Object type, @NotNull Location location);
|
||||
|
||||
/**
|
||||
* Creates entity metadata packet with given metadata.
|
||||
*
|
||||
* @param entityId
|
||||
* Entity ID to change metadata of
|
||||
* @param data
|
||||
* Metadata to change
|
||||
* @return Entity metadata packet with given parameters
|
||||
*/
|
||||
@NotNull
|
||||
Packet<ClientGamePacketListener> newEntityMetadata(int entityId, @NotNull EntityData data);
|
||||
|
||||
/**
|
||||
* Creates entity data with given parameters.
|
||||
*
|
||||
* @param viewer
|
||||
* Viewer of custom name
|
||||
* @param flags
|
||||
* Entity flags
|
||||
* @param displayName
|
||||
* Custom name
|
||||
* @param nameVisible
|
||||
* Custom name visibility
|
||||
* @param markerPosition
|
||||
* Armor stand marker flag position
|
||||
* @return Entity data with given parameters
|
||||
*/
|
||||
@NotNull
|
||||
EntityData createDataWatcher(@NotNull TabPlayer viewer, byte flags, @NotNull String displayName, boolean nameVisible, int markerPosition);
|
||||
|
||||
/**
|
||||
* Returns {@code true} if packet is player info packet, {@code false} if not.
|
||||
*
|
||||
* @param packet
|
||||
* Packet to check
|
||||
* @return {@code true} if packet is player info packet, {@code false} if not
|
||||
*/
|
||||
boolean isPlayerInfo(@NotNull Packet<?> packet);
|
||||
|
||||
/**
|
||||
* Processed player info packet for anti-override and similar.
|
||||
*
|
||||
* @param receiver
|
||||
* Player who received the packet
|
||||
* @param packet
|
||||
* Received packet
|
||||
*/
|
||||
void onPlayerInfo(@NotNull TabPlayer receiver, @NotNull Object packet);
|
||||
|
||||
/**
|
||||
* Creates tablist entry packet using given parameters.
|
||||
*
|
||||
* @param action
|
||||
* Tablist action
|
||||
* @param builder
|
||||
* Entry data
|
||||
* @return Tablist entry packet with given parameters
|
||||
*/
|
||||
@NotNull
|
||||
Packet<?> buildTabListPacket(@NotNull TabList.Action action, @NotNull FabricTabList.Builder builder);
|
||||
|
||||
/**
|
||||
* Returns {@code true} if packet is bundle packet, {@code false} if not.
|
||||
*
|
||||
* @param packet
|
||||
* Packet to check
|
||||
* @return {@code true} if packet is bundle packet, {@code false} if not
|
||||
*/
|
||||
boolean isBundlePacket(@NotNull Packet<?> packet);
|
||||
|
||||
/**
|
||||
* Returns packets bundled in given bundle packet.
|
||||
*
|
||||
* @param bundlePacket
|
||||
* Bundle packet
|
||||
* @return Bundled packets
|
||||
*/
|
||||
@NotNull
|
||||
Iterable<Object> getBundledPackets(@NotNull Packet<?> bundlePacket);
|
||||
|
||||
/**
|
||||
* Sends packets to player as a bundle.
|
||||
*
|
||||
* @param player
|
||||
* Player to send packets to
|
||||
* @param packets
|
||||
* Packets to send
|
||||
*/
|
||||
void sendPackets(@NotNull ServerPlayer player, @NotNull Iterable<Packet<ClientGamePacketListener>> packets);
|
||||
|
||||
/**
|
||||
* Returns player's world
|
||||
*
|
||||
* @param player
|
||||
* Player to get world of
|
||||
* @return Player's world
|
||||
*/
|
||||
@NotNull
|
||||
Level getLevel(@NotNull ServerPlayer player);
|
||||
|
||||
/**
|
||||
* Returns {@code true} if packet is player spawn packet, {@code false} if not.
|
||||
*
|
||||
* @param packet
|
||||
* Packet to check
|
||||
* @return {@code true} if packet is player spawn packet, {@code false} if not
|
||||
*/
|
||||
boolean isSpawnPlayerPacket(@NotNull Packet<?> packet);
|
||||
|
||||
/**
|
||||
* Returns player ID of given player spawn packet.
|
||||
*
|
||||
* @param packet
|
||||
* Player spawn packet
|
||||
* @return Player ID
|
||||
*/
|
||||
int getSpawnedPlayerId(@NotNull Packet<?> packet);
|
||||
|
||||
/**
|
||||
* Returns player's ping.
|
||||
*
|
||||
* @param player
|
||||
* Player to get ping of
|
||||
* @return Player's ping
|
||||
*/
|
||||
int getPing(@NotNull ServerPlayer player);
|
||||
|
||||
/**
|
||||
* Returns display slot of given display objective packet.
|
||||
*
|
||||
* @param packet
|
||||
* Display objective packet
|
||||
* @return Display slot of packet
|
||||
*/
|
||||
int getDisplaySlot(@NotNull ClientboundSetDisplayObjectivePacket packet);
|
||||
|
||||
/**
|
||||
* Creates display objective packet with given parameters.
|
||||
*
|
||||
* @param slot
|
||||
* Display slot
|
||||
* @param objective
|
||||
* Objective to display
|
||||
* @return Display objective packet with given parameters
|
||||
*/
|
||||
@NotNull
|
||||
Packet<?> setDisplaySlot(int slot, @NotNull Objective objective);
|
||||
|
||||
/**
|
||||
* Returns player's network channel.
|
||||
*
|
||||
* @param player
|
||||
* Player to get channel of
|
||||
* @return Player's channel
|
||||
*/
|
||||
@NotNull
|
||||
Channel getChannel(@NotNull ServerPlayer player);
|
||||
|
||||
/**
|
||||
* Returns server's current milliseconds per tick.
|
||||
*
|
||||
* @param server
|
||||
* Server to get MSPT value from
|
||||
* @return Server's milliseconds per tick
|
||||
*/
|
||||
float getMSPT(@NotNull MinecraftServer server);
|
||||
|
||||
/**
|
||||
* Creates new remove score packet with given parameters.
|
||||
*
|
||||
* @param objective
|
||||
* Objective to remove score from
|
||||
* @param holder
|
||||
* Score holder to remove
|
||||
* @return Remove score packet with given parameters
|
||||
*/
|
||||
@NotNull
|
||||
Packet<?> removeScore(@NotNull String objective, @NotNull String holder);
|
||||
|
||||
int[] getDestroyedEntities(Packet<?> destroyPacket);
|
||||
/**
|
||||
* Returns destroyed entities from destroy entity packet.
|
||||
*
|
||||
* @param destroyPacket
|
||||
* Entity destroy packet
|
||||
* @return Destroyed entities
|
||||
*/
|
||||
int[] getDestroyedEntities(@NotNull Packet<?> destroyPacket);
|
||||
|
||||
/**
|
||||
* Creates new objective with given parameters.
|
||||
*
|
||||
* @param name
|
||||
* Objective name
|
||||
* @param displayName
|
||||
* Objective display name
|
||||
* @param renderType
|
||||
* Score render type
|
||||
* @param numberFormat
|
||||
* Score number format (1.20.3+)
|
||||
* @return New objective with given parameters
|
||||
*/
|
||||
@NotNull
|
||||
Objective newObjective(@NotNull String name, @NotNull Component displayName, @NotNull RenderType renderType, @Nullable Component numberFormat);
|
||||
|
||||
/**
|
||||
* Creates a new set score packet with given parameters.
|
||||
*
|
||||
* @param objective
|
||||
* Objective to set score in
|
||||
* @param holder
|
||||
* Score holder
|
||||
* @param score
|
||||
* Score value
|
||||
* @param displayName
|
||||
* Display name of score holder (1.20.3+)
|
||||
* @param numberFormat
|
||||
* Number format of score value (1.20.3+)
|
||||
* @return New set score packet with given parameters
|
||||
*/
|
||||
@NotNull
|
||||
Packet<?> setScore(@NotNull String objective, @NotNull String holder, int score, @Nullable Component displayName, @Nullable Component numberFormat);
|
||||
|
||||
/**
|
||||
* Sets style in a component to specified style.
|
||||
*
|
||||
* @param component
|
||||
* Component to change style of
|
||||
* @param style
|
||||
* Style to use
|
||||
*/
|
||||
void setStyle(@NotNull Component component, @NotNull Style style);
|
||||
|
||||
/**
|
||||
* Logs console message as info.
|
||||
*
|
||||
* @param message
|
||||
* Message to log
|
||||
*/
|
||||
void logInfo(@NotNull TabComponent message);
|
||||
|
||||
/**
|
||||
* Logs console message as warn.
|
||||
*
|
||||
* @param message
|
||||
* Message to log
|
||||
*/
|
||||
void logWarn(@NotNull TabComponent message);
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.SneakyThrows;
|
||||
import me.neznamy.tab.platforms.fabric.FabricScoreboard;
|
||||
import me.neznamy.tab.platforms.fabric.FabricTabList;
|
||||
import me.neznamy.tab.platforms.fabric.FabricTabPlayer;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
@@ -11,6 +12,7 @@ import me.neznamy.tab.shared.backend.EntityData;
|
||||
import me.neznamy.tab.shared.backend.Location;
|
||||
import me.neznamy.tab.shared.chat.ChatModifier;
|
||||
import me.neznamy.tab.shared.chat.TabComponent;
|
||||
import me.neznamy.tab.shared.platform.Scoreboard;
|
||||
import me.neznamy.tab.shared.platform.TabList;
|
||||
import me.neznamy.tab.shared.platform.TabPlayer;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
@@ -143,8 +145,11 @@ public class Loader_1_20_5 implements Loader {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTeamPacket(@NotNull Packet<?> packet) {
|
||||
return packet instanceof ClientboundSetPlayerTeamPacket; // Fabric-mapped name changed
|
||||
public void checkTeamPacket(@NotNull Packet<?> packet, @NotNull FabricScoreboard scoreboard) {
|
||||
if (packet instanceof ClientboundSetPlayerTeamPacket team) {
|
||||
if (team.method == Scoreboard.TeamAction.REMOVE || team.method == Scoreboard.TeamAction.UPDATE) return;
|
||||
team.players = scoreboard.onTeamPacket(team.method, team.getName(), team.players);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -211,7 +216,7 @@ public class Loader_1_20_5 implements Loader {
|
||||
packet.entries = Collections.singletonList(new ClientboundPlayerInfoUpdatePacket.Entry(
|
||||
entry.getId(),
|
||||
action == TabList.Action.ADD_PLAYER ? entry.createProfile() : null,
|
||||
true,
|
||||
entry.isListed(),
|
||||
entry.getLatency(),
|
||||
GameType.byId(entry.getGameMode()),
|
||||
entry.getDisplayName(),
|
||||
@@ -291,7 +296,7 @@ public class Loader_1_20_5 implements Loader {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getDestroyedEntities(Packet<?> destroyPacket) {
|
||||
public int[] getDestroyedEntities(@NotNull Packet<?> destroyPacket) {
|
||||
return ((ClientboundRemoveEntitiesPacket) destroyPacket).getEntityIds().toIntArray();
|
||||
}
|
||||
|
||||
@@ -354,7 +359,7 @@ public class Loader_1_20_5 implements Loader {
|
||||
|
||||
private static class Register1_19_3 {
|
||||
|
||||
public static final Map<TabList.Action, EnumSet<ClientboundPlayerInfoUpdatePacket.Action>> actionMap = createActionMap();
|
||||
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()));
|
||||
@@ -366,6 +371,7 @@ public class Loader_1_20_5 implements Loader {
|
||||
actions.put(TabList.Action.UPDATE_GAME_MODE, EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE));
|
||||
actions.put(TabList.Action.UPDATE_DISPLAY_NAME, EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME));
|
||||
actions.put(TabList.Action.UPDATE_LATENCY, EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY));
|
||||
actions.put(TabList.Action.UPDATE_LISTED, EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LISTED));
|
||||
return actions;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
"1.17.1",
|
||||
"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", "1.20.1", "1.20.2", "1.20.3", "1.20.4", "1.20.5", "1.20.6",
|
||||
"1.21-alpha.24.19.a"
|
||||
]
|
||||
},
|
||||
"recommends": {
|
||||
|
||||
@@ -15,6 +15,11 @@ accessible field net/minecraft/network/protocol/game/ClientboundSetDisplayObject
|
||||
# Style constructor (1.16+)
|
||||
accessible method net/minecraft/network/chat/Style <init> (Lnet/minecraft/network/chat/TextColor;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Lnet/minecraft/network/chat/ClickEvent;Lnet/minecraft/network/chat/HoverEvent;Ljava/lang/String;Lnet/minecraft/resources/ResourceLocation;)V
|
||||
|
||||
# Team packet (1.17+)
|
||||
accessible field net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket method I
|
||||
accessible field net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket players Ljava/util/Collection;
|
||||
mutable field net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket players Ljava/util/Collection;
|
||||
|
||||
# Logger (1.18.2+)
|
||||
accessible field net/minecraft/server/MinecraftServer LOGGER Lorg/slf4j/Logger;
|
||||
|
||||
|
||||
+18
-43
@@ -5,6 +5,7 @@ import com.mojang.authlib.properties.Property;
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import me.neznamy.tab.platforms.fabric.FabricScoreboard;
|
||||
import me.neznamy.tab.platforms.fabric.FabricTabList;
|
||||
import me.neznamy.tab.platforms.fabric.FabricTabPlayer;
|
||||
import me.neznamy.tab.shared.ProtocolVersion;
|
||||
@@ -13,6 +14,7 @@ import me.neznamy.tab.shared.backend.EntityData;
|
||||
import me.neznamy.tab.shared.backend.Location;
|
||||
import me.neznamy.tab.shared.chat.ChatModifier;
|
||||
import me.neznamy.tab.shared.chat.TabComponent;
|
||||
import me.neznamy.tab.shared.platform.Scoreboard;
|
||||
import me.neznamy.tab.shared.platform.TabList;
|
||||
import me.neznamy.tab.shared.platform.TabPlayer;
|
||||
import me.neznamy.tab.shared.util.ReflectionUtils;
|
||||
@@ -42,7 +44,6 @@ import net.minecraft.world.scores.criteria.ObjectiveCriteria.RenderType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
|
||||
@@ -51,29 +52,13 @@ import java.util.*;
|
||||
*/
|
||||
@SuppressWarnings({
|
||||
"unchecked", // Java generic types
|
||||
"unused", // Actually used, just via reflection
|
||||
"rawtypes" // raw enums
|
||||
"unused" // Actually used, just via reflection
|
||||
})
|
||||
@RequiredArgsConstructor
|
||||
public class Loader_1_14_4 implements Loader {
|
||||
|
||||
private final ProtocolVersion serverVersion;
|
||||
private ArmorStand dummyEntity;
|
||||
private Class<Enum> tablistActionClass;
|
||||
|
||||
@SneakyThrows
|
||||
private ClientboundPlayerInfoPacket createInfoPacket(@NotNull ProtocolVersion serverVersion, @NotNull TabList.Action action) {
|
||||
if (tablistActionClass == null) {
|
||||
if (serverVersion.getMinorVersion() >= 17) {
|
||||
tablistActionClass = (Class<Enum>) Class.forName("net.minecraft.class_2703$class_5893");
|
||||
} else {
|
||||
tablistActionClass = (Class<Enum>) Class.forName("net.minecraft.class_2703$class_2704");
|
||||
}
|
||||
}
|
||||
Class<?> classType = serverVersion.getMinorVersion() >= 17 ? Collection.class : Iterable.class;
|
||||
return ClientboundPlayerInfoPacket.class.getConstructor(tablistActionClass, classType)
|
||||
.newInstance(Enum.valueOf(tablistActionClass, action.name()), Collections.emptyList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
@@ -158,8 +143,16 @@ public class Loader_1_14_4 implements Loader {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTeamPacket(@NotNull Packet<?> packet) {
|
||||
return packet instanceof ClientboundSetPlayerTeamPacket;
|
||||
@SneakyThrows
|
||||
public void checkTeamPacket(@NotNull Packet<?> packet, @NotNull FabricScoreboard scoreboard) {
|
||||
if (packet instanceof ClientboundSetPlayerTeamPacket) {
|
||||
int action = ReflectionUtils.getInstanceFields(packet.getClass(), int.class).get(0).getInt(packet);
|
||||
if (action == Scoreboard.TeamAction.REMOVE || action == Scoreboard.TeamAction.UPDATE) return;
|
||||
Field playersField = ReflectionUtils.getFields(packet.getClass(), Collection.class).get(0);
|
||||
Collection<String> players = (Collection<String>) playersField.get(packet);
|
||||
String teamName = String.valueOf(ReflectionUtils.getFields(packet.getClass(), String.class).get(0).get(packet));
|
||||
playersField.set(packet, scoreboard.onTeamPacket(action, teamName, players));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -198,7 +191,7 @@ public class Loader_1_14_4 implements Loader {
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void onPlayerInfo(@NotNull TabPlayer receiver, @NotNull Object packet) {
|
||||
Enum action = (Enum) ReflectionUtils.getFields(packet.getClass(), tablistActionClass).get(0).get(packet);
|
||||
ClientboundPlayerInfoPacket.Action action = (ClientboundPlayerInfoPacket.Action) ReflectionUtils.getFields(packet.getClass(), ClientboundPlayerInfoPacket.Action.class).get(0).get(packet);
|
||||
List<PlayerUpdate> players = (List<PlayerUpdate>) ReflectionUtils.getFields(packet.getClass(), List.class).get(0).get(packet);
|
||||
for (PlayerUpdate nmsData : players) {
|
||||
GameProfile profile = nmsData.getProfile();
|
||||
@@ -221,30 +214,12 @@ public class Loader_1_14_4 implements Loader {
|
||||
@NotNull
|
||||
@SneakyThrows
|
||||
public Packet<?> buildTabListPacket(TabList.@NotNull Action action, @NotNull FabricTabList.Builder entry) {
|
||||
ClientboundPlayerInfoPacket packet = createInfoPacket(serverVersion, action);
|
||||
ReflectionUtils.getFields(ClientboundPlayerInfoPacket.class, List.class).get(0).set(packet, Collections.singletonList(createUpdate(serverVersion, entry)));
|
||||
ClientboundPlayerInfoPacket packet = new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.valueOf(action.name()));
|
||||
ReflectionUtils.getFields(ClientboundPlayerInfoPacket.class, List.class).get(0).set(packet, Collections.singletonList(
|
||||
packet.new PlayerUpdate(entry.createProfile(), entry.getLatency(), GameType.byId(entry.getGameMode()), entry.getDisplayName())));
|
||||
return packet;
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@SuppressWarnings("unchecked")
|
||||
private PlayerUpdate createUpdate(@NotNull ProtocolVersion serverVersion, @NotNull FabricTabList.Builder entry) {
|
||||
Constructor<PlayerUpdate> constructor = (Constructor<PlayerUpdate>) PlayerUpdate.class.getConstructors()[0];
|
||||
if (serverVersion.getMinorVersion() >= 19) {
|
||||
// 1.19 - 1.19.2
|
||||
return constructor.newInstance(
|
||||
entry.createProfile(), entry.getLatency(), GameType.byId(entry.getGameMode()), entry.getDisplayName(), null);
|
||||
} else if (serverVersion.getMinorVersion() >= 17) {
|
||||
// 1.17 - 1.18.2
|
||||
return constructor.newInstance(
|
||||
entry.createProfile(), entry.getLatency(), GameType.byId(entry.getGameMode()), entry.getDisplayName());
|
||||
} else {
|
||||
// 1.14 - 1.16.5
|
||||
return constructor.newInstance(new ClientboundPlayerInfoPacket(null, Collections.emptyList()),
|
||||
entry.createProfile(), entry.getLatency(), GameType.byId(entry.getGameMode()), entry.getDisplayName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBundlePacket(@NotNull Packet<?> packet) {
|
||||
return false;
|
||||
@@ -318,7 +293,7 @@ public class Loader_1_14_4 implements Loader {
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public int[] getDestroyedEntities(Packet<?> destroyPacket) {
|
||||
public int[] getDestroyedEntities(@NotNull Packet<?> destroyPacket) {
|
||||
return (int[]) ReflectionUtils.getOnlyField(destroyPacket.getClass()).get(destroyPacket);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
plugins {
|
||||
id("fabric-loom")
|
||||
}
|
||||
|
||||
repositories {
|
||||
// Gradle doesn't support combining settings and project repositories, so we have to re-declare all the settings repos we need
|
||||
maven("https://jitpack.io") // YamlAssist
|
||||
maven("https://repo.opencollab.dev/maven-snapshots/")
|
||||
maven("https://repo.viaversion.com/")
|
||||
maven("https://oss.sonatype.org/content/repositories/snapshots")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(projects.fabric)
|
||||
minecraft("com.mojang:minecraft:1.18.2")
|
||||
mappings(loom.officialMojangMappings())
|
||||
modImplementation("net.fabricmc:fabric-loader:0.15.9") // Not required, but causes warn if not present
|
||||
}
|
||||
|
||||
tasks {
|
||||
compileJava {
|
||||
options.release.set(17)
|
||||
}
|
||||
}
|
||||
+285
@@ -0,0 +1,285 @@
|
||||
package me.neznamy.tab.platforms.fabric.loader;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import me.neznamy.tab.platforms.fabric.FabricScoreboard;
|
||||
import me.neznamy.tab.platforms.fabric.FabricTabList;
|
||||
import me.neznamy.tab.platforms.fabric.FabricTabPlayer;
|
||||
import me.neznamy.tab.shared.ProtocolVersion;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.backend.EntityData;
|
||||
import me.neznamy.tab.shared.backend.Location;
|
||||
import me.neznamy.tab.shared.chat.ChatModifier;
|
||||
import me.neznamy.tab.shared.chat.TabComponent;
|
||||
import me.neznamy.tab.shared.platform.TabList;
|
||||
import me.neznamy.tab.shared.platform.TabPlayer;
|
||||
import me.neznamy.tab.shared.util.ReflectionUtils;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.network.chat.BaseComponent;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.Style;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.protocol.game.ClientGamePacketListener;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoPacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoPacket.PlayerUpdate;
|
||||
import net.minecraft.network.protocol.game.ClientboundSetDisplayObjectivePacket;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.level.GameType;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.scores.Objective;
|
||||
import net.minecraft.world.scores.PlayerTeam;
|
||||
import net.minecraft.world.scores.criteria.ObjectiveCriteria;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Method loader compiled using Minecraft containing method implementations from 1.17 - 1.18.2.
|
||||
*/
|
||||
@SuppressWarnings("unused") // Actually used, just via reflection
|
||||
@RequiredArgsConstructor
|
||||
public class Loader_1_18_2 implements Loader {
|
||||
|
||||
private final ProtocolVersion serverVersion;
|
||||
|
||||
@Override
|
||||
public void sendMessage(@NotNull ServerPlayer player, @NotNull Component message) {
|
||||
player.sendMessage(message, new UUID(0, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStyle(@NotNull Component component, @NotNull Style style) {
|
||||
((BaseComponent)component).setStyle(style);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
@SneakyThrows
|
||||
public Packet<?> buildTabListPacket(@NotNull TabList.Action action, @NotNull FabricTabList.Builder entry) {
|
||||
PlayerUpdate update;
|
||||
if (serverVersion.getMinorVersion() >= 19) {
|
||||
// 1.19 - 1.19.2
|
||||
update = (PlayerUpdate) PlayerUpdate.class.getConstructors()[0].newInstance(
|
||||
entry.createProfile(), entry.getLatency(), GameType.byId(entry.getGameMode()), entry.getDisplayName(), null);
|
||||
} else {
|
||||
update = new PlayerUpdate(entry.createProfile(), entry.getLatency(), GameType.byId(entry.getGameMode()), entry.getDisplayName());
|
||||
}
|
||||
ClientboundPlayerInfoPacket packet = new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.valueOf(action.name()));
|
||||
ReflectionUtils.getFields(ClientboundPlayerInfoPacket.class, List.class).get(0).set(packet, Collections.singletonList(update));
|
||||
return packet;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
@SuppressWarnings("unchecked")
|
||||
public void onPlayerInfo(@NotNull TabPlayer receiver, @NotNull Object packet) {
|
||||
ClientboundPlayerInfoPacket.Action action = (ClientboundPlayerInfoPacket.Action) ReflectionUtils.getFields(packet.getClass(), ClientboundPlayerInfoPacket.Action.class).get(0).get(packet);
|
||||
List<PlayerUpdate> players = (List<PlayerUpdate>) ReflectionUtils.getFields(packet.getClass(), List.class).get(0).get(packet);
|
||||
for (PlayerUpdate nmsData : players) {
|
||||
GameProfile profile = nmsData.getProfile();
|
||||
Field displayNameField = ReflectionUtils.getFields(PlayerUpdate.class, Component.class).get(0);
|
||||
Field latencyField = ReflectionUtils.getFields(PlayerUpdate.class, int.class).get(0);
|
||||
if (action.name().equals(TabList.Action.UPDATE_DISPLAY_NAME.name()) || action.name().equals(TabList.Action.ADD_PLAYER.name())) {
|
||||
Object expectedName = ((FabricTabPlayer)receiver).getTabList().getExpectedDisplayName(profile.getId());
|
||||
if (expectedName != null) displayNameField.set(nmsData, expectedName);
|
||||
}
|
||||
if (action.name().equals(TabList.Action.UPDATE_LATENCY.name()) || action.name().equals(TabList.Action.ADD_PLAYER.name())) {
|
||||
latencyField.set(nmsData, TAB.getInstance().getFeatureManager().onLatencyChange(receiver, profile.getId(), latencyField.getInt(nmsData)));
|
||||
}
|
||||
if (action.name().equals(TabList.Action.ADD_PLAYER.name())) {
|
||||
TAB.getInstance().getFeatureManager().onEntryAdd(receiver, profile.getId(), profile.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getLevelName(@NotNull Level level) {
|
||||
throw new UnsupportedOperationException("Not implemented in this submodule");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public TabList.Skin propertyToSkin(@NotNull Property property) {
|
||||
throw new UnsupportedOperationException("Not implemented in this submodule");
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Component newTextComponent(@NotNull String text) {
|
||||
throw new UnsupportedOperationException("Not implemented in this submodule");
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Style convertModifier(@NotNull ChatModifier modifier, boolean modern) {
|
||||
throw new UnsupportedOperationException("Not implemented in this submodule");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSibling(@NotNull Component parent, @NotNull Component child) {
|
||||
throw new UnsupportedOperationException("Not implemented in this submodule");
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Packet<?> registerTeam(@NotNull PlayerTeam team) {
|
||||
throw new UnsupportedOperationException("Not implemented in this submodule");
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Packet<?> unregisterTeam(@NotNull PlayerTeam team) {
|
||||
throw new UnsupportedOperationException("Not implemented in this submodule");
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Packet<?> updateTeam(@NotNull PlayerTeam team) {
|
||||
throw new UnsupportedOperationException("Not implemented in this submodule");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSneaking(@NotNull ServerPlayer player) {
|
||||
throw new UnsupportedOperationException("Not implemented in this submodule");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(@NotNull CommandSourceStack source, @NotNull Component message) {
|
||||
throw new UnsupportedOperationException("Not implemented in this submodule");
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Packet<?> newHeaderFooter(@NotNull Component header, @NotNull Component footer) {
|
||||
throw new UnsupportedOperationException("Not implemented in this submodule");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkTeamPacket(@NotNull Packet<?> packet, @NotNull FabricScoreboard scoreboard) {
|
||||
throw new UnsupportedOperationException("Not implemented in this submodule");
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Packet<ClientGamePacketListener> spawnEntity(@NotNull Level level, int id, @NotNull UUID uuid, @NotNull Object type, @NotNull Location location) {
|
||||
throw new UnsupportedOperationException("Not implemented in this submodule");
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Packet<ClientGamePacketListener> newEntityMetadata(int entityId, @NotNull EntityData data) {
|
||||
throw new UnsupportedOperationException("Not implemented in this submodule");
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public EntityData createDataWatcher(@NotNull TabPlayer viewer, byte flags, @NotNull String displayName, boolean nameVisible, int markerPosition) {
|
||||
throw new UnsupportedOperationException("Not implemented in this submodule");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPlayerInfo(@NotNull Packet<?> packet) {
|
||||
throw new UnsupportedOperationException("Not implemented in this submodule");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBundlePacket(@NotNull Packet<?> packet) {
|
||||
throw new UnsupportedOperationException("Not implemented in this submodule");
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Iterable<Object> getBundledPackets(@NotNull Packet<?> bundlePacket) {
|
||||
throw new UnsupportedOperationException("Not implemented in this submodule");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPackets(@NotNull ServerPlayer player, @NotNull Iterable<Packet<ClientGamePacketListener>> packets) {
|
||||
throw new UnsupportedOperationException("Not implemented in this submodule");
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Level getLevel(@NotNull ServerPlayer player) {
|
||||
throw new UnsupportedOperationException("Not implemented in this submodule");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSpawnPlayerPacket(@NotNull Packet<?> packet) {
|
||||
throw new UnsupportedOperationException("Not implemented in this submodule");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSpawnedPlayerId(@NotNull Packet<?> packet) {
|
||||
throw new UnsupportedOperationException("Not implemented in this submodule");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPing(@NotNull ServerPlayer player) {
|
||||
throw new UnsupportedOperationException("Not implemented in this submodule");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDisplaySlot(@NotNull ClientboundSetDisplayObjectivePacket packet) {
|
||||
throw new UnsupportedOperationException("Not implemented in this submodule");
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Packet<?> setDisplaySlot(int slot, @NotNull Objective objective) {
|
||||
throw new UnsupportedOperationException("Not implemented in this submodule");
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Channel getChannel(@NotNull ServerPlayer player) {
|
||||
throw new UnsupportedOperationException("Not implemented in this submodule");
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getMSPT(@NotNull MinecraftServer server) {
|
||||
throw new UnsupportedOperationException("Not implemented in this submodule");
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Packet<?> removeScore(@NotNull String objective, @NotNull String holder) {
|
||||
throw new UnsupportedOperationException("Not implemented in this submodule");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getDestroyedEntities(@NotNull Packet<?> destroyPacket) {
|
||||
throw new UnsupportedOperationException("Not implemented in this submodule");
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Objective newObjective(@NotNull String name, @NotNull Component displayName, ObjectiveCriteria.@NotNull RenderType renderType, @Nullable Component numberFormat) {
|
||||
throw new UnsupportedOperationException("Not implemented in this submodule");
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Packet<?> setScore(@NotNull String objective, @NotNull String holder, int score, @Nullable Component displayName, @Nullable Component numberFormat) {
|
||||
throw new UnsupportedOperationException("Not implemented in this submodule");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logInfo(@NotNull TabComponent message) {
|
||||
throw new UnsupportedOperationException("Not implemented in this submodule");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logWarn(@NotNull TabComponent message) {
|
||||
throw new UnsupportedOperationException("Not implemented in this submodule");
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,8 @@ val platforms = setOf(
|
||||
|
||||
val fabrics = setOf(
|
||||
rootProject.projects.fabric,
|
||||
rootProject.projects.fabric.v1144
|
||||
rootProject.projects.fabric.v1144,
|
||||
rootProject.projects.fabric.v1182
|
||||
).map { it.dependencyProject }
|
||||
|
||||
tasks {
|
||||
|
||||
@@ -35,4 +35,5 @@ include(":sponge7")
|
||||
include(":sponge8")
|
||||
include(":fabric")
|
||||
include(":fabric:v1_14_4")
|
||||
include(":fabric:v1_18_2")
|
||||
include(":jar")
|
||||
@@ -5,7 +5,7 @@ plugins {
|
||||
dependencies {
|
||||
api(projects.api)
|
||||
api("org.yaml:snakeyaml:2.0")
|
||||
api("com.github.NEZNAMY:yamlassist:1.0.5")
|
||||
api("com.github.NEZNAMY:yamlassist:1.0.8")
|
||||
api("com.googlecode.json-simple:json-simple:1.1.1") {
|
||||
exclude("junit", "junit")
|
||||
}
|
||||
|
||||
@@ -227,20 +227,6 @@ public class ErrorManager {
|
||||
t, true, errorLog);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints error message when attempting to send plugin message to player
|
||||
* who is not connected to any server.
|
||||
*
|
||||
* @param player
|
||||
* Player message was attempted to be sent to
|
||||
* @param message
|
||||
* Message that failed to deliver
|
||||
*/
|
||||
public void noServerPluginMessage(@NotNull TabPlayer player, byte[] message) {
|
||||
printError("Skipped plugin message send to " + player.getName() + ", because player is not " +
|
||||
"connected to any server (message=" + new String(message) + ")", Collections.emptyList(), false, errorLog);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints error message when RedidSupport received message with unknown action.
|
||||
*
|
||||
@@ -292,18 +278,6 @@ public class ErrorManager {
|
||||
t, true, errorLog);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints warn if player is not in plugin's scoreboard.
|
||||
*
|
||||
* @param player
|
||||
* Player who was in the wrong scoreboard
|
||||
*/
|
||||
public void playerInWrongScoreboard(@NotNull TabPlayer player) {
|
||||
printError("Player " + player.getName() + " was in a different scoreboard " +
|
||||
"than expected. This means another plugin changed player's scoreboard.",
|
||||
Collections.emptyList(), false, errorLog);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints error message if armor stand manager of player is unexpectedly {@code null}.
|
||||
*
|
||||
|
||||
@@ -75,6 +75,9 @@ public class FeatureManager {
|
||||
((UnLoadable) f).unload();
|
||||
TAB.getInstance().debug("Feature " + f.getClass().getSimpleName() + " processed unload in " + (System.currentTimeMillis()-time) + "ms");
|
||||
}
|
||||
for (TabFeature f : values) {
|
||||
f.deactivate();
|
||||
}
|
||||
TAB.getInstance().getPlaceholderManager().getTabExpansion().unregisterExpansion();
|
||||
if (TAB.getInstance().getPlatform() instanceof ProxyPlatform) {
|
||||
for (TabPlayer player : TAB.getInstance().getOnlinePlayers()) {
|
||||
|
||||
@@ -11,6 +11,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
public enum ProtocolVersion {
|
||||
|
||||
UNKNOWN,
|
||||
V1_20_6 (766),
|
||||
V1_20_5 (766),
|
||||
V1_20_4 (765),
|
||||
V1_20_3 (765),
|
||||
@@ -76,8 +77,11 @@ public enum ProtocolVersion {
|
||||
V1_4_7 (51),
|
||||
V1_4_6 (51);
|
||||
|
||||
/** Array to iterate over to prevent new array creation each time */
|
||||
private static final ProtocolVersion[] VALUES = values();
|
||||
|
||||
/** Newest MC version this plugin jar knows */
|
||||
public static final ProtocolVersion LATEST_KNOWN_VERSION = V1_20_5;
|
||||
public static final ProtocolVersion LATEST_KNOWN_VERSION = V1_20_6;
|
||||
|
||||
/** Version's network id found at <a href="https://wiki.vg/Protocol_version_numbers">wiki.vg</a> */
|
||||
private final int networkId;
|
||||
@@ -146,7 +150,7 @@ public enum ProtocolVersion {
|
||||
* @return version from given network id
|
||||
*/
|
||||
public static @NotNull ProtocolVersion fromNetworkId(int networkId) {
|
||||
for (ProtocolVersion v : values()) {
|
||||
for (ProtocolVersion v : VALUES) {
|
||||
if (networkId == v.networkId) return v;
|
||||
}
|
||||
return UNKNOWN;
|
||||
|
||||
+1
-1
@@ -133,7 +133,7 @@ public class ArmorStand {
|
||||
if (manager.isArmorStandsAlwaysVisible()) return true;
|
||||
if (owner.isDisguised() || manager.isOnBoat(owner)) return false;
|
||||
return owner.getGamemode() != 3 && !manager.hasHiddenNameTag(owner) && !property.get().isEmpty() &&
|
||||
!manager.getUnlimitedDisableChecker().isDisabledPlayer(owner);
|
||||
!owner.disabledUnlimitedNametags.get();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+5
-7
@@ -45,9 +45,8 @@ public abstract class BackendNameTagX extends NameTagX implements GameModeListen
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public BackendArmorStandManager getArmorStandManager(@NotNull TabPlayer player) {
|
||||
return (BackendArmorStandManager) armorStandManagerMap.get(player);
|
||||
return (BackendArmorStandManager) player.unlimitedNametagData.armorStandManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -80,7 +79,7 @@ public abstract class BackendNameTagX extends NameTagX implements GameModeListen
|
||||
|
||||
@Override
|
||||
public boolean isOnBoat(@NotNull TabPlayer player) {
|
||||
return vehicleManager != null && vehicleManager.isOnBoat(player);
|
||||
return player.unlimitedNametagData.onBoat;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,8 +106,7 @@ public abstract class BackendNameTagX extends NameTagX implements GameModeListen
|
||||
for (TabPlayer all : TAB.getInstance().getOnlinePlayers()) {
|
||||
getArmorStandManager(all).unregisterPlayer((BackendTabPlayer) disconnectedPlayer);
|
||||
}
|
||||
armorStandManagerMap.get(disconnectedPlayer).destroy();
|
||||
armorStandManagerMap.remove(disconnectedPlayer); // WeakHashMap doesn't clear this due to value referencing the key
|
||||
disconnectedPlayer.unlimitedNametagData.armorStandManager.destroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -144,7 +142,7 @@ public abstract class BackendNameTagX extends NameTagX implements GameModeListen
|
||||
public void onWorldChange(@NotNull TabPlayer p, @NotNull String from, @NotNull String to) {
|
||||
super.onWorldChange(p, from, to);
|
||||
BackendArmorStandManager asm = getArmorStandManager(p);
|
||||
if (isPreviewingNameTag(p)) {
|
||||
if (p.unlimitedNametagData.previewing) {
|
||||
asm.spawn((BackendTabPlayer) p);
|
||||
}
|
||||
//for some reason this is needed for some users
|
||||
@@ -167,7 +165,7 @@ public abstract class BackendNameTagX extends NameTagX implements GameModeListen
|
||||
@Override
|
||||
public void onPacketSend(@NotNull TabPlayer receiver, @NotNull Object packet) {
|
||||
if (receiver.getVersion().getMinorVersion() < 8) return;
|
||||
if (!receiver.isLoaded() || getDisableChecker().isDisabledPlayer(receiver) || getUnlimitedDisableChecker().isDisabledPlayer(receiver)) return;
|
||||
if (!receiver.isLoaded() || receiver.disabledNametags.get() || receiver.disabledUnlimitedNametags.get()) return;
|
||||
packetListener.onPacketSend((BackendTabPlayer) receiver, packet);
|
||||
}
|
||||
|
||||
|
||||
+5
-19
@@ -34,9 +34,6 @@ public class VehicleRefresher extends TabFeature implements JoinListener, QuitLi
|
||||
@Getter
|
||||
private final Map<Integer, List<Integer>> vehicles = new ConcurrentHashMap<>();
|
||||
|
||||
/** set of players currently on boats */
|
||||
private final Set<TabPlayer> playersOnBoats = Collections.newSetFromMap(new WeakHashMap<>());
|
||||
|
||||
/** Reference to the main feature */
|
||||
private final BackendNameTagX feature;
|
||||
|
||||
@@ -48,7 +45,7 @@ public class VehicleRefresher extends TabFeature implements JoinListener, QuitLi
|
||||
feature.getArmorStandManager(inVehicle).teleport();
|
||||
}
|
||||
for (TabPlayer p : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (feature.isPreviewingNameTag(p)) {
|
||||
if (p.unlimitedNametagData.previewing) {
|
||||
feature.getArmorStandManager(p).teleport((BackendTabPlayer) p);
|
||||
}
|
||||
}
|
||||
@@ -65,7 +62,7 @@ public class VehicleRefresher extends TabFeature implements JoinListener, QuitLi
|
||||
updateVehicle(vehicle);
|
||||
addToVehicle(p, vehicle);
|
||||
if (feature.isDisableOnBoats() && feature.getEntityType(vehicle).contains("boat")) {
|
||||
playersOnBoats.add(p);
|
||||
p.unlimitedNametagData.onBoat = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -95,8 +92,8 @@ public class VehicleRefresher extends TabFeature implements JoinListener, QuitLi
|
||||
vehicles.remove(feature.getEntityId(playersInVehicle.remove(p)));
|
||||
feature.getArmorStandManager(p).teleport();
|
||||
playersInVehicleArray = playersInVehicle.keySet().toArray(new TabPlayer[0]);
|
||||
if (feature.isDisableOnBoats() && playersOnBoats.contains(p)) {
|
||||
playersOnBoats.remove(p);
|
||||
if (feature.isDisableOnBoats() && p.unlimitedNametagData.onBoat) {
|
||||
p.unlimitedNametagData.onBoat = false;
|
||||
feature.updateTeamData(p);
|
||||
}
|
||||
feature.getArmorStandManager(p).updateVisibility(true);
|
||||
@@ -107,7 +104,7 @@ public class VehicleRefresher extends TabFeature implements JoinListener, QuitLi
|
||||
feature.getArmorStandManager(p).respawn(); //making teleport instant instead of showing teleport animation
|
||||
addToVehicle(p, vehicle);
|
||||
if (feature.isDisableOnBoats() && feature.getEntityType(vehicle).contains("boat")) {
|
||||
playersOnBoats.add(p);
|
||||
p.unlimitedNametagData.onBoat = true;
|
||||
feature.updateTeamData(p);
|
||||
}
|
||||
feature.getArmorStandManager(p).updateVisibility(true);
|
||||
@@ -125,17 +122,6 @@ public class VehicleRefresher extends TabFeature implements JoinListener, QuitLi
|
||||
playersInVehicleArray = playersInVehicle.keySet().toArray(new TabPlayer[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the player is in a boat, {@code false} if not
|
||||
*
|
||||
* @param p
|
||||
* Player to check
|
||||
* @return {@code true} if in a boat, {@code false} if not
|
||||
*/
|
||||
public boolean isOnBoat(@NotNull TabPlayer p) {
|
||||
return playersOnBoats.contains(p);
|
||||
}
|
||||
|
||||
private void updateVehicle(Object vehicle) {
|
||||
feature.runInEntityScheduler(vehicle, () -> vehicles.put(feature.getEntityId(vehicle), feature.getPassengers(vehicle)));
|
||||
}
|
||||
|
||||
@@ -11,18 +11,18 @@ public class ChatModifier {
|
||||
@Nullable private TextColor color;
|
||||
private boolean bold;
|
||||
private boolean italic;
|
||||
private boolean underlined;
|
||||
private boolean strikethrough;
|
||||
private boolean obfuscated;
|
||||
private boolean strikethrough;
|
||||
private boolean underlined;
|
||||
@Nullable private String font;
|
||||
|
||||
public ChatModifier(@NotNull ChatModifier modifier) {
|
||||
color = modifier.color;
|
||||
bold = modifier.bold;
|
||||
italic = modifier.italic;
|
||||
underlined = modifier.underlined;
|
||||
strikethrough = modifier.strikethrough;
|
||||
obfuscated = modifier.obfuscated;
|
||||
strikethrough = modifier.strikethrough;
|
||||
underlined = modifier.underlined;
|
||||
font = modifier.font;
|
||||
}
|
||||
|
||||
@@ -37,18 +37,24 @@ public class ChatModifier {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (bold) builder.append(EnumChatFormat.BOLD);
|
||||
if (italic) builder.append(EnumChatFormat.ITALIC);
|
||||
if (underlined) builder.append(EnumChatFormat.UNDERLINE);
|
||||
if (strikethrough) builder.append(EnumChatFormat.STRIKETHROUGH);
|
||||
if (obfuscated) builder.append(EnumChatFormat.OBFUSCATED);
|
||||
if (strikethrough) builder.append(EnumChatFormat.STRIKETHROUGH);
|
||||
if (underlined) builder.append(EnumChatFormat.UNDERLINE);
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this modifier has any magic codes, {@code false} if not.
|
||||
* Returns bitmask of magic codes.
|
||||
*
|
||||
* @return {@code true} if this modifier has any magic codes, {@code false} if not
|
||||
* @return Bitmask of magic codes
|
||||
*/
|
||||
public boolean hasMagicCodes() {
|
||||
return bold || italic || underlined || strikethrough || obfuscated;
|
||||
public int getMagicCodeBitMask() {
|
||||
int mask = 0;
|
||||
if (bold) mask += 1;
|
||||
if (italic) mask += 2;
|
||||
if (obfuscated) mask += 4;
|
||||
if (strikethrough) mask += 8;
|
||||
if (underlined) mask += 16;
|
||||
return mask;
|
||||
}
|
||||
}
|
||||
@@ -213,8 +213,8 @@ public abstract class TabComponent {
|
||||
* @return {@code true} if valid, {@code false} if not
|
||||
*/
|
||||
private static boolean isHexCode(@NotNull String string) {
|
||||
for (char c : string.toCharArray()) {
|
||||
if ("0123456789AaBbCcDdEeFf".indexOf(c) == -1) return false;
|
||||
for (int i=0; i<string.length(); i++) {
|
||||
if ("0123456789AaBbCcDdEeFf".indexOf(string.charAt(i)) == -1) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -39,7 +39,8 @@ public class RGBUtils {
|
||||
*/
|
||||
public RGBUtils() {
|
||||
List<RGBFormatter> list = new ArrayList<>();
|
||||
if (ReflectionUtils.classExists("net.kyori.adventure.text.minimessage.MiniMessage")) {
|
||||
if (ReflectionUtils.classExists("net.kyori.adventure.text.minimessage.MiniMessage") &&
|
||||
ReflectionUtils.classExists("net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer")) {
|
||||
list.add(new MiniMessageFormat());
|
||||
}
|
||||
list.add(new BukkitFormat());
|
||||
|
||||
@@ -12,7 +12,6 @@ import me.neznamy.tab.shared.config.file.ConfigurationFile;
|
||||
import me.neznamy.tab.shared.Property;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.TabConstants;
|
||||
import me.neznamy.tab.shared.features.PlayerList;
|
||||
import me.neznamy.tab.shared.features.sorting.Sorting;
|
||||
import me.neznamy.tab.shared.proxy.ProxyTabPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -83,20 +82,17 @@ public class DebugCommand extends SubCommand {
|
||||
sendMessage(sender, getTeamName(analyzed));
|
||||
sendMessage(sender, getTeamNameNote(analyzed));
|
||||
if (tab.getFeatureManager().isFeatureEnabled(TabConstants.Feature.PLAYER_LIST)) {
|
||||
PlayerList playerlist = tab.getFeatureManager().getFeature(TabConstants.Feature.PLAYER_LIST);
|
||||
boolean disabledPlayerlist = playerlist.getDisableChecker().isDisabledPlayer(analyzed);
|
||||
showProperty(sender, analyzed, TabConstants.Property.TABPREFIX, disabledPlayerlist);
|
||||
showProperty(sender, analyzed, TabConstants.Property.TABSUFFIX, disabledPlayerlist);
|
||||
showProperty(sender, analyzed, TabConstants.Property.CUSTOMTABNAME, disabledPlayerlist);
|
||||
showProperty(sender, analyzed, TabConstants.Property.TABPREFIX, analyzed.disabledPlayerList.get());
|
||||
showProperty(sender, analyzed, TabConstants.Property.TABSUFFIX, analyzed.disabledPlayerList.get());
|
||||
showProperty(sender, analyzed, TabConstants.Property.CUSTOMTABNAME, analyzed.disabledPlayerList.get());
|
||||
} else {
|
||||
sendMessage(sender, "&atabprefix: &cDisabled");
|
||||
sendMessage(sender, "&atabsuffix: &cDisabled");
|
||||
sendMessage(sender, "&acustomtabname: &cDisabled");
|
||||
}
|
||||
if (tab.getNameTagManager() != null) {
|
||||
boolean disabledNametags = tab.getNameTagManager().getDisableChecker().isDisabledPlayer(analyzed);
|
||||
showProperty(sender, analyzed, TabConstants.Property.TAGPREFIX, disabledNametags);
|
||||
showProperty(sender, analyzed, TabConstants.Property.TAGSUFFIX, disabledNametags);
|
||||
showProperty(sender, analyzed, TabConstants.Property.TAGPREFIX, analyzed.disabledNametags.get());
|
||||
showProperty(sender, analyzed, TabConstants.Property.TAGSUFFIX, analyzed.disabledNametags.get());
|
||||
NameTagX nameTagX = TAB.getInstance().getFeatureManager().getFeature(TabConstants.Feature.UNLIMITED_NAME_TAGS);
|
||||
if (nameTagX != null) {
|
||||
boolean disabledUnlimited = nameTagX.isPlayerDisabled(analyzed);
|
||||
@@ -162,12 +158,11 @@ public class DebugCommand extends SubCommand {
|
||||
private @NotNull String getTeamName(@NotNull TabPlayer analyzed) {
|
||||
Sorting sorting = TAB.getInstance().getFeatureManager().getFeature(TabConstants.Feature.SORTING);
|
||||
if (sorting == null) return "";
|
||||
if (TAB.getInstance().getNameTagManager() != null &&
|
||||
TAB.getInstance().getNameTagManager().getDisableChecker().isDisabledPlayer(analyzed)) {
|
||||
if (TAB.getInstance().getNameTagManager() != null && analyzed.disabledNametags.get()) {
|
||||
return "&eTeam name: &cSorting is disabled in player's world/server";
|
||||
}
|
||||
return "&eTeam name: &a" + (TAB.getInstance().getFeatureManager().isFeatureEnabled(TabConstants.Feature.LAYOUT)
|
||||
? sorting.getFullTeamName(analyzed) : sorting.getShortTeamName(analyzed));
|
||||
? analyzed.sortingData.fullTeamName : analyzed.sortingData.getShortTeamName());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -178,13 +173,11 @@ public class DebugCommand extends SubCommand {
|
||||
* @return team name note of specified player
|
||||
*/
|
||||
private @NotNull String getTeamNameNote(@NotNull TabPlayer analyzed) {
|
||||
Sorting sorting = TAB.getInstance().getFeatureManager().getFeature(TabConstants.Feature.SORTING);
|
||||
if (sorting == null) return "";
|
||||
if (TAB.getInstance().getNameTagManager() != null &&
|
||||
TAB.getInstance().getNameTagManager().getDisableChecker().isDisabledPlayer(analyzed)) {
|
||||
if (analyzed.sortingData == null) return "";
|
||||
if (TAB.getInstance().getNameTagManager() != null && analyzed.disabledNametags.get()) {
|
||||
return "";
|
||||
}
|
||||
return "&eSorting note: &r" + sorting.getTeamNameNote(analyzed);
|
||||
return "&eSorting note: &r" + analyzed.sortingData.teamNameNote;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ public class ScoreboardOffCommand extends SubCommand {
|
||||
return;
|
||||
}
|
||||
boolean silent = args.length == 2 && args[1].equals("-s");
|
||||
if (scoreboard.getOtherPluginScoreboards().containsKey(target)) return; //not overriding other plugins
|
||||
if (target.scoreboardData.otherPluginScoreboard != null) return; //not overriding other plugins
|
||||
scoreboard.setScoreboardVisible(target, false, !silent);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ public class ScoreboardOnCommand extends SubCommand {
|
||||
return;
|
||||
}
|
||||
boolean silent = args.length == 2 && args[1].equals("-s");
|
||||
if (scoreboard.getOtherPluginScoreboards().containsKey(target)) return; //not overriding other plugins
|
||||
if (target.scoreboardData.otherPluginScoreboard != null) return; //not overriding other plugins
|
||||
scoreboard.setScoreboardVisible(target, true, !silent);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ public class ScoreboardToggleCommand extends SubCommand {
|
||||
return;
|
||||
}
|
||||
boolean silent = args.length == 2 && args[1].equals("-s");
|
||||
if (scoreboard.getOtherPluginScoreboards().containsKey(target)) return; //not overriding other plugins
|
||||
if (target.scoreboardData.otherPluginScoreboard != null) return; //not overriding other plugins
|
||||
scoreboard.toggleScoreboard(target, !silent);
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ public class CpuManager {
|
||||
private volatile boolean enabled;
|
||||
|
||||
/** Boolean tracking whether CPU usage should be tracked or not */
|
||||
private boolean trackUsage;
|
||||
@Getter private boolean trackUsage;
|
||||
|
||||
/**
|
||||
* Enables CPU usage tracking and returns {@code true} if it was not enabled previously.
|
||||
@@ -120,6 +120,19 @@ public class CpuManager {
|
||||
placeholderUsageCurrent.computeIfAbsent(placeholder, l -> new AtomicLong()).addAndGet(nanoseconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds placeholder time from given map.
|
||||
*
|
||||
* @param times
|
||||
* How long each placeholder took
|
||||
*/
|
||||
public void addPlaceholderTimes(@NotNull Map<String, Long> times) {
|
||||
if (!trackUsage) return;
|
||||
for (Map.Entry<String, Long> entry : times.entrySet()) {
|
||||
placeholderUsageCurrent.computeIfAbsent(entry.getKey(), l -> new AtomicLong()).addAndGet(entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
public void runMeasuredTask(@NotNull String feature, @NotNull String type, @NotNull Runnable task) {
|
||||
submit(() -> runAndMeasure(task, feature, type));
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ public class BelowName extends TabFeature implements JoinListener, Loadable, UnL
|
||||
*/
|
||||
public BelowName() {
|
||||
Condition disableCondition = Condition.getCondition(config().getString("belowname-objective.disable-condition"));
|
||||
disableChecker = new DisableChecker(getFeatureName(), disableCondition, this::onDisableConditionChange);
|
||||
disableChecker = new DisableChecker(getFeatureName(), disableCondition, this::onDisableConditionChange, p -> p.disabledBelowname);
|
||||
TAB.getInstance().getFeatureManager().registerFeature(TabConstants.Feature.BELOW_NAME + "-Condition", disableChecker);
|
||||
TAB.getInstance().getFeatureManager().registerFeature(TabConstants.Feature.BELOW_NAME_TEXT, textRefresher);
|
||||
TAB.getInstance().getConfigHelper().startup().checkBelowNameText(rawText);
|
||||
@@ -60,7 +60,7 @@ public class BelowName extends TabFeature implements JoinListener, Loadable, UnL
|
||||
loaded.setProperty(textRefresher, TEXT_PROPERTY, rawText);
|
||||
loaded.setProperty(textRefresher, DEFAULT_FORMAT_PROPERTY, fancyDisplayDefault);
|
||||
if (disableChecker.isDisableConditionMet(loaded)) {
|
||||
disableChecker.addDisabledPlayer(loaded);
|
||||
loaded.disabledBelowname.set(true);
|
||||
} else {
|
||||
register(loaded);
|
||||
}
|
||||
@@ -78,7 +78,7 @@ public class BelowName extends TabFeature implements JoinListener, Loadable, UnL
|
||||
@Override
|
||||
public void unload() {
|
||||
for (TabPlayer p : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (disableChecker.isDisabledPlayer(p)) continue;
|
||||
if (p.disabledBelowname.get()) continue;
|
||||
p.getScoreboard().unregisterObjective(OBJECTIVE_NAME);
|
||||
}
|
||||
}
|
||||
@@ -90,7 +90,7 @@ public class BelowName extends TabFeature implements JoinListener, Loadable, UnL
|
||||
connectedPlayer.setProperty(textRefresher, TEXT_PROPERTY, rawText);
|
||||
connectedPlayer.setProperty(textRefresher, DEFAULT_FORMAT_PROPERTY, fancyDisplayDefault);
|
||||
if (disableChecker.isDisableConditionMet(connectedPlayer)) {
|
||||
disableChecker.addDisabledPlayer(connectedPlayer);
|
||||
connectedPlayer.disabledBelowname.set(true);
|
||||
} else {
|
||||
register(connectedPlayer);
|
||||
}
|
||||
@@ -168,7 +168,7 @@ public class BelowName extends TabFeature implements JoinListener, Loadable, UnL
|
||||
|
||||
@Override
|
||||
public void onLoginPacket(@NotNull TabPlayer player) {
|
||||
if (disableChecker.isDisabledPlayer(player) || !player.isLoaded()) return;
|
||||
if (player.disabledBelowname.get() || !player.isLoaded()) return;
|
||||
register(player);
|
||||
for (TabPlayer all : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (!sameServerAndWorld(all, player)) continue;
|
||||
@@ -199,7 +199,7 @@ public class BelowName extends TabFeature implements JoinListener, Loadable, UnL
|
||||
* NumberFormat display of the score
|
||||
*/
|
||||
public void setScore(@NotNull TabPlayer viewer, @NotNull TabPlayer scoreHolder, int value, @NotNull String fancyDisplay) {
|
||||
if (disableChecker.isDisabledPlayer(viewer)) return;
|
||||
if (viewer.disabledBelowname.get()) return;
|
||||
viewer.getScoreboard().setScore(
|
||||
OBJECTIVE_NAME,
|
||||
scoreHolder.getNickname(),
|
||||
@@ -254,7 +254,7 @@ public class BelowName extends TabFeature implements JoinListener, Loadable, UnL
|
||||
|
||||
@Override
|
||||
public void refresh(@NotNull TabPlayer refreshed, boolean force) {
|
||||
if (feature.disableChecker.isDisabledPlayer(refreshed)) return;
|
||||
if (refreshed.disabledBelowname.get()) return;
|
||||
refreshed.getScoreboard().updateObjective(
|
||||
OBJECTIVE_NAME,
|
||||
refreshed.getProperty(feature.TEXT_PROPERTY).updateAndGet(),
|
||||
|
||||
@@ -169,7 +169,7 @@ public class GlobalPlayerList extends TabFeature implements JoinListener, QuitLi
|
||||
@NotNull
|
||||
public TabList.Entry getAddInfoData(@NotNull TabPlayer p, @NotNull TabPlayer viewer) {
|
||||
TabComponent format = null;
|
||||
if (playerlist != null && !playerlist.getDisableChecker().isDisabledPlayer(p)) {
|
||||
if (playerlist != null && !p.disabledPlayerList.get()) {
|
||||
format = playerlist.getTabFormat(p, viewer);
|
||||
}
|
||||
int gameMode = (othersAsSpectators && !p.getServer().equals(viewer.getServer())) ||
|
||||
@@ -178,6 +178,7 @@ public class GlobalPlayerList extends TabFeature implements JoinListener, QuitLi
|
||||
p.getTablistId(),
|
||||
p.getNickname(),
|
||||
p.getSkin(),
|
||||
true,
|
||||
p.getPing(),
|
||||
gameMode,
|
||||
viewer.getVersion().getMinorVersion() >= 8 ? format : null
|
||||
|
||||
@@ -29,7 +29,7 @@ public class HeaderFooter extends TabFeature implements HeaderFooterManager, Joi
|
||||
*/
|
||||
public HeaderFooter() {
|
||||
Condition disableCondition = Condition.getCondition(config().getString("header-footer.disable-condition"));
|
||||
disableChecker = new DisableChecker(getFeatureName(), disableCondition, this::onDisableConditionChange);
|
||||
disableChecker = new DisableChecker(getFeatureName(), disableCondition, this::onDisableConditionChange, p -> p.disabledHeaderFooter);
|
||||
TAB.getInstance().getFeatureManager().registerFeature(TabConstants.Feature.HEADER_FOOTER + "-Condition", disableChecker);
|
||||
TAB.getInstance().getConfigHelper().hint().checkHeaderFooterForRedundancy(config().getConfigurationSection("header-footer"));
|
||||
}
|
||||
@@ -44,7 +44,7 @@ public class HeaderFooter extends TabFeature implements HeaderFooterManager, Joi
|
||||
@Override
|
||||
public void unload() {
|
||||
for (TabPlayer p : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (disableChecker.isDisabledPlayer(p)) continue;
|
||||
if (p.disabledHeaderFooter.get()) continue;
|
||||
sendHeaderFooter(p, "","");
|
||||
}
|
||||
}
|
||||
@@ -52,7 +52,7 @@ public class HeaderFooter extends TabFeature implements HeaderFooterManager, Joi
|
||||
@Override
|
||||
public void onJoin(@NotNull TabPlayer connectedPlayer) {
|
||||
if (disableChecker.isDisableConditionMet(connectedPlayer)) {
|
||||
disableChecker.addDisabledPlayer(connectedPlayer);
|
||||
connectedPlayer.disabledHeaderFooter.set(true);
|
||||
}
|
||||
refresh(connectedPlayer, true);
|
||||
}
|
||||
@@ -140,7 +140,7 @@ public class HeaderFooter extends TabFeature implements HeaderFooterManager, Joi
|
||||
}
|
||||
|
||||
private void sendHeaderFooter(TabPlayer player, String header, String footer) {
|
||||
if (disableChecker.isDisabledPlayer(player)) return;
|
||||
if (player.disabledHeaderFooter.get()) return;
|
||||
player.getTabList().setPlayerListHeaderFooter(TabComponent.optimized(header), TabComponent.optimized(footer));
|
||||
}
|
||||
|
||||
@@ -156,6 +156,7 @@ public class HeaderFooter extends TabFeature implements HeaderFooterManager, Joi
|
||||
|
||||
@Override
|
||||
public void setHeader(@NotNull me.neznamy.tab.api.TabPlayer p, @Nullable String header) {
|
||||
ensureActive();
|
||||
TabPlayer player = (TabPlayer) p;
|
||||
player.ensureLoaded();
|
||||
player.getProperty(TabConstants.Property.HEADER).setTemporaryValue(header);
|
||||
@@ -165,6 +166,7 @@ public class HeaderFooter extends TabFeature implements HeaderFooterManager, Joi
|
||||
|
||||
@Override
|
||||
public void setFooter(@NotNull me.neznamy.tab.api.TabPlayer p, @Nullable String footer) {
|
||||
ensureActive();
|
||||
TabPlayer player = (TabPlayer) p;
|
||||
player.ensureLoaded();
|
||||
player.getProperty(TabConstants.Property.FOOTER).setTemporaryValue(footer);
|
||||
@@ -174,6 +176,7 @@ public class HeaderFooter extends TabFeature implements HeaderFooterManager, Joi
|
||||
|
||||
@Override
|
||||
public void setHeaderAndFooter(@NotNull me.neznamy.tab.api.TabPlayer p, @Nullable String header, @Nullable String footer) {
|
||||
ensureActive();
|
||||
TabPlayer player = (TabPlayer) p;
|
||||
player.ensureLoaded();
|
||||
player.getProperty(TabConstants.Property.HEADER).setTemporaryValue(header);
|
||||
|
||||
@@ -6,7 +6,6 @@ import java.util.UUID;
|
||||
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.nametags.NameTag;
|
||||
import me.neznamy.tab.shared.features.redis.RedisPlayer;
|
||||
import me.neznamy.tab.shared.features.redis.RedisSupport;
|
||||
@@ -71,13 +70,13 @@ public class NickCompatibility extends TabFeature implements EntryAddListener {
|
||||
if (nameTags != null && !nameTags.hasTeamHandlingPaused(player))
|
||||
for (TabPlayer viewer : TAB.getInstance().getOnlinePlayers()) {
|
||||
String prefix = player.getProperty(TabConstants.Property.TAGPREFIX).getFormat(viewer);
|
||||
viewer.getScoreboard().unregisterTeam(nameTags.getSorting().getShortTeamName(player));
|
||||
viewer.getScoreboard().unregisterTeam(player.sortingData.getShortTeamName());
|
||||
viewer.getScoreboard().registerTeam(
|
||||
nameTags.getSorting().getShortTeamName(player),
|
||||
player.sortingData.getShortTeamName(),
|
||||
prefix,
|
||||
player.getProperty(TabConstants.Property.TAGSUFFIX).getFormat(viewer),
|
||||
nameTags.getTeamVisibility(player, viewer) ? Scoreboard.NameVisibility.ALWAYS : Scoreboard.NameVisibility.NEVER,
|
||||
nameTags.getCollisionManager().getCollision(player) ? Scoreboard.CollisionRule.ALWAYS : Scoreboard.CollisionRule.NEVER,
|
||||
player.teamData.getCollisionRule() ? Scoreboard.CollisionRule.ALWAYS : Scoreboard.CollisionRule.NEVER,
|
||||
Collections.singletonList(player.getNickname()),
|
||||
nameTags.getTeamOptions(),
|
||||
EnumChatFormat.lastColorsOf(prefix)
|
||||
@@ -100,18 +99,18 @@ public class NickCompatibility extends TabFeature implements EntryAddListener {
|
||||
private void processNameChange(RedisPlayer player) {
|
||||
TAB.getInstance().getCPUManager().runMeasuredTask(getFeatureName(), TabConstants.CpuUsageCategory.NICK_PLUGIN_COMPATIBILITY, () -> {
|
||||
if (redisTeams != null) {
|
||||
String teamName = redisTeams.getTeamNames().get(player);
|
||||
String teamName = player.getTeamName();
|
||||
for (TabPlayer viewer : TAB.getInstance().getOnlinePlayers()) {
|
||||
viewer.getScoreboard().unregisterTeam(teamName);
|
||||
viewer.getScoreboard().registerTeam(
|
||||
teamName,
|
||||
redisTeams.getPrefixes().get(player),
|
||||
redisTeams.getSuffixes().get(player),
|
||||
redisTeams.getNameVisibilities().get(player),
|
||||
player.getTagPrefix(),
|
||||
player.getTagSuffix(),
|
||||
player.getNameVisibility(),
|
||||
Scoreboard.CollisionRule.ALWAYS,
|
||||
Collections.singletonList(player.getNickname()),
|
||||
redisTeams.getNameTags().getTeamOptions(),
|
||||
EnumChatFormat.lastColorsOf(redisTeams.getPrefixes().get(player))
|
||||
EnumChatFormat.lastColorsOf(player.getTagPrefix())
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -120,9 +119,9 @@ public class NickCompatibility extends TabFeature implements EntryAddListener {
|
||||
all.getScoreboard().setScore(
|
||||
BelowName.OBJECTIVE_NAME,
|
||||
player.getNickname(),
|
||||
redisBelowName.getValues().get(player),
|
||||
player.getBelowNameNumber(),
|
||||
null, // Unused by this objective slot
|
||||
TabComponent.optimized(redisBelowName.getFancyValues().get(player))
|
||||
player.getBelowNameFancy()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -131,9 +130,9 @@ public class NickCompatibility extends TabFeature implements EntryAddListener {
|
||||
all.getScoreboard().setScore(
|
||||
YellowNumber.OBJECTIVE_NAME,
|
||||
player.getNickname(),
|
||||
redisYellowNumber.getValues().get(player),
|
||||
player.getPlayerlistNumber(),
|
||||
null, // Unused by this objective slot
|
||||
TabComponent.optimized(redisYellowNumber.getFancyValues().get(player))
|
||||
player.getPlayerlistFancy()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package me.neznamy.tab.shared.features;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.TabConstants;
|
||||
import me.neznamy.tab.shared.features.layout.LayoutManagerImpl;
|
||||
import me.neznamy.tab.shared.features.layout.LayoutView;
|
||||
import me.neznamy.tab.shared.features.layout.ParentGroup;
|
||||
import me.neznamy.tab.shared.features.layout.PlayerSlot;
|
||||
import me.neznamy.tab.shared.features.types.*;
|
||||
@@ -26,9 +25,8 @@ public class PingSpoof extends TabFeature implements JoinListener, LatencyListen
|
||||
@Override
|
||||
public int onLatencyChange(@NotNull TabPlayer packetReceiver, @NotNull UUID id, int latency) {
|
||||
if (layoutManager != null) {
|
||||
LayoutView layout = layoutManager.getViews().get(packetReceiver);
|
||||
if (layout != null) {
|
||||
for (ParentGroup group : layout.getGroups()) {
|
||||
if (packetReceiver.layoutData.view != null) {
|
||||
for (ParentGroup group : packetReceiver.layoutData.view.getGroups()) {
|
||||
PlayerSlot slot = group.getPlayerSlots().get((int) id.getLeastSignificantBits());
|
||||
if (slot != null && slot.getPlayer() != null) return value;
|
||||
}
|
||||
|
||||
@@ -96,6 +96,7 @@ public class PlaceholderManagerImpl extends TabFeature implements PlaceholderMan
|
||||
updatePlayerPlaceholders(task.getPlayerPlaceholderResults(), update);
|
||||
Map<TabPlayer, Set<Refreshable>> forceUpdate = updateRelationalPlaceholders(task.getRelationalPlaceholderResults());
|
||||
cpu.addTime(getFeatureName(), CpuUsageCategory.PLACEHOLDER_SAVE, System.nanoTime() - time);
|
||||
cpu.addPlaceholderTimes(task.getUsedTime());
|
||||
|
||||
refreshFeatures(forceUpdate, update);
|
||||
}
|
||||
@@ -338,28 +339,50 @@ public class PlaceholderManagerImpl extends TabFeature implements PlaceholderMan
|
||||
return "Other";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if placeholder is registered, {@code false} if not.
|
||||
*
|
||||
* @param identifier
|
||||
* Placeholder to check
|
||||
* @return {@code true} if placeholder is registered, {@code false} if not
|
||||
*/
|
||||
public boolean isPlaceholderRegistered(@NotNull String identifier) {
|
||||
return registeredPlaceholders.containsKey(identifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getFeatureName() {
|
||||
return "Refreshing placeholders";
|
||||
}
|
||||
|
||||
// ------------------
|
||||
// API Implementation
|
||||
// ------------------
|
||||
|
||||
@Override
|
||||
public @NotNull ServerPlaceholderImpl registerServerPlaceholder(@NonNull String identifier, int refresh, @NonNull Supplier<Object> supplier) {
|
||||
ensureActive();
|
||||
return registerPlaceholder(new ServerPlaceholderImpl(identifier, refresh, supplier));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull PlayerPlaceholderImpl registerPlayerPlaceholder(@NonNull String identifier, int refresh, @NonNull Function<me.neznamy.tab.api.TabPlayer, Object> function) {
|
||||
public @NotNull PlayerPlaceholderImpl registerPlayerPlaceholder(@NonNull String identifier, int refresh,
|
||||
@NonNull Function<me.neznamy.tab.api.TabPlayer, Object> function) {
|
||||
ensureActive();
|
||||
return registerPlaceholder(new PlayerPlaceholderImpl(identifier, refresh, function));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull RelationalPlaceholderImpl registerRelationalPlaceholder(
|
||||
@NonNull String identifier, int refresh, @NonNull BiFunction<me.neznamy.tab.api.TabPlayer, me.neznamy.tab.api.TabPlayer, Object> function) {
|
||||
ensureActive();
|
||||
return registerPlaceholder(new RelationalPlaceholderImpl(identifier, refresh, function));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull TabPlaceholder getPlaceholder(@NonNull String identifier) {
|
||||
ensureActive();
|
||||
TabPlaceholder p = (TabPlaceholder) registeredPlaceholders.get(identifier);
|
||||
if (p == null) {
|
||||
TabPlaceholderRegisterEvent event = new TabPlaceholderRegisterEvent(identifier);
|
||||
@@ -385,30 +408,15 @@ public class PlaceholderManagerImpl extends TabFeature implements PlaceholderMan
|
||||
|
||||
@Override
|
||||
public void unregisterPlaceholder(@NonNull Placeholder placeholder) {
|
||||
ensureActive();
|
||||
unregisterPlaceholder(placeholder.getIdentifier());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterPlaceholder(@NonNull String identifier) {
|
||||
ensureActive();
|
||||
registeredPlaceholders.remove(identifier);
|
||||
placeholderUsage.remove(identifier);
|
||||
recalculateUsedPlaceholders();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if placeholder is registered, {@code false} if not.
|
||||
*
|
||||
* @param identifier
|
||||
* Placeholder to check
|
||||
* @return {@code true} if placeholder is registered, {@code false} if not
|
||||
*/
|
||||
public boolean isPlaceholderRegistered(@NotNull String identifier) {
|
||||
return registeredPlaceholders.containsKey(identifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getFeatureName() {
|
||||
return "Refreshing placeholders";
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,6 @@ 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.LayoutManagerImpl;
|
||||
import me.neznamy.tab.shared.features.layout.LayoutView;
|
||||
import me.neznamy.tab.shared.features.layout.PlayerSlot;
|
||||
import me.neznamy.tab.shared.features.redis.RedisSupport;
|
||||
import me.neznamy.tab.shared.features.types.*;
|
||||
@@ -46,7 +45,7 @@ public class PlayerList extends TabFeature implements TabListFormatManager, Join
|
||||
*/
|
||||
public PlayerList() {
|
||||
Condition disableCondition = Condition.getCondition(config().getString("tablist-name-formatting.disable-condition"));
|
||||
disableChecker = new DisableChecker(getFeatureName(), disableCondition, this::onDisableConditionChange);
|
||||
disableChecker = new DisableChecker(getFeatureName(), disableCondition, this::onDisableConditionChange, p -> p.disabledPlayerList);
|
||||
TAB.getInstance().getFeatureManager().registerFeature(TabConstants.Feature.PLAYER_LIST + "-Condition", disableChecker);
|
||||
if (antiOverrideTabList) {
|
||||
TAB.getInstance().getCPUManager().startRepeatingMeasuredTask(500, getFeatureName(), TabConstants.CpuUsageCategory.ANTI_OVERRIDE, () -> {
|
||||
@@ -73,9 +72,8 @@ public class PlayerList extends TabFeature implements TabListFormatManager, Join
|
||||
*/
|
||||
public UUID getTablistUUID(@NotNull TabPlayer p, @NotNull TabPlayer viewer) {
|
||||
if (layoutManager != null) {
|
||||
LayoutView layout = layoutManager.getViews().get(viewer);
|
||||
if (layout != null) {
|
||||
PlayerSlot slot = layout.getSlot(p);
|
||||
if (viewer.layoutData.view != null) {
|
||||
PlayerSlot slot = viewer.layoutData.view.getSlot(p);
|
||||
if (slot != null) {
|
||||
return slot.getUniqueId();
|
||||
}
|
||||
@@ -111,7 +109,7 @@ public class PlayerList extends TabFeature implements TabListFormatManager, Join
|
||||
TabPlayer player = (TabPlayer) p;
|
||||
for (TabPlayer viewer : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (viewer.getVersion().getMinorVersion() < 8) continue;
|
||||
if (!viewer.getTabList().containsEntry(player.getTablistId())) continue;
|
||||
//if (!viewer.getTabList().containsEntry(player.getTablistId())) continue;
|
||||
UUID tablistId = getTablistUUID(player, viewer);
|
||||
viewer.getTabList().updateDisplayName(tablistId, format ? getTabFormat(player, viewer) :
|
||||
tablistId.getMostSignificantBits() == 0 ? new SimpleComponent(player.getName()) : null);
|
||||
@@ -146,7 +144,7 @@ public class PlayerList extends TabFeature implements TabListFormatManager, Join
|
||||
all.getTabList().setAntiOverride(antiOverrideTabList);
|
||||
updateProperties(all);
|
||||
if (disableChecker.isDisableConditionMet(all)) {
|
||||
disableChecker.addDisabledPlayer(all);
|
||||
all.disabledPlayerList.set(true);
|
||||
} else {
|
||||
if (redis != null) redis.updateTabFormat(all, all.getProperty(TabConstants.Property.TABPREFIX).get() + all.getProperty(TabConstants.Property.CUSTOMTABNAME).get() + all.getProperty(TabConstants.Property.TABSUFFIX).get());
|
||||
}
|
||||
@@ -154,8 +152,8 @@ public class PlayerList extends TabFeature implements TabListFormatManager, Join
|
||||
for (TabPlayer viewer : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (viewer.getVersion().getMinorVersion() < 8) continue;
|
||||
for (TabPlayer target : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (disableChecker.isDisabledPlayer(target)) continue;
|
||||
if (!viewer.getTabList().containsEntry(target.getTablistId())) continue;
|
||||
if (target.disabledPlayerList.get()) continue;
|
||||
//if (!viewer.getTabList().containsEntry(target.getTablistId())) continue;
|
||||
viewer.getTabList().updateDisplayName(getTablistUUID(target, viewer), getTabFormat(target, viewer));
|
||||
}
|
||||
}
|
||||
@@ -167,8 +165,8 @@ public class PlayerList extends TabFeature implements TabListFormatManager, Join
|
||||
for (TabPlayer viewer : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (viewer.getVersion().getMinorVersion() < 8) continue;
|
||||
for (TabPlayer target : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (disableChecker.isDisabledPlayer(target)) continue;
|
||||
if (!viewer.getTabList().containsEntry(target.getTablistId())) continue;
|
||||
if (target.disabledPlayerList.get()) continue;
|
||||
//if (!viewer.getTabList().containsEntry(target.getTablistId())) continue;
|
||||
viewer.getTabList().updateDisplayName(getTablistUUID(target, target), null);
|
||||
}
|
||||
}
|
||||
@@ -176,15 +174,17 @@ public class PlayerList extends TabFeature implements TabListFormatManager, Join
|
||||
|
||||
@Override
|
||||
public void onServerChange(@NotNull TabPlayer p, @NotNull String from, @NotNull String to) {
|
||||
if (updateProperties(p) && !disableChecker.isDisabledPlayer(p)) updatePlayer(p, true);
|
||||
if (updateProperties(p) && !p.disabledPlayerList.get()) updatePlayer(p, true);
|
||||
if (TAB.getInstance().getFeatureManager().isFeatureEnabled(TabConstants.Feature.PIPELINE_INJECTION)) return;
|
||||
TAB.getInstance().getCPUManager().runTaskLater(300, getFeatureName(), TabConstants.CpuUsageCategory.PLAYER_JOIN, () -> {
|
||||
for (TabPlayer all : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (!disableChecker.isDisabledPlayer(all) && p.getVersion().getMinorVersion() >= 8
|
||||
&& p.getTabList().containsEntry(all.getTablistId()))
|
||||
if (!all.disabledPlayerList.get() && p.getVersion().getMinorVersion() >= 8
|
||||
//&& p.getTabList().containsEntry(all.getTablistId())
|
||||
)
|
||||
p.getTabList().updateDisplayName(getTablistUUID(all, p), getTabFormat(all, p));
|
||||
if (all != p && !disableChecker.isDisabledPlayer(p) && all.getVersion().getMinorVersion() >= 8
|
||||
&& all.getTabList().containsEntry(p.getTablistId()))
|
||||
if (all != p && !p.disabledPlayerList.get() && all.getVersion().getMinorVersion() >= 8
|
||||
//&& all.getTabList().containsEntry(p.getTablistId())
|
||||
)
|
||||
all.getTabList().updateDisplayName(getTablistUUID(p, all), getTabFormat(p, all));
|
||||
}
|
||||
});
|
||||
@@ -192,7 +192,7 @@ public class PlayerList extends TabFeature implements TabListFormatManager, Join
|
||||
|
||||
@Override
|
||||
public void onWorldChange(@NotNull TabPlayer changed, @NotNull String from, @NotNull String to) {
|
||||
if (updateProperties(changed) && !disableChecker.isDisabledPlayer(changed)) updatePlayer(changed, true);
|
||||
if (updateProperties(changed) && !changed.disabledPlayerList.get()) updatePlayer(changed, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -220,7 +220,7 @@ public class PlayerList extends TabFeature implements TabListFormatManager, Join
|
||||
boolean suffix = refreshed.getProperty(TabConstants.Property.TABSUFFIX).update();
|
||||
refresh = prefix || name || suffix;
|
||||
}
|
||||
if (disableChecker.isDisabledPlayer(refreshed)) return;
|
||||
if (refreshed.disabledPlayerList.get()) return;
|
||||
if (refresh) {
|
||||
updatePlayer(refreshed, true);
|
||||
}
|
||||
@@ -237,7 +237,7 @@ public class PlayerList extends TabFeature implements TabListFormatManager, Join
|
||||
connectedPlayer.getTabList().setAntiOverride(antiOverrideTabList);
|
||||
updateProperties(connectedPlayer);
|
||||
if (disableChecker.isDisableConditionMet(connectedPlayer)) {
|
||||
disableChecker.addDisabledPlayer(connectedPlayer);
|
||||
connectedPlayer.disabledPlayerList.set(true);
|
||||
return;
|
||||
}
|
||||
Runnable r = () -> {
|
||||
@@ -257,10 +257,10 @@ public class PlayerList extends TabFeature implements TabListFormatManager, Join
|
||||
|
||||
@Override
|
||||
public void onVanishStatusChange(@NotNull TabPlayer player) {
|
||||
if (player.isVanished() || disableChecker.isDisabledPlayer(player)) return;
|
||||
if (player.isVanished() || player.disabledPlayerList.get()) return;
|
||||
for (TabPlayer viewer : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (viewer.getVersion().getMinorVersion() < 8) continue;
|
||||
if (!viewer.getTabList().containsEntry(player.getTablistId())) continue;
|
||||
//if (!viewer.getTabList().containsEntry(player.getTablistId())) continue;
|
||||
viewer.getTabList().updateDisplayName(player.getTablistId(), getTabFormat(player, viewer));
|
||||
}
|
||||
}
|
||||
@@ -277,6 +277,7 @@ public class PlayerList extends TabFeature implements TabListFormatManager, Join
|
||||
|
||||
@Override
|
||||
public void setPrefix(@NonNull me.neznamy.tab.api.TabPlayer player, @Nullable String prefix) {
|
||||
ensureActive();
|
||||
((TabPlayer)player).ensureLoaded();
|
||||
((TabPlayer)player).getProperty(TabConstants.Property.TABPREFIX).setTemporaryValue(prefix);
|
||||
updatePlayer(player, true);
|
||||
@@ -284,6 +285,7 @@ public class PlayerList extends TabFeature implements TabListFormatManager, Join
|
||||
|
||||
@Override
|
||||
public void setName(@NonNull me.neznamy.tab.api.TabPlayer player, @Nullable String customName) {
|
||||
ensureActive();
|
||||
((TabPlayer)player).ensureLoaded();
|
||||
((TabPlayer)player).getProperty(TabConstants.Property.CUSTOMTABNAME).setTemporaryValue(customName);
|
||||
updatePlayer(player, true);
|
||||
@@ -291,6 +293,7 @@ public class PlayerList extends TabFeature implements TabListFormatManager, Join
|
||||
|
||||
@Override
|
||||
public void setSuffix(@NonNull me.neznamy.tab.api.TabPlayer player, @Nullable String suffix) {
|
||||
ensureActive();
|
||||
((TabPlayer)player).ensureLoaded();
|
||||
((TabPlayer)player).getProperty(TabConstants.Property.TABSUFFIX).setTemporaryValue(suffix);
|
||||
updatePlayer(player, true);
|
||||
@@ -298,36 +301,42 @@ public class PlayerList extends TabFeature implements TabListFormatManager, Join
|
||||
|
||||
@Override
|
||||
public String getCustomPrefix(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
ensureActive();
|
||||
((TabPlayer)player).ensureLoaded();
|
||||
return ((TabPlayer)player).getProperty(TabConstants.Property.TABPREFIX).getTemporaryValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCustomName(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
ensureActive();
|
||||
((TabPlayer)player).ensureLoaded();
|
||||
return ((TabPlayer)player).getProperty(TabConstants.Property.CUSTOMTABNAME).getTemporaryValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCustomSuffix(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
ensureActive();
|
||||
((TabPlayer)player).ensureLoaded();
|
||||
return ((TabPlayer)player).getProperty(TabConstants.Property.TABSUFFIX).getTemporaryValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getOriginalPrefix(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
ensureActive();
|
||||
((TabPlayer)player).ensureLoaded();
|
||||
return ((TabPlayer)player).getProperty(TabConstants.Property.TABPREFIX).getOriginalRawValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getOriginalName(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
ensureActive();
|
||||
((TabPlayer)player).ensureLoaded();
|
||||
return ((TabPlayer)player).getProperty(TabConstants.Property.CUSTOMTABNAME).getOriginalRawValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getOriginalSuffix(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
ensureActive();
|
||||
((TabPlayer)player).ensureLoaded();
|
||||
return ((TabPlayer)player).getProperty(TabConstants.Property.TABSUFFIX).getOriginalRawValue();
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ public class YellowNumber extends TabFeature implements JoinListener, Loadable,
|
||||
*/
|
||||
public YellowNumber() {
|
||||
Condition disableCondition = Condition.getCondition(config().getString("playerlist-objective.disable-condition"));
|
||||
disableChecker = new DisableChecker(getFeatureName(), disableCondition, this::onDisableConditionChange);
|
||||
disableChecker = new DisableChecker(getFeatureName(), disableCondition, this::onDisableConditionChange, p -> p.disabledYellowNumber);
|
||||
TAB.getInstance().getFeatureManager().registerFeature(TabConstants.Feature.YELLOW_NUMBER + "-Condition", disableChecker);
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ public class YellowNumber extends TabFeature implements JoinListener, Loadable,
|
||||
loaded.setProperty(this, PROPERTY_VALUE, rawValue);
|
||||
loaded.setProperty(this, PROPERTY_VALUE_FANCY, rawValueFancy);
|
||||
if (disableChecker.isDisableConditionMet(loaded)) {
|
||||
disableChecker.addDisabledPlayer(loaded);
|
||||
loaded.disabledYellowNumber.set(true);
|
||||
} else {
|
||||
register(loaded);
|
||||
}
|
||||
@@ -102,7 +102,7 @@ public class YellowNumber extends TabFeature implements JoinListener, Loadable,
|
||||
@Override
|
||||
public void unload() {
|
||||
for (TabPlayer p : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (disableChecker.isDisabledPlayer(p) || p.isBedrockPlayer()) continue;
|
||||
if (p.disabledYellowNumber.get() || p.isBedrockPlayer()) continue;
|
||||
p.getScoreboard().unregisterObjective(OBJECTIVE_NAME);
|
||||
}
|
||||
}
|
||||
@@ -112,7 +112,7 @@ public class YellowNumber extends TabFeature implements JoinListener, Loadable,
|
||||
connectedPlayer.setProperty(this, PROPERTY_VALUE, rawValue);
|
||||
connectedPlayer.setProperty(this, PROPERTY_VALUE_FANCY, rawValueFancy);
|
||||
if (disableChecker.isDisableConditionMet(connectedPlayer)) {
|
||||
disableChecker.addDisabledPlayer(connectedPlayer);
|
||||
connectedPlayer.disabledYellowNumber.set(true);
|
||||
} else {
|
||||
register(connectedPlayer);
|
||||
}
|
||||
@@ -163,7 +163,7 @@ public class YellowNumber extends TabFeature implements JoinListener, Loadable,
|
||||
|
||||
@Override
|
||||
public void onLoginPacket(@NotNull TabPlayer p) {
|
||||
if (disableChecker.isDisabledPlayer(p) || !p.isLoaded()) return;
|
||||
if (p.disabledYellowNumber.get() || !p.isLoaded()) return;
|
||||
register(p);
|
||||
for (TabPlayer all : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (all.isLoaded()) setScore(p, all, getValueNumber(all), all.getProperty(PROPERTY_VALUE_FANCY).getFormat(p));
|
||||
@@ -189,7 +189,7 @@ public class YellowNumber extends TabFeature implements JoinListener, Loadable,
|
||||
* NumberFormat display of the score
|
||||
*/
|
||||
public void setScore(@NotNull TabPlayer viewer, @NotNull TabPlayer scoreHolder, int value, @NotNull String fancyValue) {
|
||||
if (viewer.isBedrockPlayer() || disableChecker.isDisabledPlayer(viewer)) return;
|
||||
if (viewer.isBedrockPlayer() || viewer.disabledYellowNumber.get()) return;
|
||||
viewer.getScoreboard().setScore(
|
||||
OBJECTIVE_NAME,
|
||||
scoreHolder.getNickname(),
|
||||
|
||||
@@ -175,6 +175,36 @@ public class BossBarLine implements BossBar {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resends bossbar to the player.
|
||||
*
|
||||
* @param player
|
||||
* Player to resend bossbar to
|
||||
*/
|
||||
public void sendToPlayerRaw(@NotNull TabPlayer player) {
|
||||
player.getBossBar().create(
|
||||
uniqueId,
|
||||
player.getProperty(propertyTitle).updateAndGet(),
|
||||
parseProgress(player, player.getProperty(propertyProgress).updateAndGet())/100,
|
||||
parseColor(player.getProperty(propertyColor).updateAndGet()),
|
||||
parseStyle(player.getProperty(propertyStyle).updateAndGet())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes player from set of players.
|
||||
*
|
||||
* @param player
|
||||
* Player to remove
|
||||
*/
|
||||
public void removePlayerRaw(@NotNull TabPlayer player) {
|
||||
players.remove(player);
|
||||
}
|
||||
|
||||
// ------------------
|
||||
// API Implementation
|
||||
// ------------------
|
||||
|
||||
@Override
|
||||
public void setTitle(@NonNull String title) {
|
||||
if (this.title.equals(title)) return;
|
||||
@@ -234,28 +264,12 @@ public class BossBarLine implements BossBar {
|
||||
public void addPlayer(@NonNull me.neznamy.tab.api.TabPlayer p) {
|
||||
TabPlayer player = (TabPlayer) p;
|
||||
if (players.contains(player)) return;
|
||||
players.add(player);
|
||||
player.setProperty(textRefresher, propertyTitle, title);
|
||||
player.setProperty(progressRefresher, propertyProgress, progress);
|
||||
player.setProperty(colorRefresher, propertyColor, color);
|
||||
player.setProperty(styleRefresher, propertyStyle, style);
|
||||
sendToPlayerRaw(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resends bossbar to the player.
|
||||
*
|
||||
* @param player
|
||||
* Player to resend bossbar to
|
||||
*/
|
||||
public void sendToPlayerRaw(@NotNull TabPlayer player) {
|
||||
player.getBossBar().create(
|
||||
uniqueId,
|
||||
player.getProperty(propertyTitle).updateAndGet(),
|
||||
parseProgress(player, player.getProperty(propertyProgress).updateAndGet())/100,
|
||||
parseColor(player.getProperty(propertyColor).updateAndGet()),
|
||||
parseStyle(player.getProperty(propertyStyle).updateAndGet())
|
||||
);
|
||||
players.add(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -266,16 +280,6 @@ public class BossBarLine implements BossBar {
|
||||
player.getBossBar().remove(uniqueId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes player from set of players.
|
||||
*
|
||||
* @param player
|
||||
* Player to remove
|
||||
*/
|
||||
public void removePlayerRaw(@NotNull TabPlayer player) {
|
||||
players.remove(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<me.neznamy.tab.api.TabPlayer> getPlayers() {
|
||||
@@ -283,7 +287,7 @@ public class BossBarLine implements BossBar {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsPlayer(me.neznamy.tab.api.TabPlayer player) {
|
||||
public boolean containsPlayer(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
return players.contains((TabPlayer) player);
|
||||
}
|
||||
|
||||
|
||||
+66
-39
@@ -14,6 +14,7 @@ import me.neznamy.tab.shared.features.types.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -46,8 +47,6 @@ public class BossBarManagerImpl extends TabFeature implements BossBarManager, Jo
|
||||
//time when BossBar announce ends, used for placeholder
|
||||
private long announceEndTime;
|
||||
|
||||
private final Set<me.neznamy.tab.api.TabPlayer> visiblePlayers = Collections.newSetFromMap(new WeakHashMap<>());
|
||||
|
||||
/**
|
||||
* Constructs new instance and loads configuration
|
||||
*/
|
||||
@@ -84,7 +83,11 @@ public class BossBarManagerImpl extends TabFeature implements BossBarManager, Jo
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
TAB.getInstance().getPlaceholderManager().registerServerPlaceholder(TabConstants.Placeholder.COUNTDOWN, 100, () -> (announceEndTime - System.currentTimeMillis()) / 1000);
|
||||
TAB.getInstance().getPlaceholderManager().registerServerPlaceholder(TabConstants.Placeholder.COUNTDOWN, 100, () -> {
|
||||
long seconds = TimeUnit.MILLISECONDS.toSeconds(announceEndTime - System.currentTimeMillis());
|
||||
if (seconds < 0) return 0;
|
||||
return seconds;
|
||||
});
|
||||
for (TabPlayer p : TAB.getInstance().getOnlinePlayers()) {
|
||||
onJoin(p);
|
||||
}
|
||||
@@ -166,12 +169,46 @@ public class BossBarManagerImpl extends TabFeature implements BossBarManager, Jo
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull BossBar createBossBar(@NonNull String title, float progress, @NonNull BarColor color, @NonNull BarStyle style) {
|
||||
public void onLoginPacket(TabPlayer player) {
|
||||
// Since 1.20.2, Login packet clears BossBars as well
|
||||
if (player.getVersion().getNetworkId() >= ProtocolVersion.V1_20_2.getNetworkId()) {
|
||||
player.getBossBar().unfreeze();
|
||||
for (BossBar bar : lineValues) {
|
||||
if (bar.containsPlayer(player)) {
|
||||
((BossBarLine)bar).sendToPlayerRaw(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onQuit(@NotNull TabPlayer disconnectedPlayer) {
|
||||
for (BossBar line : lineValues) {
|
||||
((BossBarLine)line).removePlayerRaw(disconnectedPlayer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getFeatureName() {
|
||||
return "BossBar";
|
||||
}
|
||||
|
||||
// ------------------
|
||||
// API Implementation
|
||||
// ------------------
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public BossBar createBossBar(@NonNull String title, float progress, @NonNull BarColor color, @NonNull BarStyle style) {
|
||||
ensureActive();
|
||||
return createBossBar(title, String.valueOf(progress), color.toString(), style.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull BossBar createBossBar(@NonNull String title, @NonNull String progress, @NonNull String color, @NonNull String style) {
|
||||
@NotNull
|
||||
public BossBar createBossBar(@NonNull String title, @NonNull String progress, @NonNull String color, @NonNull String style) {
|
||||
ensureActive();
|
||||
UUID id = UUID.randomUUID();
|
||||
BossBar bar = new BossBarLine(this, id.toString(), null, color, style, title, progress, true);
|
||||
registeredBossBars.put(id.toString(), bar);
|
||||
@@ -181,25 +218,29 @@ public class BossBarManagerImpl extends TabFeature implements BossBarManager, Jo
|
||||
|
||||
@Override
|
||||
public BossBar getBossBar(@NonNull String name) {
|
||||
ensureActive();
|
||||
return registeredBossBars.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toggleBossBar(me.neznamy.tab.api.@NonNull TabPlayer player, boolean sendToggleMessage) {
|
||||
ensureActive();
|
||||
setBossBarVisible(player, !hasBossBarVisible(player), sendToggleMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasBossBarVisible(me.neznamy.tab.api.@NonNull TabPlayer player) {
|
||||
return visiblePlayers.contains(player);
|
||||
ensureActive();
|
||||
return ((TabPlayer)player).bossbarData.visible;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBossBarVisible(me.neznamy.tab.api.@NonNull TabPlayer p, boolean visible, boolean sendToggleMessage) {
|
||||
ensureActive();
|
||||
TabPlayer player = (TabPlayer) p;
|
||||
if (visiblePlayers.contains(player) == visible) return;
|
||||
if (player.bossbarData.visible == visible) return;
|
||||
if (visible) {
|
||||
visiblePlayers.add(player);
|
||||
player.bossbarData.visible = true;
|
||||
detectBossBarsAndSend(player);
|
||||
if (sendToggleMessage) player.sendMessage(toggleOnMessage, true);
|
||||
if (rememberToggleChoice) {
|
||||
@@ -215,7 +256,7 @@ public class BossBarManagerImpl extends TabFeature implements BossBarManager, Jo
|
||||
}
|
||||
}
|
||||
} else {
|
||||
visiblePlayers.remove(player);
|
||||
player.bossbarData.visible = false;
|
||||
for (BossBar l : lineValues) {
|
||||
l.removePlayer(player);
|
||||
}
|
||||
@@ -244,58 +285,44 @@ public class BossBarManagerImpl extends TabFeature implements BossBarManager, Jo
|
||||
|
||||
@Override
|
||||
public void sendBossBarTemporarily(me.neznamy.tab.api.@NonNull TabPlayer player, @NonNull String bossBar, int duration) {
|
||||
ensureActive();
|
||||
if (!hasBossBarVisible(player)) return;
|
||||
BossBar line = registeredBossBars.get(bossBar);
|
||||
if (line == null) throw new IllegalArgumentException("No registered BossBar found with name " + bossBar);
|
||||
TAB.getInstance().getCPUManager().runMeasuredTask(getFeatureName(), "Adding temporary BossBar", () -> line.addPlayer(player));
|
||||
TAB.getInstance().getCPUManager().runTaskLater(duration*1000,
|
||||
TAB.getInstance().getCPUManager().runTaskLater((int) TimeUnit.SECONDS.toMillis(duration),
|
||||
getFeatureName(), "Removing temporary BossBar", () -> line.removePlayer(player));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void announceBossBar(@NonNull String bossBar, int duration) {
|
||||
ensureActive();
|
||||
BossBar line = registeredBossBars.get(bossBar);
|
||||
if (line == null) throw new IllegalArgumentException("No registered BossBar found with name " + bossBar);
|
||||
List<TabPlayer> players = Arrays.stream(TAB.getInstance().getOnlinePlayers()).filter(
|
||||
this::hasBossBarVisible).collect(Collectors.toList());
|
||||
TAB.getInstance().getCPUManager().runMeasuredTask(getFeatureName(), "Adding announced BossBar", () -> {
|
||||
announcedBossBars.add(line);
|
||||
announceEndTime = System.currentTimeMillis() + duration* 1000L;
|
||||
announceEndTime = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(duration);
|
||||
for (TabPlayer all : players) {
|
||||
if (((BossBarLine)line).isConditionMet(all)) line.addPlayer(all);
|
||||
}
|
||||
});
|
||||
TAB.getInstance().getCPUManager().runTaskLater(duration*1000,
|
||||
TAB.getInstance().getCPUManager().runTaskLater((int) TimeUnit.SECONDS.toMillis(duration),
|
||||
getFeatureName(), "Removing announced BossBar", () -> {
|
||||
for (TabPlayer all : players) {
|
||||
line.removePlayer(all);
|
||||
}
|
||||
announcedBossBars.remove(line);
|
||||
});
|
||||
for (TabPlayer all : players) {
|
||||
line.removePlayer(all);
|
||||
}
|
||||
announcedBossBars.remove(line);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoginPacket(TabPlayer player) {
|
||||
// Since 1.20.2, Login packet clears BossBars as well
|
||||
if (player.getVersion().getNetworkId() >= ProtocolVersion.V1_20_2.getNetworkId()) {
|
||||
for (BossBar bar : lineValues) {
|
||||
if (bar.containsPlayer(player)) {
|
||||
((BossBarLine)bar).sendToPlayerRaw(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Class storing bossbar data for players.
|
||||
*/
|
||||
public static class PlayerData {
|
||||
|
||||
@Override
|
||||
public void onQuit(@NotNull TabPlayer disconnectedPlayer) {
|
||||
for (BossBar line : lineValues) {
|
||||
((BossBarLine)line).removePlayerRaw(disconnectedPlayer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getFeatureName() {
|
||||
return "BossBar";
|
||||
/** Whether player wishes to see boss bars or not */
|
||||
public boolean visible;
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,7 @@ public class FixedSlot extends TabFeature implements Refreshable {
|
||||
|
||||
@Override
|
||||
public void refresh(@NotNull TabPlayer p, boolean force) {
|
||||
if (!manager.getViews().containsKey(p) || manager.getViews().get(p).getPattern() != pattern ||
|
||||
if (p.layoutData.view == null || p.layoutData.view.getPattern() != pattern ||
|
||||
p.getVersion().getMinorVersion() < 8 || p.isBedrockPlayer()) return;
|
||||
if (p.getProperty(skinProperty).update()) {
|
||||
p.getTabList().removeEntry(id);
|
||||
@@ -52,6 +52,7 @@ public class FixedSlot extends TabFeature implements Refreshable {
|
||||
id,
|
||||
manager.getDirection().getEntryName(viewer, slot),
|
||||
manager.getSkinManager().getSkin(viewer.getProperty(skinProperty).updateAndGet()),
|
||||
true,
|
||||
ping,
|
||||
0,
|
||||
TabComponent.optimized(viewer.getProperty(propertyName).updateAndGet())
|
||||
|
||||
+2
-3
@@ -21,9 +21,8 @@ public class LayoutLatencyRefresher extends TabFeature implements Refreshable {
|
||||
public void refresh(@NotNull TabPlayer p, boolean force) {
|
||||
for (TabPlayer all : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (all.getVersion().getMinorVersion() < 8) continue;
|
||||
LayoutView layout = manager.getViews().get(all);
|
||||
if (layout == null) continue;
|
||||
PlayerSlot slot = layout.getSlot(p);
|
||||
if (all.layoutData.view == null) continue;
|
||||
PlayerSlot slot = all.layoutData.view.getSlot(p);
|
||||
if (slot == null) continue;
|
||||
all.getTabList().updateLatency(slot.getUniqueId(), p.getPing());
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ import me.neznamy.tab.shared.config.file.ConfigurationFile;
|
||||
import me.neznamy.tab.shared.platform.TabPlayer;
|
||||
import me.neznamy.tab.shared.features.PlayerList;
|
||||
import me.neznamy.tab.shared.features.layout.skin.SkinManager;
|
||||
import me.neznamy.tab.shared.features.sorting.Sorting;
|
||||
import me.neznamy.tab.shared.features.types.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -41,12 +40,8 @@ public class LayoutManagerImpl extends TabFeature implements LayoutManager, Join
|
||||
}
|
||||
}};
|
||||
private final Map<String, LayoutPattern> layouts = loadLayouts();
|
||||
private final WeakHashMap<TabPlayer, String> teamNames = new WeakHashMap<>();
|
||||
private final Map<TabPlayer, String> sortedPlayers = Collections.synchronizedMap(new TreeMap<>(Comparator.comparing(teamNames::get)));
|
||||
private final Sorting sorting = TAB.getInstance().getFeatureManager().getFeature(TabConstants.Feature.SORTING);
|
||||
private final Map<TabPlayer, String> sortedPlayers = Collections.synchronizedMap(new TreeMap<>(Comparator.comparing(p -> p.layoutData.sortingString)));
|
||||
private PlayerList playerList;
|
||||
private final WeakHashMap<TabPlayer, LayoutView> views = new WeakHashMap<>();
|
||||
private final WeakHashMap<me.neznamy.tab.api.TabPlayer, LayoutPattern> forcedLayouts = new WeakHashMap<>();
|
||||
|
||||
private static boolean teamsEnabled;
|
||||
|
||||
@@ -105,15 +100,15 @@ public class LayoutManagerImpl extends TabFeature implements LayoutManager, Join
|
||||
|
||||
@Override
|
||||
public void onJoin(@NotNull TabPlayer p) {
|
||||
teamNames.put(p, sorting.getFullTeamName(p));
|
||||
sortedPlayers.put(p, sorting.getFullTeamName(p));
|
||||
p.layoutData.sortingString = p.sortingData.fullTeamName;
|
||||
sortedPlayers.put(p, p.sortingData.fullTeamName);
|
||||
LayoutPattern highest = getHighestLayout(p);
|
||||
if (highest != null) {
|
||||
LayoutView view = new LayoutView(this, highest, p);
|
||||
view.send();
|
||||
views.put(p, view);
|
||||
p.layoutData.view = view;
|
||||
}
|
||||
views.values().forEach(LayoutView::tick);
|
||||
tickAllLayouts();
|
||||
|
||||
// Unformat original entries for players who can see a layout to avoid spaces due to unparsed placeholders and such
|
||||
if (highest == null) return;
|
||||
@@ -125,24 +120,25 @@ public class LayoutManagerImpl extends TabFeature implements LayoutManager, Join
|
||||
@Override
|
||||
public void onQuit(@NotNull TabPlayer p) {
|
||||
sortedPlayers.remove(p);
|
||||
teamNames.remove(p);
|
||||
views.remove(p);
|
||||
views.values().forEach(LayoutView::tick);
|
||||
for (TabPlayer all : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (all == p) continue;
|
||||
if (all.layoutData.view != null) all.layoutData.view.tick();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh(@NotNull TabPlayer p, boolean force) {
|
||||
LayoutPattern highest = getHighestLayout(p);
|
||||
String highestName = highest == null ? null : highest.getName();
|
||||
LayoutView current = views.get(p);
|
||||
LayoutView current = p.layoutData.view;
|
||||
String currentName = current == null ? null : current.getPattern().getName();
|
||||
if (!Objects.equals(highestName, currentName)) {
|
||||
if (current != null) current.destroy();
|
||||
views.remove(p);
|
||||
p.layoutData.view = null;
|
||||
if (highest != null) {
|
||||
LayoutView view = new LayoutView(this, highest, p);
|
||||
view.send();
|
||||
views.put(p, view);
|
||||
p.layoutData.view = view;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -163,11 +159,11 @@ public class LayoutManagerImpl extends TabFeature implements LayoutManager, Join
|
||||
|
||||
@Override
|
||||
public void onVanishStatusChange(@NotNull TabPlayer p) {
|
||||
views.values().forEach(LayoutView::tick);
|
||||
tickAllLayouts();
|
||||
}
|
||||
|
||||
private @Nullable LayoutPattern getHighestLayout(@NotNull TabPlayer p) {
|
||||
if (forcedLayouts.containsKey(p)) return forcedLayouts.get(p);
|
||||
if (p.layoutData.forcedLayout != null) return p.layoutData.forcedLayout;
|
||||
for (LayoutPattern pattern : layouts.values()) {
|
||||
if (pattern.isConditionMet(p)) return pattern;
|
||||
}
|
||||
@@ -180,9 +176,9 @@ public class LayoutManagerImpl extends TabFeature implements LayoutManager, Join
|
||||
|
||||
public void updateTeamName(@NotNull TabPlayer p, @NotNull String teamName) {
|
||||
sortedPlayers.remove(p);
|
||||
teamNames.put(p, teamName);
|
||||
p.layoutData.sortingString = teamName;
|
||||
sortedPlayers.put(p, teamName);
|
||||
views.values().forEach(LayoutView::tick);
|
||||
tickAllLayouts();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -193,8 +189,16 @@ public class LayoutManagerImpl extends TabFeature implements LayoutManager, Join
|
||||
|
||||
@Override
|
||||
public void onTabListClear(@NotNull TabPlayer player) {
|
||||
LayoutView view = views.get(player);
|
||||
if (view != null) view.send();
|
||||
if (player.layoutData.view != null) player.layoutData.view.send();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ticks layouts for all players.
|
||||
*/
|
||||
public void tickAllLayouts() {
|
||||
for (TabPlayer all : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (all.layoutData.view != null) all.layoutData.view.tick();
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------
|
||||
@@ -203,21 +207,26 @@ public class LayoutManagerImpl extends TabFeature implements LayoutManager, Join
|
||||
|
||||
@Override
|
||||
public Layout createNewLayout(String name) {
|
||||
ensureActive();
|
||||
return new LayoutPattern(this, name, Collections.emptyMap());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendLayout(@NonNull me.neznamy.tab.api.TabPlayer player, @Nullable Layout layout) {
|
||||
((TabPlayer)player).ensureLoaded();
|
||||
forcedLayouts.put(player, (LayoutPattern) layout);
|
||||
refresh((TabPlayer) player, false);
|
||||
ensureActive();
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
p.layoutData.forcedLayout = (LayoutPattern) layout;
|
||||
refresh(p, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetLayout(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
((TabPlayer)player).ensureLoaded();
|
||||
forcedLayouts.remove(player);
|
||||
refresh((TabPlayer) player, false);
|
||||
ensureActive();
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
p.layoutData.forcedLayout = null;
|
||||
refresh(p, false);
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@@ -244,4 +253,21 @@ public class LayoutManagerImpl extends TabFeature implements LayoutManager, Join
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class storing layout data for players.
|
||||
*/
|
||||
public static class PlayerData {
|
||||
|
||||
/** Merged string to sort players by */
|
||||
public String sortingString;
|
||||
|
||||
/** Layout the player can currently see */
|
||||
@Nullable
|
||||
public LayoutView view;
|
||||
|
||||
/** Layout forced via API */
|
||||
@Nullable
|
||||
public LayoutPattern forcedLayout;
|
||||
}
|
||||
}
|
||||
@@ -70,7 +70,7 @@ public class LayoutPattern extends TabFeature implements Refreshable, Layout {
|
||||
|
||||
@Override
|
||||
public void refresh(@NotNull TabPlayer refreshed, boolean force) {
|
||||
manager.getViews().values().forEach(LayoutView::tick);
|
||||
manager.tickAllLayouts();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -79,35 +79,44 @@ public class LayoutPattern extends TabFeature implements Refreshable, Layout {
|
||||
return "Updating player groups";
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getFeatureName() {
|
||||
return manager.getFeatureName();
|
||||
}
|
||||
|
||||
// ------------------
|
||||
// API Implementation
|
||||
// ------------------
|
||||
|
||||
@Override
|
||||
public void addFixedSlot(int slot, @NonNull String text) {
|
||||
ensureActive();
|
||||
addFixedSlot(slot, text, manager.getDefaultSkin(slot), manager.getEmptySlotPing());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFixedSlot(int slot, @NonNull String text, @NonNull String skin) {
|
||||
ensureActive();
|
||||
addFixedSlot(slot, text, skin, manager.getEmptySlotPing());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFixedSlot(int slot, @NonNull String text, int ping) {
|
||||
ensureActive();
|
||||
addFixedSlot(slot, text, manager.getDefaultSkin(slot), ping);
|
||||
}
|
||||
|
||||
@Override
|
||||
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));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addGroup(@Nullable String condition, int[] slots) {
|
||||
ensureActive();
|
||||
addGroup(UUID.randomUUID().toString(), Condition.getCondition(condition), slots);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getFeatureName() {
|
||||
return manager.getFeatureName();
|
||||
}
|
||||
}
|
||||
@@ -53,6 +53,7 @@ public class LayoutView {
|
||||
manager.getUUID(slot),
|
||||
manager.getDirection().getEntryName(viewer, slot),
|
||||
manager.getSkinManager().getDefaultSkin(slot),
|
||||
true,
|
||||
manager.getEmptySlotPing(),
|
||||
0,
|
||||
new SimpleComponent("")
|
||||
|
||||
@@ -15,7 +15,7 @@ public class ParentGroup {
|
||||
@Getter private final int[] slots;
|
||||
private final TabPlayer viewer;
|
||||
@Getter private final Map<Integer, PlayerSlot> playerSlots = new HashMap<>();
|
||||
@Getter final Map<TabPlayer, PlayerSlot> players = new HashMap<>();
|
||||
@Getter private final Map<TabPlayer, PlayerSlot> players = new HashMap<>();
|
||||
|
||||
public ParentGroup(@NotNull LayoutView layout, @NotNull GroupPattern pattern, @NotNull TabPlayer viewer) {
|
||||
this.layout = layout;
|
||||
|
||||
@@ -39,6 +39,7 @@ public class PlayerSlot {
|
||||
uniqueId,
|
||||
layout.getManager().getDirection().getEntryName(p, slot),
|
||||
player.getSkin(),
|
||||
true,
|
||||
player.getPing(),
|
||||
0,
|
||||
playerList == null ? new SimpleComponent(player.getName()) : playerList.getTabFormat(player, p)
|
||||
@@ -48,6 +49,7 @@ public class PlayerSlot {
|
||||
uniqueId,
|
||||
layout.getManager().getDirection().getEntryName(p, slot),
|
||||
layout.getManager().getSkinManager().getDefaultSkin(slot),
|
||||
true,
|
||||
layout.getManager().getEmptySlotPing(),
|
||||
0,
|
||||
new SimpleComponent(text)
|
||||
|
||||
+11
-59
@@ -1,19 +1,15 @@
|
||||
package me.neznamy.tab.shared.features.nametags;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import me.neznamy.tab.shared.placeholders.conditions.Condition;
|
||||
import me.neznamy.tab.shared.platform.TabPlayer;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.TabConstants;
|
||||
import me.neznamy.tab.shared.features.types.JoinListener;
|
||||
import me.neznamy.tab.shared.features.types.Loadable;
|
||||
import me.neznamy.tab.shared.features.types.Refreshable;
|
||||
import me.neznamy.tab.shared.features.types.TabFeature;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.TabConstants;
|
||||
import me.neznamy.tab.shared.placeholders.conditions.Condition;
|
||||
import me.neznamy.tab.shared.platform.TabPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Class managing collision rule for players.
|
||||
@@ -22,33 +18,31 @@ import org.jetbrains.annotations.Nullable;
|
||||
public class CollisionManager extends TabFeature implements JoinListener, Loadable, Refreshable {
|
||||
|
||||
private final NameTag nameTags;
|
||||
private final String collisionRule = config().getString("scoreboard-teams.enable-collision", "true");
|
||||
private final Condition refreshCondition = Condition.getCondition(collisionRule);
|
||||
private final WeakHashMap<TabPlayer, Boolean> collision = new WeakHashMap<>();
|
||||
private final WeakHashMap<me.neznamy.tab.api.TabPlayer, Boolean> forcedCollision = new WeakHashMap<>();
|
||||
private final Condition refreshCondition = Condition.getCondition(config().getString("scoreboard-teams.enable-collision", "true"));
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
TAB.getInstance().getPlaceholderManager().registerPlayerPlaceholder(TabConstants.Placeholder.COLLISION, 500, p -> {
|
||||
if (forcedCollision.containsKey(p)) return forcedCollision.get(p);
|
||||
TabPlayer player = (TabPlayer) p;
|
||||
if (player.teamData.forcedCollision != null) return player.teamData.forcedCollision;
|
||||
boolean newCollision = !((TabPlayer)p).isDisguised() && refreshCondition.isMet((TabPlayer) p);
|
||||
collision.put((TabPlayer) p, newCollision);
|
||||
player.teamData.collisionRule = newCollision;
|
||||
return newCollision;
|
||||
});
|
||||
addUsedPlaceholder(TabConstants.Placeholder.COLLISION);
|
||||
for (TabPlayer all : TAB.getInstance().getOnlinePlayers()) {
|
||||
collision.put(all, true);
|
||||
onJoin(all);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onJoin(@NotNull TabPlayer connectedPlayer) {
|
||||
collision.put(connectedPlayer, refreshCondition.isMet(connectedPlayer));
|
||||
connectedPlayer.teamData.collisionRule = refreshCondition.isMet(connectedPlayer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh(@NotNull TabPlayer p, boolean force) {
|
||||
if (nameTags.getDisableChecker().isDisabledPlayer(p)) return;
|
||||
if (p.disabledNametags.get()) return;
|
||||
nameTags.updateTeamData(p);
|
||||
}
|
||||
|
||||
@@ -58,48 +52,6 @@ public class CollisionManager extends TabFeature implements JoinListener, Loadab
|
||||
return "Updating collision";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns current collision rule for player.
|
||||
*
|
||||
* @param p
|
||||
* Player to get collision rule of
|
||||
* @return Current collision rule for player
|
||||
*/
|
||||
public boolean getCollision(@NotNull TabPlayer p) {
|
||||
return forcedCollision.getOrDefault(p, collision.get(p));
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces collision rule for player. {@code null} removes forced collision.
|
||||
*
|
||||
* @param player
|
||||
* Player to force collision rule for
|
||||
* @param collision
|
||||
* Forced collision rule, {@code null} for resetting.
|
||||
*/
|
||||
public void setCollisionRule(@NotNull TabPlayer player, @Nullable Boolean collision) {
|
||||
if (Objects.equals(forcedCollision.get(player), collision)) return;
|
||||
if (collision == null) {
|
||||
forcedCollision.remove(player);
|
||||
} else {
|
||||
forcedCollision.put(player, collision);
|
||||
}
|
||||
nameTags.updateTeamData(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns forced collision rule for specified player. If no collision
|
||||
* rule is forced for the player, returns {@code null}.
|
||||
*
|
||||
* @param player
|
||||
* Player to get forced collision rule of
|
||||
* @return Forced collision rule of player or {@code null} if not forced
|
||||
*/
|
||||
@Nullable
|
||||
public Boolean getCollisionRule(@NotNull TabPlayer player) {
|
||||
return forcedCollision.get(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getFeatureName() {
|
||||
|
||||
@@ -11,7 +11,6 @@ import me.neznamy.tab.shared.platform.TabPlayer;
|
||||
import me.neznamy.tab.shared.TabConstants;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.features.redis.RedisSupport;
|
||||
import me.neznamy.tab.shared.features.sorting.Sorting;
|
||||
import me.neznamy.tab.shared.features.types.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -25,39 +24,31 @@ public class NameTag extends TabFeature implements NameTagManager, JoinListener,
|
||||
protected final boolean invisibleNameTags = config().getBoolean("scoreboard-teams.invisible-nametags", false);
|
||||
private final boolean canSeeFriendlyInvisibles = config().getBoolean("scoreboard-teams.can-see-friendly-invisibles", false);
|
||||
private final boolean antiOverride = config().getBoolean("scoreboard-teams.anti-override", true);
|
||||
@Getter private final Sorting sorting = TAB.getInstance().getFeatureManager().getFeature(TabConstants.Feature.SORTING);
|
||||
|
||||
@Getter private final CollisionManager collisionManager = new CollisionManager(this);
|
||||
@Getter private final int teamOptions = canSeeFriendlyInvisibles ? 2 : 0;
|
||||
|
||||
private final Set<me.neznamy.tab.api.TabPlayer> hiddenNameTag = Collections.newSetFromMap(new WeakHashMap<>());
|
||||
protected final Set<me.neznamy.tab.api.TabPlayer> teamHandlingPaused = Collections.newSetFromMap(new WeakHashMap<>());
|
||||
protected final WeakHashMap<me.neznamy.tab.api.TabPlayer, Set<me.neznamy.tab.api.TabPlayer>> hiddenNameTagFor = new WeakHashMap<>();
|
||||
protected final Set<me.neznamy.tab.api.TabPlayer> playersWithInvisibleNameTagView = Collections.newSetFromMap(new WeakHashMap<>());
|
||||
@Getter private final DisableChecker disableChecker;
|
||||
private RedisSupport redis;
|
||||
|
||||
// Key - Vanished player, Value = List of players who cannot see the player (UUIDs to prevent memory leak)
|
||||
private final WeakHashMap<TabPlayer, List<UUID>> vanishedPlayers = new WeakHashMap<>();
|
||||
|
||||
public NameTag() {
|
||||
Condition disableCondition = Condition.getCondition(config().getString("scoreboard-teams.disable-condition"));
|
||||
disableChecker = new DisableChecker(getFeatureName(), disableCondition, this::onDisableConditionChange);
|
||||
disableChecker = new DisableChecker(getFeatureName(), disableCondition, this::onDisableConditionChange, p -> p.disabledNametags);
|
||||
TAB.getInstance().getFeatureManager().registerFeature(TabConstants.Feature.NAME_TAGS + "-Condition", disableChecker);
|
||||
TAB.getInstance().getFeatureManager().registerFeature(TabConstants.Feature.NAME_TAGS_COLLISION, collisionManager);
|
||||
if (!antiOverride) TAB.getInstance().getConfigHelper().startup().teamAntiOverrideDisabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
TAB.getInstance().getFeatureManager().registerFeature(TabConstants.Feature.NAME_TAGS_COLLISION, collisionManager);
|
||||
collisionManager.load();
|
||||
// RedisSupport is instantiated after NameTags, so must be loaded after
|
||||
redis = TAB.getInstance().getFeatureManager().getFeature(TabConstants.Feature.REDIS_BUNGEE);
|
||||
TAB.getInstance().getFeatureManager().registerFeature(TabConstants.Feature.NAME_TAGS_VISIBILITY, new VisibilityRefresher(this));
|
||||
for (TabPlayer all : TAB.getInstance().getOnlinePlayers()) {
|
||||
all.getScoreboard().setAntiOverrideTeams(antiOverride);
|
||||
updateProperties(all);
|
||||
hiddenNameTagFor.put(all, new HashSet<>());
|
||||
if (disableChecker.isDisableConditionMet(all)) {
|
||||
disableChecker.addDisabledPlayer(all);
|
||||
all.disabledNametags.set(true);
|
||||
continue;
|
||||
}
|
||||
TAB.getInstance().getPlaceholderManager().getTabExpansion().setNameTagVisibility(all, true);
|
||||
@@ -65,9 +56,9 @@ public class NameTag extends TabFeature implements NameTagManager, JoinListener,
|
||||
for (TabPlayer viewer : TAB.getInstance().getOnlinePlayers()) {
|
||||
for (TabPlayer target : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (target.isVanished() && !TAB.getInstance().getPlatform().canSee(viewer, target)) {
|
||||
vanishedPlayers.computeIfAbsent(target, p -> new ArrayList<>()).add(viewer.getUniqueId());
|
||||
target.teamData.vanishedFor.add(viewer.getUniqueId());
|
||||
}
|
||||
if (!disableChecker.isDisabledPlayer(target)) registerTeam(target, viewer);
|
||||
if (!target.disabledNametags.get()) registerTeam(target, viewer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,15 +67,15 @@ public class NameTag extends TabFeature implements NameTagManager, JoinListener,
|
||||
public void unload() {
|
||||
for (TabPlayer viewer : TAB.getInstance().getOnlinePlayers()) {
|
||||
for (TabPlayer target : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (hasTeamHandlingPaused(target) || disableChecker.isDisabledPlayer(target)) continue;
|
||||
viewer.getScoreboard().unregisterTeam(sorting.getShortTeamName(target));
|
||||
if (hasTeamHandlingPaused(target) || target.disabledNametags.get()) continue;
|
||||
viewer.getScoreboard().unregisterTeam(target.sortingData.getShortTeamName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh(@NotNull TabPlayer refreshed, boolean force) {
|
||||
if (disableChecker.isDisabledPlayer(refreshed)) return;
|
||||
if (refreshed.disabledNametags.get()) return;
|
||||
boolean refresh;
|
||||
if (force) {
|
||||
updateProperties(refreshed);
|
||||
@@ -107,22 +98,21 @@ public class NameTag extends TabFeature implements NameTagManager, JoinListener,
|
||||
public void onJoin(@NotNull TabPlayer connectedPlayer) {
|
||||
connectedPlayer.getScoreboard().setAntiOverrideTeams(antiOverride);
|
||||
updateProperties(connectedPlayer);
|
||||
hiddenNameTagFor.put(connectedPlayer, new HashSet<>());
|
||||
for (TabPlayer all : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (all == connectedPlayer) continue; //avoiding double registration
|
||||
if (connectedPlayer.isVanished() && !TAB.getInstance().getPlatform().canSee(all, connectedPlayer)) {
|
||||
vanishedPlayers.computeIfAbsent(connectedPlayer, p -> new ArrayList<>()).add(all.getUniqueId());
|
||||
connectedPlayer.teamData.vanishedFor.add(all.getUniqueId());
|
||||
}
|
||||
if (all.isVanished() && !TAB.getInstance().getPlatform().canSee(connectedPlayer, all)) {
|
||||
vanishedPlayers.computeIfAbsent(all, p -> new ArrayList<>()).add(connectedPlayer.getUniqueId());
|
||||
all.teamData.vanishedFor.add(connectedPlayer.getUniqueId());
|
||||
}
|
||||
if (!disableChecker.isDisabledPlayer(all)) {
|
||||
if (!all.disabledNametags.get()) {
|
||||
registerTeam(all, connectedPlayer);
|
||||
}
|
||||
}
|
||||
TAB.getInstance().getPlaceholderManager().getTabExpansion().setNameTagVisibility(connectedPlayer, true);
|
||||
if (disableChecker.isDisableConditionMet(connectedPlayer)) {
|
||||
disableChecker.addDisabledPlayer(connectedPlayer);
|
||||
connectedPlayer.disabledNametags.set(true);
|
||||
return;
|
||||
}
|
||||
registerTeam(connectedPlayer);
|
||||
@@ -130,8 +120,8 @@ public class NameTag extends TabFeature implements NameTagManager, JoinListener,
|
||||
|
||||
@Override
|
||||
public void onQuit(@NotNull TabPlayer disconnectedPlayer) {
|
||||
if (!disableChecker.isDisabledPlayer(disconnectedPlayer) && !hasTeamHandlingPaused(disconnectedPlayer)) {
|
||||
String teamName = sorting.getShortTeamName(disconnectedPlayer);
|
||||
if (!disconnectedPlayer.disabledNametags.get() && !hasTeamHandlingPaused(disconnectedPlayer)) {
|
||||
String teamName = disconnectedPlayer.sortingData.getShortTeamName();
|
||||
for (TabPlayer viewer : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (viewer == disconnectedPlayer) continue; //player who just disconnected
|
||||
if (viewer.getScoreboard().containsTeam(teamName)) {
|
||||
@@ -139,25 +129,21 @@ public class NameTag extends TabFeature implements NameTagManager, JoinListener,
|
||||
}
|
||||
}
|
||||
}
|
||||
for (TabPlayer all : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (all == disconnectedPlayer) continue;
|
||||
hiddenNameTagFor.getOrDefault(all, Collections.emptySet()).remove(disconnectedPlayer); //clearing memory from API method
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServerChange(@NonNull TabPlayer p, @NonNull String from, @NonNull String to) {
|
||||
if (updateProperties(p) && !disableChecker.isDisabledPlayer(p)) updateTeamData(p);
|
||||
if (updateProperties(p) && !p.disabledNametags.get()) updateTeamData(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWorldChange(@NotNull TabPlayer changed, @NotNull String from, @NotNull String to) {
|
||||
if (updateProperties(changed) && !disableChecker.isDisabledPlayer(changed)) updateTeamData(changed);
|
||||
if (updateProperties(changed) && !changed.disabledNametags.get()) updateTeamData(changed);
|
||||
}
|
||||
|
||||
public void onDisableConditionChange(TabPlayer p, boolean disabledNow) {
|
||||
if (disabledNow) {
|
||||
unregisterTeam(p, sorting.getShortTeamName(p));
|
||||
unregisterTeam(p, p.sortingData.getShortTeamName());
|
||||
} else {
|
||||
registerTeam(p);
|
||||
}
|
||||
@@ -167,22 +153,22 @@ public class NameTag extends TabFeature implements NameTagManager, JoinListener,
|
||||
for (TabPlayer viewer : TAB.getInstance().getOnlinePlayers()) {
|
||||
updateTeamData(p, viewer);
|
||||
}
|
||||
if (redis != null) redis.updateTeam(p, sorting.getShortTeamName(p),
|
||||
if (redis != null) redis.updateTeam(p, p.sortingData.getShortTeamName(),
|
||||
p.getProperty(TabConstants.Property.TAGPREFIX).get(),
|
||||
p.getProperty(TabConstants.Property.TAGSUFFIX).get(),
|
||||
getTeamVisibility(p, p) ? NameVisibility.ALWAYS : NameVisibility.NEVER);
|
||||
}
|
||||
|
||||
public void updateTeamData(@NonNull TabPlayer p, @NonNull TabPlayer viewer) {
|
||||
if (!viewer.getScoreboard().containsTeam(sorting.getShortTeamName(p))) return;
|
||||
if (!viewer.getScoreboard().containsTeam(p.sortingData.getShortTeamName())) return;
|
||||
boolean visible = getTeamVisibility(p, viewer);
|
||||
String prefix = p.getProperty(TabConstants.Property.TAGPREFIX).getFormat(viewer);
|
||||
viewer.getScoreboard().updateTeam(
|
||||
sorting.getShortTeamName(p),
|
||||
p.sortingData.getShortTeamName(),
|
||||
prefix,
|
||||
p.getProperty(TabConstants.Property.TAGSUFFIX).getFormat(viewer),
|
||||
visible ? NameVisibility.ALWAYS : NameVisibility.NEVER,
|
||||
collisionManager.getCollision(p) ? CollisionRule.ALWAYS : CollisionRule.NEVER,
|
||||
p.teamData.getCollisionRule() ? CollisionRule.ALWAYS : CollisionRule.NEVER,
|
||||
teamOptions,
|
||||
EnumChatFormat.lastColorsOf(prefix)
|
||||
);
|
||||
@@ -208,11 +194,11 @@ public class NameTag extends TabFeature implements NameTagManager, JoinListener,
|
||||
if (!TAB.getInstance().getPlatform().canSee(viewer, p) && p != viewer) return;
|
||||
String prefix = p.getProperty(TabConstants.Property.TAGPREFIX).getFormat(viewer);
|
||||
viewer.getScoreboard().registerTeam(
|
||||
sorting.getShortTeamName(p),
|
||||
p.sortingData.getShortTeamName(),
|
||||
prefix,
|
||||
p.getProperty(TabConstants.Property.TAGSUFFIX).getFormat(viewer),
|
||||
getTeamVisibility(p, viewer) ? NameVisibility.ALWAYS : NameVisibility.NEVER,
|
||||
collisionManager.getCollision(p) ? CollisionRule.ALWAYS : CollisionRule.NEVER,
|
||||
p.teamData.getCollisionRule() ? CollisionRule.ALWAYS : CollisionRule.NEVER,
|
||||
Collections.singletonList(p.getNickname()),
|
||||
teamOptions,
|
||||
EnumChatFormat.lastColorsOf(prefix)
|
||||
@@ -226,15 +212,15 @@ public class NameTag extends TabFeature implements NameTagManager, JoinListener,
|
||||
}
|
||||
|
||||
public boolean getTeamVisibility(@NonNull TabPlayer p, @NonNull TabPlayer viewer) {
|
||||
return !hasHiddenNameTag(p) && !hasHiddenNameTag(p, viewer) && !invisibleNameTags
|
||||
&& !p.hasInvisibilityPotion() && !playersWithInvisibleNameTagView.contains(viewer);
|
||||
if (viewer.getVersion().getMinorVersion() == 8 && p.hasInvisibilityPotion()) return false;
|
||||
return !hasHiddenNameTag(p) && !hasHiddenNameTag(p, viewer) && !invisibleNameTags && !viewer.teamData.invisibleNameTagView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoginPacket(TabPlayer player) {
|
||||
if (!player.isLoaded()) return;
|
||||
for (TabPlayer all : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (!disableChecker.isDisabledPlayer(all) && all.isLoaded()) registerTeam(all, player);
|
||||
if (!all.disabledNametags.get() && all.isLoaded()) registerTeam(all, player);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,16 +230,16 @@ public class NameTag extends TabFeature implements NameTagManager, JoinListener,
|
||||
for (TabPlayer viewer : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (viewer == player) continue;
|
||||
if (!TAB.getInstance().getPlatform().canSee(viewer, player)) {
|
||||
vanishedPlayers.computeIfAbsent(player, p -> new ArrayList<>()).add(viewer.getUniqueId());
|
||||
viewer.getScoreboard().unregisterTeam(sorting.getShortTeamName(player));
|
||||
player.teamData.vanishedFor.add(viewer.getUniqueId());
|
||||
viewer.getScoreboard().unregisterTeam(player.sortingData.getShortTeamName());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (UUID id : vanishedPlayers.getOrDefault(player, Collections.emptyList())) {
|
||||
for (UUID id : player.teamData.vanishedFor) {
|
||||
TabPlayer viewer = TAB.getInstance().getPlayer(id);
|
||||
if (viewer != null) registerTeam(player, viewer);
|
||||
}
|
||||
vanishedPlayers.remove(player);
|
||||
player.teamData.vanishedFor.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,84 +255,103 @@ public class NameTag extends TabFeature implements NameTagManager, JoinListener,
|
||||
|
||||
@Override
|
||||
public void hideNameTag(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
ensureActive();
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
if (!hiddenNameTag.add(player)) return;
|
||||
updateTeamData(p);
|
||||
if (!p.teamData.hiddenNameTag) {
|
||||
p.teamData.hiddenNameTag = true;
|
||||
updateTeamData(p);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideNameTag(@NonNull me.neznamy.tab.api.TabPlayer player, @NonNull me.neznamy.tab.api.TabPlayer viewer) {
|
||||
ensureActive();
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
if (!hiddenNameTagFor.get(player).add(viewer)) return;
|
||||
if (!p.teamData.hiddenNameTagFor.add((TabPlayer) viewer)) return;
|
||||
updateTeamData(p, (TabPlayer) viewer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showNameTag(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
ensureActive();
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
if (!hiddenNameTag.remove(player)) return;
|
||||
updateTeamData(p);
|
||||
if (p.teamData.hiddenNameTag) {
|
||||
p.teamData.hiddenNameTag = false;
|
||||
updateTeamData(p);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showNameTag(@NonNull me.neznamy.tab.api.TabPlayer player, @NonNull me.neznamy.tab.api.TabPlayer viewer) {
|
||||
ensureActive();
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
if (!hiddenNameTagFor.get(player).remove(viewer)) return;
|
||||
if (!p.teamData.hiddenNameTagFor.remove((TabPlayer) viewer)) return;
|
||||
updateTeamData(p, (TabPlayer) viewer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasHiddenNameTag(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
return hiddenNameTag.contains(player);
|
||||
ensureActive();
|
||||
return ((TabPlayer)player).teamData.hiddenNameTag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasHiddenNameTag(@NonNull me.neznamy.tab.api.TabPlayer player, @NonNull me.neznamy.tab.api.TabPlayer viewer) {
|
||||
return hiddenNameTagFor.containsKey(player) && hiddenNameTagFor.get(player).contains(viewer);
|
||||
ensureActive();
|
||||
return ((TabPlayer)player).teamData.hiddenNameTagFor.contains((TabPlayer) viewer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pauseTeamHandling(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
ensureActive();
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
if (teamHandlingPaused.contains(player)) return;
|
||||
if (!disableChecker.isDisabledPlayer(p)) unregisterTeam(p, sorting.getShortTeamName(p));
|
||||
teamHandlingPaused.add(player); //adding after, so unregisterTeam method runs
|
||||
if (p.teamData.teamHandlingPaused) return;
|
||||
if (!p.disabledNametags.get()) unregisterTeam(p, p.sortingData.getShortTeamName());
|
||||
p.teamData.teamHandlingPaused = true; //setting after, so unregisterTeam method runs
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resumeTeamHandling(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
ensureActive();
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
if (!teamHandlingPaused.remove(player)) return; //removing before, so registerTeam method runs
|
||||
if (!disableChecker.isDisabledPlayer(p)) registerTeam(p);
|
||||
if (!p.teamData.teamHandlingPaused) return;
|
||||
p.teamData.teamHandlingPaused = false; //setting before, so registerTeam method runs
|
||||
if (!p.disabledNametags.get()) registerTeam(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTeamHandlingPaused(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
return teamHandlingPaused.contains(player);
|
||||
ensureActive();
|
||||
return ((TabPlayer)player).teamData.teamHandlingPaused;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCollisionRule(@NonNull me.neznamy.tab.api.TabPlayer player, Boolean collision) {
|
||||
ensureActive();
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
collisionManager.setCollisionRule(p, collision);
|
||||
if (Objects.equals(p.teamData.forcedCollision, collision)) return;
|
||||
p.teamData.forcedCollision = collision;
|
||||
updateTeamData(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getCollisionRule(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
ensureActive();
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
return collisionManager.getCollisionRule(p);
|
||||
return p.teamData.forcedCollision;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPrefix(@NonNull me.neznamy.tab.api.TabPlayer player, @Nullable String prefix) {
|
||||
ensureActive();
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
p.getProperty(TabConstants.Property.TAGPREFIX).setTemporaryValue(prefix);
|
||||
@@ -355,6 +360,7 @@ public class NameTag extends TabFeature implements NameTagManager, JoinListener,
|
||||
|
||||
@Override
|
||||
public void setSuffix(@NonNull me.neznamy.tab.api.TabPlayer player, @Nullable String suffix) {
|
||||
ensureActive();
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
p.getProperty(TabConstants.Property.TAGSUFFIX).setTemporaryValue(suffix);
|
||||
@@ -363,6 +369,7 @@ public class NameTag extends TabFeature implements NameTagManager, JoinListener,
|
||||
|
||||
@Override
|
||||
public String getCustomPrefix(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
ensureActive();
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
return p.getProperty(TabConstants.Property.TAGPREFIX).getTemporaryValue();
|
||||
@@ -370,6 +377,7 @@ public class NameTag extends TabFeature implements NameTagManager, JoinListener,
|
||||
|
||||
@Override
|
||||
public String getCustomSuffix(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
ensureActive();
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
return p.getProperty(TabConstants.Property.TAGSUFFIX).getTemporaryValue();
|
||||
@@ -378,6 +386,7 @@ public class NameTag extends TabFeature implements NameTagManager, JoinListener,
|
||||
@Override
|
||||
@NonNull
|
||||
public String getOriginalPrefix(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
ensureActive();
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
return p.getProperty(TabConstants.Property.TAGPREFIX).getOriginalRawValue();
|
||||
@@ -386,6 +395,7 @@ public class NameTag extends TabFeature implements NameTagManager, JoinListener,
|
||||
@Override
|
||||
@NonNull
|
||||
public String getOriginalSuffix(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
ensureActive();
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
return p.getProperty(TabConstants.Property.TAGSUFFIX).getOriginalRawValue();
|
||||
@@ -393,15 +403,16 @@ public class NameTag extends TabFeature implements NameTagManager, JoinListener,
|
||||
|
||||
@Override
|
||||
public void toggleNameTagVisibilityView(@NonNull me.neznamy.tab.api.TabPlayer p, boolean sendToggleMessage) {
|
||||
ensureActive();
|
||||
TabPlayer player = (TabPlayer) p;
|
||||
if (playersWithInvisibleNameTagView.contains(player)) {
|
||||
playersWithInvisibleNameTagView.remove(player);
|
||||
if (player.teamData.invisibleNameTagView) {
|
||||
player.teamData.invisibleNameTagView = false;
|
||||
if (sendToggleMessage) player.sendMessage(TAB.getInstance().getConfiguration().getMessages().getNameTagsShown(), true);
|
||||
} else {
|
||||
playersWithInvisibleNameTagView.add(player);
|
||||
player.teamData.invisibleNameTagView = true;
|
||||
if (sendToggleMessage) player.sendMessage(TAB.getInstance().getConfiguration().getMessages().getNameTagsHidden(), true);
|
||||
}
|
||||
TAB.getInstance().getPlaceholderManager().getTabExpansion().setNameTagVisibility(player, !playersWithInvisibleNameTagView.contains(player));
|
||||
TAB.getInstance().getPlaceholderManager().getTabExpansion().setNameTagVisibility(player, !player.teamData.invisibleNameTagView);
|
||||
for (TabPlayer all : TAB.getInstance().getOnlinePlayers()) {
|
||||
updateTeamData(all, player);
|
||||
}
|
||||
@@ -409,6 +420,45 @@ public class NameTag extends TabFeature implements NameTagManager, JoinListener,
|
||||
|
||||
@Override
|
||||
public boolean hasHiddenNameTagVisibilityView(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
return playersWithInvisibleNameTagView.contains(player);
|
||||
ensureActive();
|
||||
return ((TabPlayer)player).teamData.invisibleNameTagView;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class holding team data for players.
|
||||
*/
|
||||
public static class PlayerData {
|
||||
|
||||
/** Flag tracking whether this player has name tag hidden globally using API or not */
|
||||
public boolean hiddenNameTag;
|
||||
|
||||
/** Players who should not see this player's name tag */
|
||||
public final Set<TabPlayer> hiddenNameTagFor = Collections.newSetFromMap(new WeakHashMap<>());
|
||||
|
||||
/** Flag tracking whether team handling is paused or not */
|
||||
public boolean teamHandlingPaused;
|
||||
|
||||
/** Flag tracking whether this player disabled nametags on all players or not */
|
||||
public boolean invisibleNameTagView;
|
||||
|
||||
/** Players who this player is vanished for */
|
||||
public final Set<UUID> vanishedFor = new HashSet<>();
|
||||
|
||||
/** Currently used collision rule */
|
||||
public boolean collisionRule;
|
||||
|
||||
/** Forced collision rule using API */
|
||||
@Nullable
|
||||
public Boolean forcedCollision;
|
||||
|
||||
/**
|
||||
* Returns current collision rule. If forced using API, the forced value is returned.
|
||||
* Otherwise, value assigned internally based on configuration is returned.
|
||||
*
|
||||
* @return Current collision rule to use
|
||||
*/
|
||||
public boolean getCollisionRule() {
|
||||
return forcedCollision != null ? forcedCollision : collisionRule;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -21,7 +21,7 @@ public class VisibilityRefresher extends TabFeature implements Refreshable {
|
||||
|
||||
@Override
|
||||
public void refresh(@NotNull TabPlayer p, boolean force) {
|
||||
if (nameTags.getDisableChecker().isDisabledPlayer(p)) return;
|
||||
if (p.disabledNametags.get()) return;
|
||||
nameTags.updateTeamData(p);
|
||||
}
|
||||
|
||||
|
||||
+75
-49
@@ -15,34 +15,29 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.util.*;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
|
||||
@Getter
|
||||
public abstract class NameTagX extends NameTag implements UnlimitedNameTagManager {
|
||||
|
||||
//config options
|
||||
@Getter private final boolean disableOnBoats = config().getBoolean("scoreboard-teams.unlimited-nametag-mode.disable-on-boats", true);
|
||||
@Getter private final List<String> dynamicLines = new ArrayList<>(config().getStringList("scoreboard-teams.unlimited-nametag-mode.dynamic-lines", Arrays.asList(TabConstants.Property.ABOVENAME, TabConstants.Property.NAMETAG, TabConstants.Property.BELOWNAME, "another")));
|
||||
@Getter private final Map<String, Object> staticLines = config().getConfigurationSection("scoreboard-teams.unlimited-nametag-mode.static-lines");
|
||||
@Getter private final boolean armorStandsAlwaysVisible = TAB.getInstance().getConfiguration().getSecretOption("scoreboard-teams.unlimited-nametag-mode.always-visible", false);
|
||||
private final boolean disableOnBoats = config().getBoolean("scoreboard-teams.unlimited-nametag-mode.disable-on-boats", true);
|
||||
private final List<String> dynamicLines = new ArrayList<>(config().getStringList("scoreboard-teams.unlimited-nametag-mode.dynamic-lines", Arrays.asList(TabConstants.Property.ABOVENAME, TabConstants.Property.NAMETAG, TabConstants.Property.BELOWNAME, "another")));
|
||||
private final Map<String, Object> staticLines = config().getConfigurationSection("scoreboard-teams.unlimited-nametag-mode.static-lines");
|
||||
private final boolean armorStandsAlwaysVisible = TAB.getInstance().getConfiguration().getSecretOption("scoreboard-teams.unlimited-nametag-mode.always-visible", false);
|
||||
|
||||
private final Set<me.neznamy.tab.api.TabPlayer> playersDisabledWithAPI = Collections.newSetFromMap(new WeakHashMap<>());
|
||||
protected final Map<TabPlayer, ArmorStandManager> armorStandManagerMap = new WeakHashMap<>();
|
||||
private final Set<TabPlayer> playersPreviewingNameTag = Collections.newSetFromMap(new WeakHashMap<>());
|
||||
private final BiFunction<NameTagX, TabPlayer, ArmorStandManager> armorStandFunction;
|
||||
@Getter private final DisableChecker unlimitedDisableChecker;
|
||||
private final DisableChecker unlimitedDisableChecker;
|
||||
|
||||
protected NameTagX(@NonNull BiFunction<NameTagX, TabPlayer, ArmorStandManager> armorStandFunction) {
|
||||
this.armorStandFunction = armorStandFunction;
|
||||
Collections.reverse(dynamicLines);
|
||||
Condition disableCondition = Condition.getCondition(config().getString("scoreboard-teams.unlimited-nametag-mode.disable-condition"));
|
||||
unlimitedDisableChecker = new DisableChecker(getExtraFeatureName(), disableCondition, this::onUnlimitedDisableConditionChange);
|
||||
unlimitedDisableChecker = new DisableChecker(getExtraFeatureName(), disableCondition, this::onUnlimitedDisableConditionChange, p -> p.disabledUnlimitedNametags);
|
||||
TAB.getInstance().getFeatureManager().registerFeature(TabConstants.Feature.UNLIMITED_NAME_TAGS + "-Condition", unlimitedDisableChecker);
|
||||
}
|
||||
|
||||
public ArmorStandManager getArmorStandManager(@NonNull TabPlayer player) {
|
||||
return armorStandManagerMap.get(player);
|
||||
}
|
||||
|
||||
public boolean isPlayerDisabled(@NonNull TabPlayer p) {
|
||||
return getDisableChecker().isDisabledPlayer(p) || unlimitedDisableChecker.isDisabledPlayer(p) || hasTeamHandlingPaused(p) || hasDisabledArmorStands(p);
|
||||
return p.disabledNametags.get() || p.disabledUnlimitedNametags.get() || hasTeamHandlingPaused(p) || hasDisabledArmorStands(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -52,7 +47,7 @@ public abstract class NameTagX extends NameTag implements UnlimitedNameTagManage
|
||||
}
|
||||
for (TabPlayer all : TAB.getInstance().getOnlinePlayers()) {
|
||||
updateProperties(all);
|
||||
armorStandManagerMap.put(all, armorStandFunction.apply(this, all));
|
||||
all.unlimitedNametagData.armorStandManager = armorStandFunction.apply(this, all);
|
||||
if (unlimitedDisableChecker.isDisableConditionMet(all)) {
|
||||
addDisabledPlayer(all);
|
||||
}
|
||||
@@ -66,26 +61,26 @@ public abstract class NameTagX extends NameTag implements UnlimitedNameTagManage
|
||||
if (unlimitedDisableChecker.isDisableConditionMet(connectedPlayer))
|
||||
addDisabledPlayer(connectedPlayer);
|
||||
super.onJoin(connectedPlayer);
|
||||
armorStandManagerMap.put(connectedPlayer, armorStandFunction.apply(this, connectedPlayer));
|
||||
connectedPlayer.unlimitedNametagData.armorStandManager = armorStandFunction.apply(this, connectedPlayer);
|
||||
TAB.getInstance().getPlaceholderManager().getTabExpansion().setNameTagPreview(connectedPlayer, false);
|
||||
}
|
||||
|
||||
public void addDisabledPlayer(@NotNull TabPlayer player) {
|
||||
unlimitedDisableChecker.addDisabledPlayer(player);
|
||||
player.disabledUnlimitedNametags.set(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh(@NotNull TabPlayer refreshed, boolean force) {
|
||||
super.refresh(refreshed, force);
|
||||
if (isPlayerDisabled(refreshed)) return;
|
||||
getArmorStandManager(refreshed).refresh(force);
|
||||
refreshed.unlimitedNametagData.armorStandManager.refresh(force);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unload() {
|
||||
super.unload();
|
||||
for (TabPlayer p : TAB.getInstance().getOnlinePlayers()) {
|
||||
ArmorStandManager asm = getArmorStandManager(p);
|
||||
ArmorStandManager asm = p.unlimitedNametagData.armorStandManager;
|
||||
if (asm != null) {
|
||||
asm.destroy();
|
||||
} else {
|
||||
@@ -95,25 +90,21 @@ public abstract class NameTagX extends NameTag implements UnlimitedNameTagManage
|
||||
}
|
||||
|
||||
public void toggleNameTagPreview(TabPlayer player, boolean sendToggleMessage) {
|
||||
if (playersPreviewingNameTag.contains(player)) {
|
||||
if (player.unlimitedNametagData.previewing) {
|
||||
setNameTagPreview(player, false);
|
||||
if (sendToggleMessage) player.sendMessage(TAB.getInstance().getConfiguration().getMessages().getNametagPreviewOff(), true);
|
||||
playersPreviewingNameTag.remove(player);
|
||||
player.unlimitedNametagData.previewing = false;
|
||||
} else {
|
||||
setNameTagPreview(player, true);
|
||||
if (sendToggleMessage) player.sendMessage(TAB.getInstance().getConfiguration().getMessages().getNametagPreviewOn(), true);
|
||||
playersPreviewingNameTag.add(player);
|
||||
player.unlimitedNametagData.previewing = true;
|
||||
}
|
||||
TAB.getInstance().getPlaceholderManager().getTabExpansion().setNameTagPreview(player, isPreviewingNameTag(player));
|
||||
}
|
||||
|
||||
public boolean isPreviewingNameTag(@NonNull TabPlayer player) {
|
||||
return playersPreviewingNameTag.contains(player);
|
||||
TAB.getInstance().getPlaceholderManager().getTabExpansion().setNameTagPreview(player, player.unlimitedNametagData.previewing);
|
||||
}
|
||||
|
||||
public void onUnlimitedDisableConditionChange(TabPlayer p, boolean disabledNow) {
|
||||
if (!getDisableChecker().isDisabledPlayer(p)) updateTeamData(p);
|
||||
getArmorStandManager(p).refresh(true);
|
||||
if (!p.disabledNametags.get()) updateTeamData(p);
|
||||
p.unlimitedNametagData.armorStandManager.refresh(true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,7 +131,7 @@ public abstract class NameTagX extends NameTag implements UnlimitedNameTagManage
|
||||
@Override
|
||||
public boolean getTeamVisibility(@NonNull TabPlayer p, @NonNull TabPlayer viewer) {
|
||||
if (p.hasInvisibilityPotion()) return false; //1.8.x client sided bug
|
||||
if (playersWithInvisibleNameTagView.contains(viewer)) return false;
|
||||
if (viewer.teamData.invisibleNameTagView) return false;
|
||||
return isOnBoat(p) || isPlayerDisabled(p);
|
||||
}
|
||||
|
||||
@@ -158,16 +149,18 @@ public abstract class NameTagX extends NameTag implements UnlimitedNameTagManage
|
||||
|
||||
@Override
|
||||
public void hideNameTag(@NonNull me.neznamy.tab.api.TabPlayer player, @NonNull me.neznamy.tab.api.TabPlayer viewer) {
|
||||
if (hiddenNameTagFor.get(player).contains(viewer)) return;
|
||||
hiddenNameTagFor.get(player).add(viewer);
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
if (!p.teamData.hiddenNameTagFor.add((TabPlayer) viewer)) return;
|
||||
updateTeamData((TabPlayer) player, (TabPlayer) viewer);
|
||||
pauseArmorStands((TabPlayer) player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showNameTag(@NonNull me.neznamy.tab.api.TabPlayer player, @NonNull me.neznamy.tab.api.TabPlayer viewer) {
|
||||
if (!hiddenNameTagFor.get(player).contains(viewer)) return;
|
||||
hiddenNameTagFor.get(player).remove(viewer);
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
if (!p.teamData.hiddenNameTagFor.remove((TabPlayer) viewer)) return;
|
||||
updateTeamData((TabPlayer) player, (TabPlayer) viewer);
|
||||
resumeArmorStands((TabPlayer) player);
|
||||
}
|
||||
@@ -186,40 +179,45 @@ public abstract class NameTagX extends NameTag implements UnlimitedNameTagManage
|
||||
|
||||
@Override
|
||||
public void setPrefix(@NonNull me.neznamy.tab.api.TabPlayer player, String prefix) {
|
||||
ensureActive();
|
||||
super.setPrefix(player, prefix);
|
||||
rebuildNameTagLine((TabPlayer) player);
|
||||
getArmorStandManager((TabPlayer) player).refresh(true);
|
||||
((TabPlayer) player).unlimitedNametagData.armorStandManager.refresh(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSuffix(@NonNull me.neznamy.tab.api.TabPlayer player, String suffix) {
|
||||
ensureActive();
|
||||
super.setSuffix(player, suffix);
|
||||
rebuildNameTagLine((TabPlayer) player);
|
||||
getArmorStandManager((TabPlayer) player).refresh(true);
|
||||
((TabPlayer) player).unlimitedNametagData.armorStandManager.refresh(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pauseTeamHandling(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
ensureActive();
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
if (teamHandlingPaused.contains(player)) return;
|
||||
if (!getDisableChecker().isDisabledPlayer(p)) unregisterTeam(p, getSorting().getShortTeamName(p));
|
||||
teamHandlingPaused.add(player); //adding after, so unregisterTeam method runs
|
||||
if (p.teamData.teamHandlingPaused) return;
|
||||
if (!p.disabledNametags.get()) unregisterTeam(p, p.sortingData.getShortTeamName());
|
||||
p.teamData.teamHandlingPaused = true; //setting after, so unregisterTeam method runs
|
||||
pauseArmorStands(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resumeTeamHandling(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
ensureActive();
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
if (!teamHandlingPaused.contains(player)) return;
|
||||
teamHandlingPaused.remove(player); //removing before, so registerTeam method runs
|
||||
if (!getDisableChecker().isDisabledPlayer(p)) registerTeam(p);
|
||||
if (!p.teamData.teamHandlingPaused) return;
|
||||
p.teamData.teamHandlingPaused = false; //setting before, so registerTeam method runs
|
||||
if (!p.disabledNametags.get()) registerTeam(p);
|
||||
resumeArmorStands(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toggleNameTagVisibilityView(@NonNull me.neznamy.tab.api.TabPlayer player, boolean sendToggleMessage) {
|
||||
ensureActive();
|
||||
super.toggleNameTagVisibilityView(player, sendToggleMessage);
|
||||
updateNameTagVisibilityView((TabPlayer) player);
|
||||
}
|
||||
@@ -230,49 +228,55 @@ public abstract class NameTagX extends NameTag implements UnlimitedNameTagManage
|
||||
|
||||
@Override
|
||||
public void disableArmorStands(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
ensureActive();
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
if (playersDisabledWithAPI.contains(player)) return;
|
||||
playersDisabledWithAPI.add(player);
|
||||
if (p.unlimitedNametagData.disabledWithAPI) return;
|
||||
p.unlimitedNametagData.disabledWithAPI = true;
|
||||
pauseArmorStands(p);
|
||||
updateTeamData(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableArmorStands(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
ensureActive();
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
if (!playersDisabledWithAPI.contains(player)) return;
|
||||
playersDisabledWithAPI.remove(player);
|
||||
if (!p.unlimitedNametagData.disabledWithAPI) return;
|
||||
p.unlimitedNametagData.disabledWithAPI = false;
|
||||
resumeArmorStands(p);
|
||||
updateTeamData(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDisabledArmorStands(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
return playersDisabledWithAPI.contains(player);
|
||||
ensureActive();
|
||||
return ((TabPlayer)player).unlimitedNametagData.disabledWithAPI;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(@NonNull me.neznamy.tab.api.TabPlayer player, @Nullable String customName) {
|
||||
ensureActive();
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
p.getProperty(TabConstants.Property.CUSTOMTAGNAME).setTemporaryValue(customName);
|
||||
rebuildNameTagLine(p);
|
||||
getArmorStandManager(p).refresh(true);
|
||||
p.unlimitedNametagData.armorStandManager.refresh(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLine(@NonNull me.neznamy.tab.api.TabPlayer player, @NonNull String line, @Nullable String value) {
|
||||
ensureActive();
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
if (!getDefinedLines().contains(line)) throw new IllegalArgumentException("\"" + line + "\" is not a defined line. Defined lines: " + getDefinedLines());
|
||||
p.getProperty(line).setTemporaryValue(value);
|
||||
getArmorStandManager(p).refresh(true);
|
||||
p.unlimitedNametagData.armorStandManager.refresh(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCustomName(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
ensureActive();
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
return p.getProperty(TabConstants.Property.CUSTOMTAGNAME).getTemporaryValue();
|
||||
@@ -280,6 +284,7 @@ public abstract class NameTagX extends NameTag implements UnlimitedNameTagManage
|
||||
|
||||
@Override
|
||||
public String getCustomLineValue(@NonNull me.neznamy.tab.api.TabPlayer player, @NonNull String line) {
|
||||
ensureActive();
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
return p.getProperty(line).getTemporaryValue();
|
||||
@@ -288,6 +293,7 @@ public abstract class NameTagX extends NameTag implements UnlimitedNameTagManage
|
||||
@Override
|
||||
@NotNull
|
||||
public String getOriginalName(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
ensureActive();
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
return p.getProperty(TabConstants.Property.CUSTOMTAGNAME).getOriginalRawValue();
|
||||
@@ -296,6 +302,7 @@ public abstract class NameTagX extends NameTag implements UnlimitedNameTagManage
|
||||
@Override
|
||||
@NotNull
|
||||
public String getOriginalLineValue(@NonNull me.neznamy.tab.api.TabPlayer player, @NonNull String line) {
|
||||
ensureActive();
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
return p.getProperty(line).getOriginalRawValue();
|
||||
@@ -304,8 +311,27 @@ public abstract class NameTagX extends NameTag implements UnlimitedNameTagManage
|
||||
@Override
|
||||
@NotNull
|
||||
public List<String> getDefinedLines() {
|
||||
ensureActive();
|
||||
List<String> lines = new ArrayList<>(dynamicLines);
|
||||
lines.addAll(staticLines.keySet());
|
||||
return lines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class storing unlimited nametag data for players.
|
||||
*/
|
||||
public static class PlayerData {
|
||||
|
||||
/** Armor stand manager */
|
||||
public ArmorStandManager armorStandManager;
|
||||
|
||||
/** Whether player is previewing armor stands or not */
|
||||
public boolean previewing;
|
||||
|
||||
/** Whether armor stands are disabled via API or not */
|
||||
public boolean disabledWithAPI;
|
||||
|
||||
/** Whether player is riding a boat or not */
|
||||
public boolean onBoat;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,10 @@
|
||||
package me.neznamy.tab.shared.features.redis;
|
||||
|
||||
import lombok.*;
|
||||
import me.neznamy.tab.shared.TabConstants.Permission;
|
||||
import me.neznamy.tab.shared.chat.TabComponent;
|
||||
import me.neznamy.tab.shared.platform.Scoreboard;
|
||||
import me.neznamy.tab.shared.platform.TabList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.UUID;
|
||||
@@ -10,16 +14,15 @@ import java.util.UUID;
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
public class RedisPlayer {
|
||||
|
||||
/** Tablist UUID of the player */
|
||||
@NotNull
|
||||
private UUID uniqueId;
|
||||
private final UUID uniqueId;
|
||||
|
||||
/** Player's real name */
|
||||
@NotNull
|
||||
private String name;
|
||||
private final String name;
|
||||
|
||||
/** Player's name as seen in game profile */
|
||||
@NotNull
|
||||
@@ -33,5 +36,60 @@ public class RedisPlayer {
|
||||
private boolean vanished;
|
||||
|
||||
/** Whether player is staff or not */
|
||||
private boolean staff;
|
||||
private final boolean staff;
|
||||
|
||||
/** Belowname number for 1.20.2- */
|
||||
private int belowNameNumber;
|
||||
|
||||
/** Belowname NumberFormat for 1.20.3+ */
|
||||
private TabComponent belowNameFancy;
|
||||
|
||||
/** Player's skin for global playerlist */
|
||||
private TabList.Skin skin;
|
||||
|
||||
/** Tablist display name */
|
||||
private TabComponent tabFormat;
|
||||
|
||||
/** Scoreboard team name */
|
||||
private String teamName;
|
||||
|
||||
/** Nametag prefix */
|
||||
private String tagPrefix;
|
||||
|
||||
/** Nametag suffix */
|
||||
private String tagSuffix;
|
||||
|
||||
/** Nametag visibility rule */
|
||||
private Scoreboard.NameVisibility nameVisibility;
|
||||
|
||||
/** Playerlist objective number for 1.20.2- */
|
||||
private int playerlistNumber;
|
||||
|
||||
/** Playerlist objective NumberFormat for 1.20.3+ */
|
||||
private TabComponent playerlistFancy;
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters.
|
||||
*
|
||||
* @param uniqueId
|
||||
* Player's tablist UUID
|
||||
* @param name
|
||||
* Player's real name
|
||||
* @param nickname
|
||||
* Player's nickname in game profile
|
||||
* @param server
|
||||
* Player's server
|
||||
* @param vanished
|
||||
* Whether player is vanished or not
|
||||
* @param staff
|
||||
* Whether player has {@link Permission#STAFF} permission or not
|
||||
*/
|
||||
public RedisPlayer(@NotNull UUID uniqueId, @NotNull String name, @NotNull String nickname, @NotNull String server, boolean vanished, boolean staff) {
|
||||
this.uniqueId = uniqueId;
|
||||
this.name = name;
|
||||
this.nickname = nickname;
|
||||
this.server = server;
|
||||
this.vanished = vanished;
|
||||
this.staff = staff;
|
||||
}
|
||||
}
|
||||
+8
-13
@@ -14,18 +14,13 @@ import me.neznamy.tab.shared.features.redis.message.RedisMessage;
|
||||
import me.neznamy.tab.shared.platform.TabPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
public class RedisBelowName extends RedisFeature {
|
||||
|
||||
private final RedisSupport redisSupport;
|
||||
@Getter private final BelowName belowName;
|
||||
|
||||
@Getter private final Map<RedisPlayer, Integer> values = new WeakHashMap<>();
|
||||
@Getter private final Map<RedisPlayer, String> fancyValues = new WeakHashMap<>();
|
||||
|
||||
public RedisBelowName(@NotNull RedisSupport redisSupport, @NotNull BelowName belowName) {
|
||||
this.redisSupport = redisSupport;
|
||||
this.belowName = belowName;
|
||||
@@ -38,9 +33,9 @@ public class RedisBelowName extends RedisFeature {
|
||||
player.getScoreboard().setScore(
|
||||
BelowName.OBJECTIVE_NAME,
|
||||
redis.getNickname(),
|
||||
values.get(redis),
|
||||
redis.getBelowNameNumber(),
|
||||
null, // Unused by this objective slot
|
||||
TabComponent.optimized(fancyValues.get(redis))
|
||||
redis.getBelowNameFancy()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -51,9 +46,9 @@ public class RedisBelowName extends RedisFeature {
|
||||
viewer.getScoreboard().setScore(
|
||||
BelowName.OBJECTIVE_NAME,
|
||||
player.getNickname(),
|
||||
values.get(player),
|
||||
player.getBelowNameNumber(),
|
||||
null, // Unused by this objective slot
|
||||
TabComponent.optimized(fancyValues.get(player))
|
||||
player.getBelowNameFancy()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -66,8 +61,8 @@ public class RedisBelowName extends RedisFeature {
|
||||
|
||||
@Override
|
||||
public void read(@NotNull ByteArrayDataInput in, @NotNull RedisPlayer player) {
|
||||
values.put(player, in.readInt());
|
||||
fancyValues.put(player, in.readUTF());
|
||||
player.setBelowNameNumber(in.readInt());
|
||||
player.setBelowNameFancy(TabComponent.optimized(in.readUTF()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -101,8 +96,8 @@ public class RedisBelowName extends RedisFeature {
|
||||
public void process(@NotNull RedisSupport redisSupport) {
|
||||
RedisPlayer target = redisSupport.getRedisPlayers().get(playerId);
|
||||
if (target == null) return; // Print warn?
|
||||
values.put(target, value);
|
||||
fancyValues.put(target, fancyValue);
|
||||
target.setBelowNameNumber(value);
|
||||
target.setBelowNameFancy(TabComponent.optimized(fancyValue));
|
||||
onJoin(target);
|
||||
}
|
||||
}
|
||||
|
||||
+4
-10
@@ -5,7 +5,6 @@ import com.google.common.io.ByteArrayDataOutput;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.TabConstants;
|
||||
import me.neznamy.tab.shared.chat.TabComponent;
|
||||
import me.neznamy.tab.shared.features.GlobalPlayerList;
|
||||
import me.neznamy.tab.shared.features.redis.RedisPlayer;
|
||||
import me.neznamy.tab.shared.features.redis.RedisSupport;
|
||||
@@ -13,15 +12,11 @@ import me.neznamy.tab.shared.platform.TabPlayer;
|
||||
import me.neznamy.tab.shared.platform.TabList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class RedisGlobalPlayerList extends RedisFeature {
|
||||
|
||||
private final RedisSupport redisSupport;
|
||||
private final GlobalPlayerList globalPlayerList;
|
||||
private final Map<RedisPlayer, TabList.Skin> skins = new WeakHashMap<>();
|
||||
|
||||
@Override
|
||||
public void onJoin(@NotNull TabPlayer player) {
|
||||
@@ -84,7 +79,7 @@ public class RedisGlobalPlayerList extends RedisFeature {
|
||||
if (in.readBoolean()) {
|
||||
signature = in.readUTF();
|
||||
}
|
||||
skins.put(player, new TabList.Skin(value, signature));
|
||||
player.setSkin(new TabList.Skin(value, signature));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,10 +94,9 @@ public class RedisGlobalPlayerList extends RedisFeature {
|
||||
return globalPlayerList.getServerGroup(viewer.getServer()).equals(globalPlayerList.getServerGroup(target.getServer()));
|
||||
}
|
||||
|
||||
private @NotNull TabList.Entry getEntry(@NotNull RedisPlayer player) {
|
||||
return new TabList.Entry(player.getUniqueId(), player.getNickname(), skins.get(player), 0, 0,
|
||||
redisSupport.getRedisPlayerList() == null ? null :
|
||||
TabComponent.optimized(redisSupport.getRedisPlayerList().getFormat(player)));
|
||||
@NotNull
|
||||
private TabList.Entry getEntry(@NotNull RedisPlayer player) {
|
||||
return new TabList.Entry(player.getUniqueId(), player.getNickname(), player.getSkin(), true, 0, 0, player.getTabFormat());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+5
-10
@@ -21,7 +21,6 @@ public class RedisPlayerList extends RedisFeature {
|
||||
|
||||
private final RedisSupport redisSupport;
|
||||
@Getter private final PlayerList playerList;
|
||||
private final Map<RedisPlayer, String> values = new WeakHashMap<>();
|
||||
|
||||
public RedisPlayerList(@NotNull RedisSupport redisSupport, @NotNull PlayerList playerList) {
|
||||
this.redisSupport = redisSupport;
|
||||
@@ -33,7 +32,7 @@ public class RedisPlayerList extends RedisFeature {
|
||||
public void onJoin(@NotNull TabPlayer player) {
|
||||
if (player.getVersion().getMinorVersion() < 8) return;
|
||||
for (RedisPlayer redis : redisSupport.getRedisPlayers().values()) {
|
||||
player.getTabList().updateDisplayName(redis.getUniqueId(), TabComponent.optimized(values.get(redis)));
|
||||
player.getTabList().updateDisplayName(redis.getUniqueId(), redis.getTabFormat());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +40,7 @@ public class RedisPlayerList extends RedisFeature {
|
||||
public void onJoin(@NotNull RedisPlayer player) {
|
||||
for (TabPlayer viewer : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (viewer.getVersion().getMinorVersion() < 8) continue;
|
||||
viewer.getTabList().updateDisplayName(player.getUniqueId(), TabComponent.optimized(values.get(player)));
|
||||
viewer.getTabList().updateDisplayName(player.getUniqueId(), player.getTabFormat());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,11 +58,7 @@ public class RedisPlayerList extends RedisFeature {
|
||||
|
||||
@Override
|
||||
public void read(@NotNull ByteArrayDataInput in, @NotNull RedisPlayer player) {
|
||||
values.put(player, in.readUTF());
|
||||
}
|
||||
|
||||
public String getFormat(@NotNull RedisPlayer player) {
|
||||
return values.get(player);
|
||||
player.setTabFormat(TabComponent.optimized(in.readUTF()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -71,7 +66,7 @@ public class RedisPlayerList extends RedisFeature {
|
||||
if (player.isVanished()) return;
|
||||
for (TabPlayer viewer : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (viewer.getVersion().getMinorVersion() < 8) continue;
|
||||
viewer.getTabList().updateDisplayName(player.getUniqueId(), TabComponent.optimized(getFormat(player)));
|
||||
viewer.getTabList().updateDisplayName(player.getUniqueId(), player.getTabFormat());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +93,7 @@ public class RedisPlayerList extends RedisFeature {
|
||||
public void process(@NotNull RedisSupport redisSupport) {
|
||||
RedisPlayer target = redisSupport.getRedisPlayers().get(playerId);
|
||||
if (target == null) return; // Print warn?
|
||||
values.put(target, format);
|
||||
target.setTabFormat(TabComponent.optimized(format));
|
||||
onJoin(target);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,10 +24,6 @@ public class RedisTeams extends RedisFeature {
|
||||
|
||||
private final RedisSupport redisSupport;
|
||||
private final NameTag nameTags;
|
||||
private final Map<RedisPlayer, String> teamNames = new WeakHashMap<>();
|
||||
private final Map<RedisPlayer, String> prefixes = new WeakHashMap<>();
|
||||
private final Map<RedisPlayer, String> suffixes = new WeakHashMap<>();
|
||||
private final Map<RedisPlayer, NameVisibility> nameVisibilities = new WeakHashMap<>();
|
||||
|
||||
public RedisTeams(@NotNull RedisSupport redisSupport, @NotNull NameTag nameTags) {
|
||||
this.redisSupport = redisSupport;
|
||||
@@ -38,31 +34,31 @@ public class RedisTeams extends RedisFeature {
|
||||
@Override
|
||||
public void onJoin(@NotNull TabPlayer player) {
|
||||
for (RedisPlayer redis : redisSupport.getRedisPlayers().values()) {
|
||||
player.getScoreboard().registerTeam(teamNames.get(redis), prefixes.get(redis), suffixes.get(redis),
|
||||
nameVisibilities.get(redis), CollisionRule.ALWAYS,
|
||||
Collections.singletonList(redis.getNickname()), 2, EnumChatFormat.lastColorsOf(prefixes.get(redis)));
|
||||
player.getScoreboard().registerTeam(redis.getTeamName(), redis.getTagPrefix(), redis.getTagSuffix(),
|
||||
redis.getNameVisibility(), CollisionRule.ALWAYS,
|
||||
Collections.singletonList(redis.getNickname()), 2, EnumChatFormat.lastColorsOf(redis.getTagPrefix()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onJoin(@NotNull RedisPlayer player) {
|
||||
for (TabPlayer viewer : TAB.getInstance().getOnlinePlayers()) {
|
||||
viewer.getScoreboard().registerTeam(teamNames.get(player), prefixes.get(player), suffixes.get(player),
|
||||
nameVisibilities.get(player), CollisionRule.ALWAYS,
|
||||
Collections.singletonList(player.getNickname()), 2, EnumChatFormat.lastColorsOf(prefixes.get(player)));
|
||||
viewer.getScoreboard().registerTeam(player.getTeamName(), player.getTagPrefix(), player.getTagSuffix(),
|
||||
player.getNameVisibility(), CollisionRule.ALWAYS,
|
||||
Collections.singletonList(player.getNickname()), 2, EnumChatFormat.lastColorsOf(player.getTagPrefix()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onQuit(@NotNull RedisPlayer player) {
|
||||
for (TabPlayer viewer : TAB.getInstance().getOnlinePlayers()) {
|
||||
viewer.getScoreboard().unregisterTeam(teamNames.get(player));
|
||||
viewer.getScoreboard().unregisterTeam(player.getTeamName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(@NotNull ByteArrayDataOutput out, @NotNull TabPlayer player) {
|
||||
out.writeUTF(nameTags.getSorting().getShortTeamName(player));
|
||||
out.writeUTF(player.sortingData.getShortTeamName());
|
||||
out.writeUTF(player.getProperty(TabConstants.Property.TAGPREFIX).get());
|
||||
out.writeUTF(player.getProperty(TabConstants.Property.TAGSUFFIX).get());
|
||||
out.writeUTF((nameTags.getTeamVisibility(player, player) ? NameVisibility.ALWAYS : NameVisibility.NEVER).toString());
|
||||
@@ -72,10 +68,10 @@ public class RedisTeams extends RedisFeature {
|
||||
public void read(@NotNull ByteArrayDataInput in, @NotNull RedisPlayer player) {
|
||||
String teamName = in.readUTF();
|
||||
teamName = checkTeamName(player, teamName.substring(0, teamName.length()-1), 65);
|
||||
teamNames.put(player, teamName);
|
||||
prefixes.put(player, in.readUTF());
|
||||
suffixes.put(player, in.readUTF());
|
||||
nameVisibilities.put(player, NameVisibility.getByName(in.readUTF()));
|
||||
player.setTeamName(teamName);
|
||||
player.setTagPrefix(in.readUTF());
|
||||
player.setTagSuffix(in.readUTF());
|
||||
player.setNameVisibility(NameVisibility.getByName(in.readUTF()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -86,13 +82,13 @@ public class RedisTeams extends RedisFeature {
|
||||
private @NotNull String checkTeamName(@NotNull RedisPlayer player, @NotNull String currentName15, int id) {
|
||||
String potentialTeamName = currentName15 + (char)id;
|
||||
for (TabPlayer all : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (nameTags.getSorting().getShortTeamName(all).equals(potentialTeamName)) {
|
||||
if (all.sortingData.getShortTeamName().equals(potentialTeamName)) {
|
||||
return checkTeamName(player, currentName15, id+1);
|
||||
}
|
||||
}
|
||||
for (RedisPlayer all : redisSupport.getRedisPlayers().values()) {
|
||||
if (all == player) continue;
|
||||
if (teamNames.containsKey(all) && teamNames.get(all).equals(potentialTeamName)) {
|
||||
if (potentialTeamName.equals(all.getTeamName())) {
|
||||
return checkTeamName(player, currentName15, id+1);
|
||||
}
|
||||
}
|
||||
@@ -131,11 +127,11 @@ public class RedisTeams extends RedisFeature {
|
||||
public void process(@NotNull RedisSupport redisSupport) {
|
||||
RedisPlayer target = redisSupport.getRedisPlayers().get(playerId);
|
||||
if (target == null) return; // Print warn?
|
||||
String oldTeamName = teamNames.get(target);
|
||||
String oldTeamName = target.getTeamName();
|
||||
String newTeamName = checkTeamName(target, teamName.substring(0, teamName.length()-1), 65);
|
||||
teamNames.put(target, newTeamName);
|
||||
prefixes.put(target, prefix);
|
||||
suffixes.put(target, suffix);
|
||||
target.setTeamName(newTeamName);
|
||||
target.setTagPrefix(prefix);
|
||||
target.setTagSuffix(suffix);
|
||||
if (!oldTeamName.equals(newTeamName)) {
|
||||
for (TabPlayer viewer : TAB.getInstance().getOnlinePlayers()) {
|
||||
viewer.getScoreboard().unregisterTeam(oldTeamName);
|
||||
|
||||
+8
-13
@@ -14,18 +14,13 @@ import me.neznamy.tab.shared.features.redis.message.RedisMessage;
|
||||
import me.neznamy.tab.shared.platform.TabPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
public class RedisYellowNumber extends RedisFeature {
|
||||
|
||||
private final RedisSupport redisSupport;
|
||||
@Getter private final YellowNumber yellowNumber;
|
||||
|
||||
@Getter private final Map<RedisPlayer, Integer> values = new WeakHashMap<>();
|
||||
@Getter private final Map<RedisPlayer, String> fancyValues = new WeakHashMap<>();
|
||||
|
||||
public RedisYellowNumber(@NotNull RedisSupport redisSupport, @NotNull YellowNumber yellowNumber) {
|
||||
this.redisSupport = redisSupport;
|
||||
this.yellowNumber = yellowNumber;
|
||||
@@ -38,9 +33,9 @@ public class RedisYellowNumber extends RedisFeature {
|
||||
player.getScoreboard().setScore(
|
||||
YellowNumber.OBJECTIVE_NAME,
|
||||
redis.getNickname(),
|
||||
values.get(redis),
|
||||
redis.getPlayerlistNumber(),
|
||||
null, // Unused by this objective slot
|
||||
TabComponent.optimized(fancyValues.get(redis))
|
||||
redis.getPlayerlistFancy()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -51,9 +46,9 @@ public class RedisYellowNumber extends RedisFeature {
|
||||
viewer.getScoreboard().setScore(
|
||||
YellowNumber.OBJECTIVE_NAME,
|
||||
player.getNickname(),
|
||||
values.get(player),
|
||||
player.getPlayerlistNumber(),
|
||||
null, // Unused by this objective slot
|
||||
TabComponent.optimized(fancyValues.get(player))
|
||||
player.getPlayerlistFancy()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -66,8 +61,8 @@ public class RedisYellowNumber extends RedisFeature {
|
||||
|
||||
@Override
|
||||
public void read(@NotNull ByteArrayDataInput in, @NotNull RedisPlayer player) {
|
||||
values.put(player, in.readInt());
|
||||
fancyValues.put(player, in.readUTF());
|
||||
player.setPlayerlistNumber(in.readInt());
|
||||
player.setPlayerlistFancy(TabComponent.optimized(in.readUTF()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -101,8 +96,8 @@ public class RedisYellowNumber extends RedisFeature {
|
||||
public void process(@NotNull RedisSupport redisSupport) {
|
||||
RedisPlayer target = redisSupport.getRedisPlayers().get(playerId);
|
||||
if (target == null) return; // Print warn?
|
||||
values.put(target, value);
|
||||
fancyValues.put(target, fancyValue);
|
||||
target.setPlayerlistNumber(value);
|
||||
target.setPlayerlistFancy(TabComponent.optimized(fancyValue));
|
||||
onJoin(target);
|
||||
}
|
||||
}
|
||||
|
||||
+50
-42
@@ -150,19 +150,11 @@ public class ScoreboardImpl extends TabFeature implements me.neznamy.tab.api.sco
|
||||
((ScoreboardLine)s).register(p);
|
||||
}
|
||||
players.add(p);
|
||||
manager.getActiveScoreboards().put(p, this);
|
||||
p.scoreboardData.activeScoreboard = this;
|
||||
recalculateScores(p);
|
||||
TAB.getInstance().getPlaceholderManager().getTabExpansion().setScoreboardName(p, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregister() {
|
||||
for (TabPlayer all : players.toArray(new TabPlayer[0])) {
|
||||
removePlayer(all);
|
||||
}
|
||||
players.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters player from this scoreboard.
|
||||
*
|
||||
@@ -176,7 +168,7 @@ public class ScoreboardImpl extends TabFeature implements me.neznamy.tab.api.sco
|
||||
if (((ScoreboardLine)line).isShownTo(p))
|
||||
p.getScoreboard().unregisterTeam(((ScoreboardLine)line).getTeamName());
|
||||
}
|
||||
manager.getActiveScoreboards().remove(p);
|
||||
p.scoreboardData.activeScoreboard = null;
|
||||
TAB.getInstance().getPlaceholderManager().getTabExpansion().setScoreboardName(p, "");
|
||||
}
|
||||
|
||||
@@ -197,38 +189,6 @@ public class ScoreboardImpl extends TabFeature implements me.neznamy.tab.api.sco
|
||||
return "Updating Scoreboard title";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTitle(@NonNull String title) {
|
||||
this.title = title;
|
||||
for (TabPlayer p : players) {
|
||||
p.setProperty(this, titleProperty, title);
|
||||
refresh(p, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLine(@NonNull String text) {
|
||||
StableDynamicLine line = new StableDynamicLine(this, lines.size()+1, text);
|
||||
TAB.getInstance().getFeatureManager().registerFeature(TabConstants.Feature.scoreboardLine(name, lines.size()), line);
|
||||
lines.add(line);
|
||||
for (TabPlayer p : players) {
|
||||
line.register(p);
|
||||
recalculateScores(p);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeLine(int index) {
|
||||
if (index < 0 || index >= lines.size()) throw new IndexOutOfBoundsException("Index " + index + " is out of range (0 - " + (lines.size()-1) + ")");
|
||||
ScoreboardLine line = (ScoreboardLine) lines.get(index);
|
||||
lines.remove(line);
|
||||
for (TabPlayer p : players) {
|
||||
line.unregister(p);
|
||||
recalculateScores(p);
|
||||
}
|
||||
TAB.getInstance().getFeatureManager().unregisterFeature(TabConstants.Feature.scoreboardLine(name, index));
|
||||
}
|
||||
|
||||
/**
|
||||
* Recalculate scores for each line if using numbers. This takes into
|
||||
* consideration lines that are not visible.
|
||||
@@ -271,4 +231,52 @@ public class ScoreboardImpl extends TabFeature implements me.neznamy.tab.api.sco
|
||||
public String getFeatureName() {
|
||||
return manager.getFeatureName();
|
||||
}
|
||||
|
||||
// ------------------
|
||||
// API Implementation
|
||||
// ------------------
|
||||
|
||||
@Override
|
||||
public void setTitle(@NonNull String title) {
|
||||
ensureActive();
|
||||
this.title = title;
|
||||
for (TabPlayer p : players) {
|
||||
p.setProperty(this, titleProperty, title);
|
||||
refresh(p, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLine(@NonNull String text) {
|
||||
ensureActive();
|
||||
StableDynamicLine line = new StableDynamicLine(this, lines.size()+1, text);
|
||||
TAB.getInstance().getFeatureManager().registerFeature(TabConstants.Feature.scoreboardLine(name, lines.size()), line);
|
||||
lines.add(line);
|
||||
for (TabPlayer p : players) {
|
||||
line.register(p);
|
||||
recalculateScores(p);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeLine(int index) {
|
||||
ensureActive();
|
||||
if (index < 0 || index >= lines.size()) throw new IndexOutOfBoundsException("Index " + index + " is out of range (0 - " + (lines.size()-1) + ")");
|
||||
ScoreboardLine line = (ScoreboardLine) lines.get(index);
|
||||
lines.remove(line);
|
||||
for (TabPlayer p : players) {
|
||||
line.unregister(p);
|
||||
recalculateScores(p);
|
||||
}
|
||||
TAB.getInstance().getFeatureManager().unregisterFeature(TabConstants.Feature.scoreboardLine(name, index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregister() {
|
||||
ensureActive();
|
||||
for (TabPlayer all : players.toArray(new TabPlayer[0])) {
|
||||
removePlayer(all);
|
||||
}
|
||||
players.clear();
|
||||
}
|
||||
}
|
||||
+140
-107
@@ -45,12 +45,6 @@ public class ScoreboardManagerImpl extends TabFeature implements ScoreboardManag
|
||||
@Nullable
|
||||
private me.neznamy.tab.api.scoreboard.Scoreboard announcement;
|
||||
|
||||
private final Set<TabPlayer> joinDelayed = Collections.newSetFromMap(new WeakHashMap<>());
|
||||
private final WeakHashMap<me.neznamy.tab.api.TabPlayer, ScoreboardImpl> forcedScoreboard = new WeakHashMap<>();
|
||||
@Getter private final WeakHashMap<me.neznamy.tab.api.TabPlayer, ScoreboardImpl> activeScoreboards = new WeakHashMap<>();
|
||||
private final Set<me.neznamy.tab.api.TabPlayer> visiblePlayers = Collections.newSetFromMap(new WeakHashMap<>());
|
||||
@Getter private final WeakHashMap<TabPlayer, String> otherPluginScoreboards = new WeakHashMap<>();
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
Map<String, Map<String, Object>> map = config().getConfigurationSection("scoreboard.scoreboards");
|
||||
@@ -85,8 +79,8 @@ public class ScoreboardManagerImpl extends TabFeature implements ScoreboardManag
|
||||
|
||||
@Override
|
||||
public void refresh(@NotNull TabPlayer p, boolean force) {
|
||||
if (forcedScoreboard.containsKey(p) || !hasScoreboardVisible(p) ||
|
||||
announcement != null || otherPluginScoreboards.containsKey(p) || joinDelayed.contains(p)) return;
|
||||
if (p.scoreboardData.forcedScoreboard != null || !hasScoreboardVisible(p) ||
|
||||
announcement != null || p.scoreboardData.otherPluginScoreboard != null || p.scoreboardData.joinDelayed) return;
|
||||
sendHighestScoreboard(p);
|
||||
}
|
||||
|
||||
@@ -108,10 +102,11 @@ public class ScoreboardManagerImpl extends TabFeature implements ScoreboardManag
|
||||
TAB.getInstance().getPlaceholderManager().getTabExpansion().setScoreboardName(connectedPlayer, "");
|
||||
TAB.getInstance().getPlaceholderManager().getTabExpansion().setScoreboardVisible(connectedPlayer, false);
|
||||
if (joinDelay > 0) {
|
||||
joinDelayed.add(connectedPlayer);
|
||||
connectedPlayer.scoreboardData.joinDelayed = true;
|
||||
TAB.getInstance().getCPUManager().runTaskLater(joinDelay, getFeatureName(), TabConstants.CpuUsageCategory.PLAYER_JOIN, () -> {
|
||||
if (!otherPluginScoreboards.containsKey(connectedPlayer)) setScoreboardVisible(connectedPlayer, hiddenByDefault == sbOffPlayers.contains(connectedPlayer.getName()), false);
|
||||
joinDelayed.remove(connectedPlayer);
|
||||
if (connectedPlayer.scoreboardData.otherPluginScoreboard == null)
|
||||
setScoreboardVisible(connectedPlayer, hiddenByDefault == sbOffPlayers.contains(connectedPlayer.getName()), false);
|
||||
connectedPlayer.scoreboardData.joinDelayed = false;
|
||||
});
|
||||
} else {
|
||||
setScoreboardVisible(connectedPlayer, hiddenByDefault == sbOffPlayers.contains(connectedPlayer.getName()), false);
|
||||
@@ -127,7 +122,7 @@ public class ScoreboardManagerImpl extends TabFeature implements ScoreboardManag
|
||||
public void sendHighestScoreboard(@NonNull TabPlayer p) {
|
||||
if (!hasScoreboardVisible(p)) return;
|
||||
ScoreboardImpl scoreboard = (ScoreboardImpl) detectHighestScoreboard(p);
|
||||
ScoreboardImpl current = activeScoreboards.get(p);
|
||||
ScoreboardImpl current = p.scoreboardData.activeScoreboard;
|
||||
if (scoreboard != current) {
|
||||
if (current != null) {
|
||||
current.removePlayer(p);
|
||||
@@ -145,9 +140,9 @@ public class ScoreboardManagerImpl extends TabFeature implements ScoreboardManag
|
||||
* player to unregister scoreboard to
|
||||
*/
|
||||
public void unregisterScoreboard(@NonNull TabPlayer p) {
|
||||
if (activeScoreboards.containsKey(p)) {
|
||||
activeScoreboards.get(p).removePlayer(p);
|
||||
activeScoreboards.remove(p);
|
||||
if (p.scoreboardData.activeScoreboard != null) {
|
||||
p.scoreboardData.activeScoreboard.removePlayer(p);
|
||||
p.scoreboardData.activeScoreboard = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,7 +154,7 @@ public class ScoreboardManagerImpl extends TabFeature implements ScoreboardManag
|
||||
* @return highest scoreboard player should see
|
||||
*/
|
||||
public @Nullable me.neznamy.tab.api.scoreboard.Scoreboard detectHighestScoreboard(@NonNull TabPlayer p) {
|
||||
if (forcedScoreboard.containsKey(p)) return forcedScoreboard.get(p);
|
||||
if (p.scoreboardData.forcedScoreboard != null) return p.scoreboardData.forcedScoreboard;
|
||||
for (me.neznamy.tab.api.scoreboard.Scoreboard sb : definedScoreboards) {
|
||||
if (((ScoreboardImpl)sb).isConditionMet(p)) return sb;
|
||||
}
|
||||
@@ -179,8 +174,8 @@ public class ScoreboardManagerImpl extends TabFeature implements ScoreboardManag
|
||||
public void onDisplayObjective(@NotNull TabPlayer receiver, int slot, @NotNull String objective) {
|
||||
if (respectOtherPlugins && slot == Scoreboard.DisplaySlot.SIDEBAR && !objective.equals(OBJECTIVE_NAME)) {
|
||||
TAB.getInstance().debug("Player " + receiver.getName() + " received scoreboard called " + objective + ", hiding TAB one.");
|
||||
otherPluginScoreboards.put(receiver, objective);
|
||||
ScoreboardImpl sb = activeScoreboards.get(receiver);
|
||||
receiver.scoreboardData.otherPluginScoreboard = objective;
|
||||
ScoreboardImpl sb = receiver.scoreboardData.activeScoreboard;
|
||||
if (sb != null) {
|
||||
TAB.getInstance().getCPUManager().runMeasuredTask(getFeatureName(), TabConstants.CpuUsageCategory.SCOREBOARD_PACKET_CHECK, () -> sb.removePlayer(receiver));
|
||||
}
|
||||
@@ -189,32 +184,112 @@ public class ScoreboardManagerImpl extends TabFeature implements ScoreboardManag
|
||||
|
||||
@Override
|
||||
public void onObjective(@NotNull TabPlayer receiver, int action, @NotNull String objective) {
|
||||
if (respectOtherPlugins && action == 1 && otherPluginScoreboards.containsKey(receiver) && otherPluginScoreboards.get(receiver).equals(objective)) {
|
||||
if (respectOtherPlugins && action == Scoreboard.ObjectiveAction.UNREGISTER && objective.equals(receiver.scoreboardData.otherPluginScoreboard)) {
|
||||
TAB.getInstance().debug("Player " + receiver.getName() + " no longer has another scoreboard, sending TAB one.");
|
||||
otherPluginScoreboards.remove(receiver);
|
||||
receiver.scoreboardData.otherPluginScoreboard = null;
|
||||
TAB.getInstance().getCPUManager().runMeasuredTask(getFeatureName(), TabConstants.CpuUsageCategory.SCOREBOARD_PACKET_CHECK, () -> sendHighestScoreboard(receiver));
|
||||
}
|
||||
}
|
||||
|
||||
private void savePlayers() {
|
||||
synchronized (sbOffPlayers) {
|
||||
TAB.getInstance().getConfiguration().getPlayerDataFile().set("scoreboard-off", new ArrayList<>(sbOffPlayers));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull me.neznamy.tab.api.scoreboard.Scoreboard createScoreboard(@NonNull String name, @NonNull String title, @NonNull List<String> lines) {
|
||||
public void onQuit(@NotNull TabPlayer disconnectedPlayer) {
|
||||
ScoreboardImpl sb = disconnectedPlayer.scoreboardData.activeScoreboard;
|
||||
if (sb != null) {
|
||||
sb.removePlayerFromSet(disconnectedPlayer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoginPacket(TabPlayer player) {
|
||||
if (!player.isLoaded()) return;
|
||||
player.scoreboardData.otherPluginScoreboard = null;
|
||||
ScoreboardImpl scoreboard = player.scoreboardData.activeScoreboard;
|
||||
if (scoreboard != null) {
|
||||
scoreboard.removePlayerFromSet(player);
|
||||
scoreboard.addPlayer(player);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getFeatureName() {
|
||||
return "Scoreboard";
|
||||
}
|
||||
|
||||
// ------------------
|
||||
// API Implementation
|
||||
// ------------------
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public me.neznamy.tab.api.scoreboard.Scoreboard createScoreboard(@NonNull String name, @NonNull String title, @NonNull List<String> lines) {
|
||||
ensureActive();
|
||||
me.neznamy.tab.api.scoreboard.Scoreboard sb = new ScoreboardImpl(this, name, title, lines, true);
|
||||
registeredScoreboards.put(name, sb);
|
||||
definedScoreboards = registeredScoreboards.values().toArray(new me.neznamy.tab.api.scoreboard.Scoreboard[0]);
|
||||
return sb;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showScoreboard(@NonNull me.neznamy.tab.api.TabPlayer player, @NonNull me.neznamy.tab.api.scoreboard.Scoreboard scoreboard) {
|
||||
ensureActive();
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
|
||||
if (p.scoreboardData.forcedScoreboard != null) {
|
||||
p.scoreboardData.forcedScoreboard.removePlayer(p);
|
||||
}
|
||||
p.scoreboardData.forcedScoreboard = (ScoreboardImpl) scoreboard;
|
||||
|
||||
if (p.scoreboardData.activeScoreboard != null) {
|
||||
p.scoreboardData.activeScoreboard.removePlayer(p);
|
||||
p.scoreboardData.activeScoreboard = null;
|
||||
}
|
||||
|
||||
if (hasScoreboardVisible(player)) ((ScoreboardImpl) scoreboard).addPlayer(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCustomScoreboard(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
ensureActive();
|
||||
return ((TabPlayer)player).scoreboardData.forcedScoreboard != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetScoreboard(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
ensureActive();
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
|
||||
if (p.scoreboardData.forcedScoreboard != null) {
|
||||
p.scoreboardData.forcedScoreboard.removePlayer(p);
|
||||
p.scoreboardData.forcedScoreboard = null;
|
||||
me.neznamy.tab.api.scoreboard.Scoreboard sb = detectHighestScoreboard(p);
|
||||
if (sb == null) return; //no scoreboard available
|
||||
p.scoreboardData.activeScoreboard = (ScoreboardImpl) sb;
|
||||
((ScoreboardImpl) sb).addPlayer(p);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasScoreboardVisible(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
return visiblePlayers.contains(player);
|
||||
ensureActive();
|
||||
return ((TabPlayer)player).scoreboardData.visible;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScoreboardVisible(@NonNull me.neznamy.tab.api.TabPlayer p, boolean visible, boolean sendToggleMessage) {
|
||||
ensureActive();
|
||||
TabPlayer player = (TabPlayer) p;
|
||||
if (visiblePlayers.contains(player) == visible) return;
|
||||
if (player.scoreboardData.visible == visible) return;
|
||||
if (visible) {
|
||||
visiblePlayers.add(player);
|
||||
player.scoreboardData.visible = true;
|
||||
sendHighestScoreboard(player);
|
||||
if (sendToggleMessage) {
|
||||
player.sendMessage(TAB.getInstance().getConfiguration().getMessages().getScoreboardOn(), true);
|
||||
@@ -232,7 +307,7 @@ public class ScoreboardManagerImpl extends TabFeature implements ScoreboardManag
|
||||
}
|
||||
}
|
||||
} else {
|
||||
visiblePlayers.remove(player);
|
||||
player.scoreboardData.visible = false;
|
||||
unregisterScoreboard(player);
|
||||
if (sendToggleMessage) {
|
||||
player.sendMessage(TAB.getInstance().getConfiguration().getMessages().getScoreboardOff(), true);
|
||||
@@ -253,14 +328,15 @@ public class ScoreboardManagerImpl extends TabFeature implements ScoreboardManag
|
||||
TAB.getInstance().getPlaceholderManager().getTabExpansion().setScoreboardVisible(player, visible);
|
||||
}
|
||||
|
||||
private void savePlayers() {
|
||||
synchronized (sbOffPlayers) {
|
||||
TAB.getInstance().getConfiguration().getPlayerDataFile().set("scoreboard-off", new ArrayList<>(sbOffPlayers));
|
||||
}
|
||||
@Override
|
||||
public void toggleScoreboard(@NonNull me.neznamy.tab.api.TabPlayer player, boolean sendToggleMessage) {
|
||||
ensureActive();
|
||||
setScoreboardVisible(player, !((TabPlayer)player).scoreboardData.visible, sendToggleMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void announceScoreboard(@NonNull String scoreboard, int duration) {
|
||||
ensureActive();
|
||||
if (duration < 0) throw new IllegalArgumentException("Duration cannot be negative");
|
||||
ScoreboardImpl sb = (ScoreboardImpl) registeredScoreboards.get(scoreboard);
|
||||
if (sb == null) throw new IllegalArgumentException("No registered scoreboard found with name " + scoreboard);
|
||||
@@ -269,93 +345,50 @@ public class ScoreboardManagerImpl extends TabFeature implements ScoreboardManag
|
||||
announcement = sb;
|
||||
for (TabPlayer all : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (!hasScoreboardVisible(all)) continue;
|
||||
previous.put(all, activeScoreboards.get(all));
|
||||
if (activeScoreboards.containsKey(all)) activeScoreboards.get(all).removePlayer(all);
|
||||
previous.put(all, all.scoreboardData.activeScoreboard);
|
||||
if (all.scoreboardData.activeScoreboard != null) all.scoreboardData.activeScoreboard.removePlayer(all);
|
||||
sb.addPlayer(all);
|
||||
}
|
||||
});
|
||||
TAB.getInstance().getCPUManager().runTaskLater(duration*1000,
|
||||
getFeatureName(), "Removing announced Scoreboard", () -> {
|
||||
for (TabPlayer all : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (!hasScoreboardVisible(all)) continue;
|
||||
sb.removePlayer(all);
|
||||
if (previous.get(all) != null) previous.get(all).addPlayer(all);
|
||||
}
|
||||
announcement = null;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onQuit(@NotNull TabPlayer disconnectedPlayer) {
|
||||
ScoreboardImpl sb = activeScoreboards.get(disconnectedPlayer);
|
||||
if (sb != null) {
|
||||
sb.removePlayerFromSet(disconnectedPlayer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoginPacket(TabPlayer player) {
|
||||
if (!player.isLoaded()) return;
|
||||
otherPluginScoreboards.remove(player);
|
||||
ScoreboardImpl scoreboard = activeScoreboards.get(player);
|
||||
if (scoreboard != null) {
|
||||
scoreboard.removePlayerFromSet(player);
|
||||
scoreboard.addPlayer(player);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getFeatureName() {
|
||||
return "Scoreboard";
|
||||
}
|
||||
|
||||
// ------------------
|
||||
// API Implementation
|
||||
// ------------------
|
||||
|
||||
@Override
|
||||
public void showScoreboard(@NonNull me.neznamy.tab.api.TabPlayer player, @NonNull me.neznamy.tab.api.scoreboard.Scoreboard scoreboard) {
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
|
||||
ScoreboardImpl forced = forcedScoreboard.put(player, (ScoreboardImpl) scoreboard);
|
||||
if (forced != null) forced.removePlayer(p);
|
||||
|
||||
ScoreboardImpl active = activeScoreboards.remove(player);
|
||||
if (active != null) active.removePlayer(p);
|
||||
|
||||
if (hasScoreboardVisible(player)) ((ScoreboardImpl) scoreboard).addPlayer(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetScoreboard(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
|
||||
ScoreboardImpl forced = forcedScoreboard.remove(player);
|
||||
if (forced == null) return;
|
||||
forced.removePlayer(p);
|
||||
|
||||
me.neznamy.tab.api.scoreboard.Scoreboard sb = detectHighestScoreboard(p);
|
||||
if (sb == null) return; //no scoreboard available
|
||||
activeScoreboards.put(player, (ScoreboardImpl) sb);
|
||||
((ScoreboardImpl) sb).addPlayer(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCustomScoreboard(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
return forcedScoreboard.containsKey(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toggleScoreboard(@NonNull me.neznamy.tab.api.TabPlayer player, boolean sendToggleMessage) {
|
||||
setScoreboardVisible(player, !visiblePlayers.contains(player), sendToggleMessage);
|
||||
for (TabPlayer all : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (!hasScoreboardVisible(all)) continue;
|
||||
sb.removePlayer(all);
|
||||
if (previous.get(all) != null) previous.get(all).addPlayer(all);
|
||||
}
|
||||
announcement = null;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ScoreboardImpl getActiveScoreboard(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
return activeScoreboards.get(player);
|
||||
ensureActive();
|
||||
return ((TabPlayer)player).scoreboardData.activeScoreboard;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class storing scoreboard data of players.
|
||||
*/
|
||||
public static class PlayerData {
|
||||
|
||||
/** Flag tracking whether this player is under join delay or not */
|
||||
public boolean joinDelayed;
|
||||
|
||||
/** Flag tracking whether player wishes to have scoreboard visible or not */
|
||||
public boolean visible;
|
||||
|
||||
/** Scoreboard currently displayed to player */
|
||||
@Nullable
|
||||
public ScoreboardImpl activeScoreboard;
|
||||
|
||||
/** Forced scoreboard using API */
|
||||
@Nullable
|
||||
public ScoreboardImpl forcedScoreboard;
|
||||
|
||||
/** Scoreboard sent by another plugin (objective name) */
|
||||
@Nullable
|
||||
public String otherPluginScoreboard;
|
||||
}
|
||||
}
|
||||
@@ -80,6 +80,7 @@ public class LongLine extends ScoreboardLine {
|
||||
|
||||
@Override
|
||||
public void setText(@NonNull String text) {
|
||||
ensureActive();
|
||||
initializeText(text);
|
||||
for (TabPlayer p : parent.getPlayers()) {
|
||||
p.setProperty(this, textProperty, text);
|
||||
|
||||
+1
@@ -129,6 +129,7 @@ public class StableDynamicLine extends ScoreboardLine {
|
||||
|
||||
@Override
|
||||
public void setText(@NonNull String text) {
|
||||
ensureActive();
|
||||
initializeText(text);
|
||||
for (TabPlayer p : parent.getPlayers()) {
|
||||
p.setProperty(this, textProperty, text);
|
||||
|
||||
@@ -29,6 +29,7 @@ import me.neznamy.tab.shared.features.sorting.types.PlaceholderLowToHigh;
|
||||
import me.neznamy.tab.shared.features.sorting.types.PlaceholderZtoA;
|
||||
import me.neznamy.tab.shared.features.sorting.types.SortingType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Class for handling player sorting rules
|
||||
@@ -47,12 +48,6 @@ public class Sorting extends TabFeature implements SortingManager, JoinListener,
|
||||
|
||||
//active sorting types
|
||||
private final SortingType[] usedSortingTypes;
|
||||
|
||||
//team names and notes
|
||||
private final WeakHashMap<TabPlayer, String> shortTeamNames = new WeakHashMap<>();
|
||||
private final WeakHashMap<TabPlayer, String> fullTeamNames = new WeakHashMap<>();
|
||||
private final WeakHashMap<TabPlayer, String> teamNameNotes = new WeakHashMap<>();
|
||||
private final WeakHashMap<me.neznamy.tab.api.TabPlayer, String> forcedTeamName = new WeakHashMap<>();
|
||||
|
||||
/**
|
||||
* Constructs new instance and loads config options
|
||||
@@ -70,16 +65,16 @@ public class Sorting extends TabFeature implements SortingManager, JoinListener,
|
||||
|
||||
@Override
|
||||
public void refresh(@NotNull TabPlayer p, boolean force) {
|
||||
String previousShortName = shortTeamNames.get(p);
|
||||
String previousShortName = p.sortingData.shortTeamName;
|
||||
constructTeamNames(p);
|
||||
if (!shortTeamNames.get(p).equals(previousShortName)) {
|
||||
if (nameTags != null && getForcedTeamName(p) == null && !nameTags.hasTeamHandlingPaused(p) && !nameTags.getDisableChecker().isDisabledPlayer(p)) {
|
||||
if (!p.sortingData.shortTeamName.equals(previousShortName)) {
|
||||
if (nameTags != null && p.sortingData.forcedTeamName == null && !nameTags.hasTeamHandlingPaused(p) && !p.disabledNametags.get()) {
|
||||
for (TabPlayer viewer : TAB.getInstance().getOnlinePlayers()) {
|
||||
viewer.getScoreboard().unregisterTeam(previousShortName);
|
||||
}
|
||||
nameTags.registerTeam(p);
|
||||
}
|
||||
if (layout != null) layout.updateTeamName(p, fullTeamNames.get(p));
|
||||
if (layout != null) layout.updateTeamName(p, p.sortingData.fullTeamName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +91,7 @@ public class Sorting extends TabFeature implements SortingManager, JoinListener,
|
||||
layout = TAB.getInstance().getFeatureManager().getFeature(TabConstants.Feature.LAYOUT);
|
||||
redis = TAB.getInstance().getFeatureManager().getFeature(TabConstants.Feature.REDIS_BUNGEE);
|
||||
for (TabPlayer all : TAB.getInstance().getOnlinePlayers()) {
|
||||
constructTeamNames(all);
|
||||
onJoin(all);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,7 +126,7 @@ public class Sorting extends TabFeature implements SortingManager, JoinListener,
|
||||
* player to build team name for
|
||||
*/
|
||||
public void constructTeamNames(@NotNull TabPlayer p) {
|
||||
teamNameNotes.put(p, "");
|
||||
p.sortingData.teamNameNote = "";
|
||||
StringBuilder shortName = new StringBuilder();
|
||||
for (SortingType type : usedSortingTypes) {
|
||||
shortName.append(type.getChars(p));
|
||||
@@ -146,12 +141,12 @@ public class Sorting extends TabFeature implements SortingManager, JoinListener,
|
||||
shortName.setLength(Limitations.TEAM_NAME_LENGTH-1);
|
||||
}
|
||||
String finalShortName = checkTeamName(p, shortName, 'A');
|
||||
shortTeamNames.put(p, finalShortName);
|
||||
fullTeamNames.put(p, fullName.append(finalShortName.charAt(finalShortName.length() - 1)).toString());
|
||||
p.sortingData.shortTeamName = finalShortName;
|
||||
p.sortingData.fullTeamName = fullName.append(finalShortName.charAt(finalShortName.length() - 1)).toString();
|
||||
|
||||
// Do not randomly override note
|
||||
if (forcedTeamName.get(p) != null) {
|
||||
teamNameNotes.put(p, "Set using API");
|
||||
if (p.sortingData.forcedTeamName != null) {
|
||||
p.sortingData.teamNameNote = "Set using API";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,13 +165,13 @@ public class Sorting extends TabFeature implements SortingManager, JoinListener,
|
||||
String potentialTeamName = currentName.toString() + (char)id;
|
||||
for (TabPlayer all : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (all == p) continue;
|
||||
if (shortTeamNames.get(all) != null && shortTeamNames.get(all).equals(potentialTeamName)) {
|
||||
if (potentialTeamName.equals(all.sortingData.shortTeamName)) {
|
||||
return checkTeamName(p, currentName, id+1);
|
||||
}
|
||||
}
|
||||
if (redis != null && redis.getRedisTeams() != null) {
|
||||
for (RedisPlayer all : redis.getRedisPlayers().values()) {
|
||||
if (redis.getRedisTeams().getTeamNames().get(all).equals(potentialTeamName)) {
|
||||
if (all.getTeamName().equals(potentialTeamName)) {
|
||||
return checkTeamName(p, currentName, id+1);
|
||||
}
|
||||
}
|
||||
@@ -193,56 +188,6 @@ public class Sorting extends TabFeature implements SortingManager, JoinListener,
|
||||
return Arrays.stream(usedSortingTypes).map(SortingType::getDisplayName).collect(Collectors.joining(" -> "));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns short team name of specified player.
|
||||
*
|
||||
* @param p
|
||||
* Player to get short team name of
|
||||
* @return short team name of specified player
|
||||
*/
|
||||
@NotNull
|
||||
public String getShortTeamName(@NotNull TabPlayer p) {
|
||||
String forced = getForcedTeamName(p);
|
||||
if (forced != null) return forced;
|
||||
return shortTeamNames.get(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns full team name of specified player.
|
||||
*
|
||||
* @param p
|
||||
* Player to get full team name of
|
||||
* @return full team name of specified player
|
||||
*/
|
||||
@NotNull
|
||||
public String getFullTeamName(@NotNull TabPlayer p) {
|
||||
return fullTeamNames.get(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns team name note for player.
|
||||
*
|
||||
* @param p
|
||||
* Player to get team name note of
|
||||
* @return team name note for player
|
||||
*/
|
||||
@NotNull
|
||||
public String getTeamNameNote(@NotNull TabPlayer p) {
|
||||
return teamNameNotes.get(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets team note for player.
|
||||
*
|
||||
* @param p
|
||||
* Player to set team name note of
|
||||
* @param note
|
||||
* Team name note
|
||||
*/
|
||||
public void setTeamNameNote(@NotNull TabPlayer p, @NotNull String note) {
|
||||
teamNameNotes.put(p, note);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getFeatureName() {
|
||||
@@ -255,29 +200,64 @@ public class Sorting extends TabFeature implements SortingManager, JoinListener,
|
||||
|
||||
@Override
|
||||
public void forceTeamName(@NonNull me.neznamy.tab.api.TabPlayer player, String name) {
|
||||
((TabPlayer)player).ensureLoaded();
|
||||
if (Objects.equals(forcedTeamName.get(player), name)) return;
|
||||
ensureActive();
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
if (Objects.equals(p.sortingData.forcedTeamName, name)) return;
|
||||
if (name != null && name.length() > Limitations.TEAM_NAME_LENGTH) throw new IllegalArgumentException("Team name cannot be more than 16 characters long.");
|
||||
if (name != null) setTeamNameNote((TabPlayer) player, "Set using API");
|
||||
if (name != null) p.sortingData.teamNameNote = "Set using API";
|
||||
NameTag nametag = TAB.getInstance().getNameTagManager();
|
||||
if (nametag != null) nametag.unregisterTeam((TabPlayer) player, getShortTeamName((TabPlayer) player));
|
||||
forcedTeamName.put(player, name);
|
||||
if (nametag != null) nametag.registerTeam((TabPlayer) player);
|
||||
if (layout != null) layout.updateTeamName((TabPlayer) player, fullTeamNames.get(player));
|
||||
if (redis != null && nametag != null) redis.updateTeam((TabPlayer) player, getShortTeamName((TabPlayer) player),
|
||||
((TabPlayer) player).getProperty(TabConstants.Property.TAGPREFIX).get(),
|
||||
((TabPlayer) player).getProperty(TabConstants.Property.TAGSUFFIX).get(),
|
||||
(nametag.getTeamVisibility((TabPlayer) player, (TabPlayer) player) ? Scoreboard.NameVisibility.ALWAYS : Scoreboard.NameVisibility.NEVER));
|
||||
if (nametag != null) nametag.unregisterTeam(p, p.sortingData.getShortTeamName());
|
||||
p.sortingData.forcedTeamName = name;
|
||||
if (nametag != null) nametag.registerTeam(p);
|
||||
if (layout != null) layout.updateTeamName(p, p.sortingData.fullTeamName);
|
||||
if (redis != null && nametag != null) redis.updateTeam(p, p.sortingData.getShortTeamName(),
|
||||
(p).getProperty(TabConstants.Property.TAGPREFIX).get(),
|
||||
(p).getProperty(TabConstants.Property.TAGSUFFIX).get(),
|
||||
(nametag.getTeamVisibility(p, p) ? Scoreboard.NameVisibility.ALWAYS : Scoreboard.NameVisibility.NEVER));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getForcedTeamName(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
return forcedTeamName.get(player);
|
||||
ensureActive();
|
||||
return ((TabPlayer)player).sortingData.forcedTeamName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getOriginalTeamName(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
@NotNull
|
||||
public String getOriginalTeamName(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
ensureActive();
|
||||
((TabPlayer)player).ensureLoaded();
|
||||
return shortTeamNames.get((TabPlayer) player);
|
||||
return ((TabPlayer)player).sortingData.shortTeamName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class storing sorting data for players.
|
||||
*/
|
||||
public static class PlayerData {
|
||||
|
||||
/** Short team name (16 chars), used for teams */
|
||||
public String shortTeamName;
|
||||
|
||||
/** Full sorting string, used for sorting in Layout (and maybe for 1.18+ in the future) */
|
||||
public String fullTeamName;
|
||||
|
||||
/** Note explaining player's current team name */
|
||||
public String teamNameNote;
|
||||
|
||||
/** Forced team name using API */
|
||||
@Nullable
|
||||
public String forcedTeamName;
|
||||
|
||||
/**
|
||||
* Returns short team name. If forced using API, that value is returned.
|
||||
*
|
||||
* @return short team name to use
|
||||
*/
|
||||
@NotNull
|
||||
public String getShortTeamName() {
|
||||
return forcedTeamName != null ? forcedTeamName : shortTeamName;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -36,10 +36,10 @@ public class Groups extends SortingType {
|
||||
if (!sortedGroups.containsKey(group)) {
|
||||
TAB.getInstance().getConfigHelper().runtime().groupNotInSortingList(sortedGroups.keySet(), group, p);
|
||||
position = sortedGroups.size() + 1;
|
||||
sorting.setTeamNameNote(p, sorting.getTeamNameNote(p) + "\n-> &cPrimary group (&e" + p.getGroup() + "&c) is not in sorting list. &r");
|
||||
p.sortingData.teamNameNote += "\n-> &cPrimary group (&e" + p.getGroup() + "&c) is not in sorting list. &r";
|
||||
} else {
|
||||
position = sortedGroups.get(group);
|
||||
sorting.setTeamNameNote(p, sorting.getTeamNameNote(p) + "\n-> Primary group (&e" + p.getGroup() + "&r) is &a#" + position + "&r in sorting list.");
|
||||
p.sortingData.teamNameNote += "\n-> Primary group (&e" + p.getGroup() + "&r) is &a#" + position + "&r in sorting list.";
|
||||
}
|
||||
return String.valueOf((char) (position + 47));
|
||||
}
|
||||
|
||||
@@ -46,9 +46,9 @@ public class Permissions extends SortingType {
|
||||
for (String permission : sortedGroups.keySet()) {
|
||||
if (p.hasPermission(permission)) {
|
||||
position = sortedGroups.get(permission.toLowerCase());
|
||||
sorting.setTeamNameNote(p, sorting.getTeamNameNote(p) + "\n-> Highest sorting permission: &e" + permission + " &a(#" + position + " in list). &r");
|
||||
p.sortingData.teamNameNote += "\n-> Highest sorting permission: &e" + permission + " &a(#" + position + " in list). &r";
|
||||
if (p.hasPermission(TabConstants.Permission.TEST_PERMISSION)) {
|
||||
sorting.setTeamNameNote(p, sorting.getTeamNameNote(p) + "&cThis user appears to have all permissions. Are they OP? &r");
|
||||
p.sortingData.teamNameNote += "&cThis user appears to have all permissions. Are they OP? &r";
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -56,7 +56,7 @@ public class Permissions extends SortingType {
|
||||
if (position == 0) {
|
||||
TAB.getInstance().getConfigHelper().runtime().noPermissionFromSortingList(sortedGroups.keySet(), p);
|
||||
position = sortedGroups.size()+1;
|
||||
sorting.setTeamNameNote(p, sorting.getTeamNameNote(p) + "\n-> &cPlayer does not have any of the defined permissions. &r");
|
||||
p.sortingData.teamNameNote += "\n-> &cPlayer does not have any of the defined permissions. &r";
|
||||
}
|
||||
return String.valueOf((char) (position + 47));
|
||||
}
|
||||
|
||||
@@ -61,15 +61,15 @@ public class Placeholder extends SortingType {
|
||||
@Override
|
||||
public String getChars(@NotNull TabPlayer p) {
|
||||
String output = EnumChatFormat.color(setPlaceholders(p));
|
||||
sorting.setTeamNameNote(p, sorting.getTeamNameNote(p) + "\n-> " + sortingPlaceholder.getIdentifier() + " returned \"&e" + output + "&r\"");
|
||||
p.sortingData.teamNameNote += "\n-> " + sortingPlaceholder.getIdentifier() + " returned \"&e" + output + "&r\"";
|
||||
int position;
|
||||
if (!sortingMap.containsKey(output.toLowerCase(Locale.US))) {
|
||||
TAB.getInstance().getConfigHelper().runtime().valueNotInPredefinedValues(sortingPlaceholder.getIdentifier(), sortingMap.keySet(), output, p);
|
||||
position = sortingMap.size()+1;
|
||||
sorting.setTeamNameNote(p, sorting.getTeamNameNote(p) + "&c (not in list)&r. ");
|
||||
p.sortingData.teamNameNote += "&c (not in list)&r. ";
|
||||
} else {
|
||||
position = sortingMap.get(output.toLowerCase(Locale.US));
|
||||
sorting.setTeamNameNote(p, sorting.getTeamNameNote(p) + "&r &a(#" + position + " in list). &r");
|
||||
p.sortingData.teamNameNote += "&r &a(#" + position + " in list). &r";
|
||||
}
|
||||
return String.valueOf((char) (position + 47));
|
||||
}
|
||||
|
||||
+1
-2
@@ -24,8 +24,7 @@ public class PlaceholderAtoZ extends SortingType {
|
||||
@Override
|
||||
public String getChars(@NotNull TabPlayer p) {
|
||||
String output = setPlaceholders(p);
|
||||
sorting.setTeamNameNote(p, sorting.getTeamNameNote(p) + "\n-> " + sortingPlaceholder.getIdentifier() +
|
||||
" returned \"&e" + output + "&r\". &r");
|
||||
p.sortingData.teamNameNote += "\n-> " + sortingPlaceholder.getIdentifier() + " returned \"&e" + output + "&r\". &r";
|
||||
return sorting.isCaseSensitiveSorting() ? output : output.toLowerCase();
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -24,8 +24,7 @@ public class PlaceholderHighToLow extends SortingType {
|
||||
@Override
|
||||
public String getChars(@NotNull TabPlayer p) {
|
||||
String output = setPlaceholders(p);
|
||||
sorting.setTeamNameNote(p, sorting.getTeamNameNote(p) + "\n-> " + sortingPlaceholder.getIdentifier() +
|
||||
" returned \"&e" + output + "&r\". &r");
|
||||
p.sortingData.teamNameNote += "\n-> " + sortingPlaceholder.getIdentifier() + " returned \"&e" + output + "&r\". &r";
|
||||
return compressNumber(DEFAULT_NUMBER - parseDouble(sortingPlaceholder.getIdentifier(), output, 0, p));
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -24,8 +24,7 @@ public class PlaceholderLowToHigh extends SortingType {
|
||||
@Override
|
||||
public String getChars(@NotNull TabPlayer p) {
|
||||
String output = setPlaceholders(p);
|
||||
sorting.setTeamNameNote(p, sorting.getTeamNameNote(p) + "\n-> " + sortingPlaceholder.getIdentifier() +
|
||||
" returned \"&e" + output + "&r\". &r");
|
||||
p.sortingData.teamNameNote += "\n-> " + sortingPlaceholder.getIdentifier() + " returned \"&e" + output + "&r\". &r";
|
||||
return compressNumber(DEFAULT_NUMBER + parseDouble(sortingPlaceholder.getIdentifier(), output, 0, p));
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -24,8 +24,7 @@ public class PlaceholderZtoA extends SortingType {
|
||||
@Override
|
||||
public String getChars(@NotNull TabPlayer p) {
|
||||
char[] chars = setPlaceholders(p).toCharArray();
|
||||
sorting.setTeamNameNote(p, sorting.getTeamNameNote(p) + "\n-> " + sortingPlaceholder.getIdentifier() +
|
||||
" returned \"&e" + new String(chars) + "&r\". &r");
|
||||
p.sortingData.teamNameNote += "\n-> " + sortingPlaceholder.getIdentifier() + " returned \"&e" + new String(chars) + "&r\". &r";
|
||||
for (int i=0; i<chars.length; i++) {
|
||||
char c = chars[i];
|
||||
if (c >= 65 && c <= 90) {
|
||||
|
||||
@@ -80,27 +80,27 @@ public abstract class SortingType {
|
||||
|
||||
/**
|
||||
* Compresses a number to ### format, where # is a character symbol representing
|
||||
* a number in a base of 65536. The first two represent the whole part, the third one decimal part.
|
||||
* a number in a base of 65534. The first two represent the whole part, the third one decimal part.
|
||||
* The maximum number it will work properly with is {@link Integer#MAX_VALUE}.
|
||||
*
|
||||
* @param number
|
||||
* Number to convert
|
||||
* @return 3 characters long String of converted number with a base of 65536.
|
||||
* @return 3 characters long String of converted number with a base of 65534.
|
||||
*/
|
||||
public String compressNumber(double number) {
|
||||
int wholePart = (int) number;
|
||||
char decimalChar = (char) ((number - wholePart) * (Character.MAX_VALUE - 1));
|
||||
int base = Character.MAX_VALUE - 1;
|
||||
char decimalChar = (char) ((number - wholePart) * base);
|
||||
// The \ symbol breaks json syntax, skip it (and reduce range) (why is it not being escaped by json writer?)
|
||||
if (decimalChar >= '\\') decimalChar++;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
while (wholePart > 0) {
|
||||
char digit = (char) (wholePart % (Character.MAX_VALUE - 1));
|
||||
char digit = (char) (wholePart % base);
|
||||
if (digit >= '\\') digit++;
|
||||
sb.append(digit);
|
||||
wholePart /= Character.MAX_VALUE;
|
||||
sb.insert(0, digit);
|
||||
wholePart /= base;
|
||||
}
|
||||
sb.reverse();
|
||||
if (sb.length() == 1) sb.insert(0, (char) 0); // Avoid a single # if number is < 65535
|
||||
if (sb.length() == 1) sb.insert(0, (char) 0); // Avoid a single # if number is < base
|
||||
sb.append(decimalChar);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@@ -7,10 +7,9 @@ import me.neznamy.tab.shared.platform.TabPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Class checking if disable-condition of each feature is met or not.
|
||||
@@ -29,9 +28,8 @@ public class DisableChecker extends TabFeature implements Refreshable {
|
||||
@NotNull
|
||||
private final BiConsumer<TabPlayer, Boolean> action;
|
||||
|
||||
/** Players with the feature currently disabled */
|
||||
@NotNull
|
||||
private final Set<TabPlayer> disabledPlayers = Collections.newSetFromMap(new WeakHashMap<>());
|
||||
private final Function<TabPlayer, AtomicBoolean> field;
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters.
|
||||
@@ -42,11 +40,15 @@ public class DisableChecker extends TabFeature implements Refreshable {
|
||||
* Configured condition for disabling the feature
|
||||
* @param action
|
||||
* Action to take on condition change
|
||||
* @param field
|
||||
* Function that returns field storing disable status
|
||||
*/
|
||||
public DisableChecker(@NotNull String featureName, @Nullable Condition disableCondition, @NotNull BiConsumer<TabPlayer, Boolean> action) {
|
||||
public DisableChecker(@NotNull String featureName, @Nullable Condition disableCondition,
|
||||
@NotNull BiConsumer<TabPlayer, Boolean> action, @NotNull Function<TabPlayer, AtomicBoolean> field) {
|
||||
this.featureName = featureName;
|
||||
this.disableCondition = disableCondition;
|
||||
this.action = action;
|
||||
this.field = field;
|
||||
if (disableCondition != null) addUsedPlaceholder(TabConstants.Placeholder.condition(disableCondition.getName()));
|
||||
}
|
||||
|
||||
@@ -54,37 +56,12 @@ public class DisableChecker extends TabFeature implements Refreshable {
|
||||
public void refresh(@NotNull TabPlayer refreshed, boolean force) {
|
||||
if (disableCondition == null) return;
|
||||
boolean disabledNow = disableCondition.isMet(refreshed);
|
||||
if (disabledNow == disabledPlayers.contains(refreshed)) return; // Condition result did not change, only placeholders inside
|
||||
if (disabledNow) {
|
||||
disabledPlayers.add(refreshed);
|
||||
} else {
|
||||
disabledPlayers.remove(refreshed);
|
||||
}
|
||||
AtomicBoolean value = field.apply(refreshed);
|
||||
if (disabledNow == value.get()) return; // Condition result did not change, only placeholders inside
|
||||
value.set(disabledNow);
|
||||
action.accept(refreshed, disabledNow);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the feature is disabled for specified player, {@code false} if not
|
||||
*
|
||||
* @param p
|
||||
* Player to check
|
||||
* @return {@code true} if player is disabled,
|
||||
* {@code false} if not
|
||||
*/
|
||||
public boolean isDisabledPlayer(@NotNull TabPlayer p) {
|
||||
return disabledPlayers.contains(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds specified player into set of disabled players
|
||||
*
|
||||
* @param p
|
||||
* Player to add
|
||||
*/
|
||||
public void addDisabledPlayer(@NotNull TabPlayer p) {
|
||||
disabledPlayers.add(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if disable condition is {@code null} or met,
|
||||
* {@code false} if not met.
|
||||
|
||||
@@ -9,6 +9,23 @@ import org.jetbrains.annotations.NotNull;
|
||||
*/
|
||||
public abstract class TabFeature {
|
||||
|
||||
/** Flag tracking whether this instance is active or not */
|
||||
private boolean active = true;
|
||||
|
||||
/**
|
||||
* Marks this instance as no longer active.
|
||||
*/
|
||||
public void deactivate() {
|
||||
active = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws {@link IllegalStateException} if this instance is no longer active.
|
||||
*/
|
||||
public void ensureActive() {
|
||||
if (!active) throw new IllegalStateException("This instance got discarded because plugin was reloaded. Obtain a new instance.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns name of this feature displayed in /tab cpu
|
||||
*
|
||||
|
||||
@@ -24,6 +24,29 @@ public class AdventureHook {
|
||||
private static final ComponentCache<Component, String> componentToString = new ComponentCache<>(1000,
|
||||
(component, version) -> GsonComponentSerializer.gson().serialize(component));
|
||||
|
||||
/** Array of all 32 possible decoration combinations for fast access */
|
||||
private static final EnumSet<TextDecoration>[] decorations = loadDecorations();
|
||||
|
||||
/**
|
||||
* Loads decoration array.
|
||||
*
|
||||
* @return Decoration array with all possible options
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private static EnumSet<TextDecoration>[] loadDecorations() {
|
||||
EnumSet<TextDecoration>[] decorations = new EnumSet[32];
|
||||
for (int i=0; i<32; i++) {
|
||||
EnumSet<TextDecoration> set = EnumSet.noneOf(TextDecoration.class);
|
||||
if ((i & 1) > 0) set.add(TextDecoration.BOLD);
|
||||
if ((i & 2) > 0) set.add(TextDecoration.ITALIC);
|
||||
if ((i & 4) > 0) set.add(TextDecoration.OBFUSCATED);
|
||||
if ((i & 8) > 0) set.add(TextDecoration.STRIKETHROUGH);
|
||||
if ((i & 16) > 0) set.add(TextDecoration.UNDERLINED);
|
||||
decorations[i] = set;
|
||||
}
|
||||
return decorations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts component to adventure component
|
||||
*
|
||||
@@ -42,7 +65,7 @@ public class AdventureHook {
|
||||
Component adventureComponent = Component.text(
|
||||
iComponent.getText(),
|
||||
convertColor(modifier.getColor(), modern),
|
||||
getDecorations(modifier)
|
||||
decorations[modifier.getMagicCodeBitMask()]
|
||||
);
|
||||
|
||||
if (modifier.getFont() != null) {
|
||||
@@ -88,22 +111,4 @@ public class AdventureHook {
|
||||
return TextColor.color(color.getLegacyColor().getRgb());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets decorations from modifier.
|
||||
*
|
||||
* @param modifier
|
||||
* Modifier to get decorations from
|
||||
* @return Decorations from modifier
|
||||
*/
|
||||
private static Set<TextDecoration> getDecorations(@NotNull ChatModifier modifier) {
|
||||
if (!modifier.hasMagicCodes()) return Collections.emptySet();
|
||||
Set<TextDecoration> decorations = EnumSet.noneOf(TextDecoration.class);
|
||||
if (modifier.isBold()) decorations.add(TextDecoration.BOLD);
|
||||
if (modifier.isItalic()) decorations.add(TextDecoration.ITALIC);
|
||||
if (modifier.isObfuscated()) decorations.add(TextDecoration.OBFUSCATED);
|
||||
if (modifier.isStrikethrough()) decorations.add(TextDecoration.STRIKETHROUGH);
|
||||
if (modifier.isUnderlined()) decorations.add(TextDecoration.UNDERLINED);
|
||||
return decorations;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package me.neznamy.tab.shared.hook;
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import lombok.Getter;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.chat.SimpleComponent;
|
||||
import me.neznamy.tab.shared.util.ReflectionUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -50,22 +49,4 @@ public class ViaVersionHook {
|
||||
TAB.getInstance().debug("ViaVersion returned protocol version " + version + " for " + playerName);
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints warn into console when ViaVersion is installed on BungeeCord.
|
||||
* Surprisingly, the issue with wrong protocol version is not present on Velocity.
|
||||
*/
|
||||
public void printProxyWarn() {
|
||||
if (!installed) return;
|
||||
TAB.getInstance().getPlatform().logWarn(new SimpleComponent("Detected plugin ViaVersion, which when installed on BungeeCord acts like a" +
|
||||
" client-sided protocol hack, making it impossible for TAB to properly detect player version and causing issues " +
|
||||
"if client and server versions don't match, which include, but are not limited to:"));
|
||||
TAB.getInstance().getPlatform().logWarn(new SimpleComponent("#1 - NameTag prefix/suffix being cut to 16 characters even for 1.13+ players"));
|
||||
TAB.getInstance().getPlatform().logWarn(new SimpleComponent("#2 - Scoreboard lines being cut to 26 characters even for 1.13+ players"));
|
||||
TAB.getInstance().getPlatform().logWarn(new SimpleComponent("#3 - Scoreboard lines being cut to 14 characters for <1.13"));
|
||||
TAB.getInstance().getPlatform().logWarn(new SimpleComponent("#4 - Scoreboard lines might be out of order when using all 0s"));
|
||||
TAB.getInstance().getPlatform().logWarn(new SimpleComponent("#5 - RGB colors will display as legacy colors even for 1.16+ players"));
|
||||
TAB.getInstance().getPlatform().logWarn(new SimpleComponent("#6 - Layout entries will be in random order for 1.19.3+ players"));
|
||||
TAB.getInstance().getPlatform().logWarn(new SimpleComponent("Please install ViaVersion on all backend servers instead."));
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,9 @@ public class PlaceholderRefreshTask implements Runnable {
|
||||
@Nullable
|
||||
private Map<RelationalPlaceholderImpl, Map<TabPlayer, Map<TabPlayer, Object>>> relationalPlaceholderResults;
|
||||
|
||||
/** Time it took placeholders to retrieve value (in nanoseconds) */
|
||||
private final Map<String, Long> usedTime = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
TabPlayer[] players = TAB.getInstance().getOnlinePlayers();
|
||||
@@ -74,7 +77,7 @@ public class PlaceholderRefreshTask implements Runnable {
|
||||
if (relationalPlaceholderResults == null) relationalPlaceholderResults = new HashMap<>();
|
||||
relationalPlaceholderResults.put(relationalPlaceholder, viewerMap);
|
||||
}
|
||||
TAB.getInstance().getCPUManager().addPlaceholderTime(placeholder.getIdentifier(), nanoTime);
|
||||
usedTime.put(placeholder.getIdentifier(), nanoTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package me.neznamy.tab.shared.placeholders.expansion;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Class storing placeholders for plugin's PlaceholderAPI expansion.
|
||||
*/
|
||||
public class PlayerExpansionValues {
|
||||
|
||||
/** Map of placeholder values */
|
||||
public final Map<String, String> values = new HashMap<>();
|
||||
}
|
||||
@@ -74,4 +74,19 @@ public interface BossBar {
|
||||
* Unique identifier to match the bossbar with other functions
|
||||
*/
|
||||
void remove(@NotNull UUID id);
|
||||
|
||||
|
||||
/**
|
||||
* Freezes the class, not letting any packets through.
|
||||
*/
|
||||
default void freeze() {
|
||||
// Empty by default
|
||||
}
|
||||
|
||||
/**
|
||||
* Unfreezes the class, enabling it back.
|
||||
*/
|
||||
default void unfreeze() {
|
||||
// Empty by default
|
||||
}
|
||||
}
|
||||
Loaded 100 of 112 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user