mirror of
https://github.com/NEZNAMY/TAB.git
synced 2026-11-13 04:32:03 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4c3bd66209 | ||
|
|
0827d083bf | ||
|
|
2f7b42ab85 | ||
|
|
735aa666d6 | ||
|
|
c2ceb643e5 | ||
|
|
5c166f647f | ||
|
|
03a8fb9aa2 | ||
|
|
1a44c97d5a | ||
|
|
29cf0a26d6 | ||
|
|
33d172598d | ||
|
|
af1e685c2b | ||
|
|
09129974db | ||
|
|
0efb69fb4b | ||
|
|
5cbec52ea3 | ||
|
|
8db9e64121 | ||
|
|
05009b17f0 | ||
|
|
032af707dd | ||
|
|
cf227a97f3 | ||
|
|
1a2075dfe2 | ||
|
|
1de7665309 | ||
|
|
9473037127 | ||
|
|
dcb234dc08 | ||
|
|
79eb34fc32 | ||
|
|
40544ef5d3 | ||
|
|
14dfa0154a | ||
|
|
7df2aba2d1 | ||
|
|
9edf3176ea | ||
|
|
ec73aa13b4 | ||
|
|
6f002cd61b | ||
|
|
cf065ba27d | ||
|
|
f96e263bd7 | ||
|
|
a22f8eccaf | ||
|
|
718ee89211 | ||
|
|
54b44ce6cd | ||
|
|
29da28e955 | ||
|
|
fa195389ab | ||
|
|
9e3864be53 | ||
|
|
29b89b3bb7 | ||
|
|
e741608261 | ||
|
|
8e8a4cc9e8 | ||
|
|
3bb6e0c3f2 | ||
|
|
4c3b13a81c | ||
|
|
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 | ||
|
|
6b38954694 | ||
|
|
9eb350df30 | ||
|
|
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
|
||||
|
||||
@@ -2,7 +2,7 @@ name: Build
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- v5
|
||||
jobs:
|
||||
build:
|
||||
name: Build
|
||||
|
||||
@@ -1,58 +1,2 @@
|
||||
# About
|
||||
TAB aims to be a superior all-in-one minecraft plugin for displaying information that outperforms all
|
||||
similar plugins in terms of features, performance and compatibility.
|
||||
More information can be found at [Why TAB?](https://github.com/NEZNAMY/TAB/wiki/Why-TAB%3F) wiki page.
|
||||
|
||||
# Download
|
||||
### Releases
|
||||
You can download full releases from [GitHub releases](https://github.com/NEZNAMY/TAB/releases),
|
||||
[SpigotMC](https://www.spigotmc.org/resources/57806/), [Modrinth](https://modrinth.com/plugin/tab-was-taken) or [BuiltByBit](https://builtbybit.com/resources/20631).
|
||||
|
||||
### Dev builds
|
||||
Plugin's development is continuous and contains lots of small changes/fixes not worthy of being called a full
|
||||
update, therefore development builds are being created and eventually a full update is released when enough changes are made.
|
||||
If you want to benefit from a recent change in the code before official release, you can download development builds
|
||||
from [GitHub actions](https://github.com/NEZNAMY/TAB/actions) (you must be logged into GitHub to be able to download it).
|
||||
|
||||
# Compiling
|
||||
Compilation requires JDK 21 and up.
|
||||
To compile the plugin, run `./gradlew build` from the terminal.
|
||||
Once the plugin compiles, grab the jar from `/jar/build/libs/` folder.
|
||||
The universal jar contains all modules for all supported platforms.
|
||||
|
||||
# Documentation
|
||||
You can find everything about the plugin on the [Wiki](https://github.com/NEZNAMY/TAB/wiki). This includes a detailed description
|
||||
of all features, as well as information regarding compatibility or limitations of each feature.
|
||||
|
||||
# Issues
|
||||
The [Issues](https://github.com/NEZNAMY/TAB/issues) section is an issue tracker for all the kind of problems covered in issue templates.
|
||||
Please refrain from attempting to use it to receive help with your server, such issues will be closed immediately.
|
||||
When opening an issue, provide as much information as possible. The difference between a bug getting fixed in 1 week vs 1 hour
|
||||
is in quality of the report. Bug reports where steps to reproduce are "idk" have no value and will not help to get the bug fixed at all.
|
||||
|
||||
# Contributing
|
||||
See [CONTRIBUTING.md](https://github.com/NEZNAMY/TAB/blob/master/CONTRIBUTING.md)
|
||||
|
||||
# Provided services
|
||||
The plugin is being used by a large amount of servers, which also means the demand for my attention is high. Unfortunately,
|
||||
I am no longer able to keep up with the demand since I don't want to dedicate my whole existence to a free plugin.
|
||||
In order to provide the best quality of all provided services, the amount of services provided may vary over time.
|
||||
Here is the full list of potential services and their status:
|
||||
|
||||
| Service type | Availability |
|
||||
|-------------------------------|--------------|
|
||||
| Updates for new MC versions | ✔ |
|
||||
| Bug fixes | ✔ |
|
||||
| Wiki updates<sup>1</sup> | ✔ |
|
||||
| Feature requests | ❌ |
|
||||
| Customer support<sup>2</sup> | ✔ |
|
||||
| Free user support<sup>3</sup> | ❌* |
|
||||
| Optimization<sup>4</sup> | ✔ |
|
||||
|
||||
<sup>1</sup> - Adding new examples, guides and other kind of useful information people ask about.
|
||||
<sup>2</sup> - Unrestricted assistance with the plugin for those, who bought a copy of the plugin when it was purchasable.
|
||||
<sup>3</sup> - Unlimited access to my free time for everyone in the world.
|
||||
<sup>4</sup> - Improving plugin's performance while not losing out on any features. This was done
|
||||
proactively a lot in the past, so there isn't much to do anymore, only if someone actually finds and reports something.
|
||||
|
||||
*Instead, you can use [this fresh new community discord](https://discord.gg/YPqXt63YQj) made by a nice person who will provide this service.
|
||||
# Warning
|
||||
This branch is abandoned and NO support will be provided. It is an archived source code of the latest release with unlimited nametags and 1.8 bossbars (4.1.9) for MC 1.5 - 1.21.1.
|
||||
@@ -1,5 +1,6 @@
|
||||
package me.neznamy.tab.api;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.UUID;
|
||||
|
||||
import lombok.NonNull;
|
||||
@@ -67,8 +68,17 @@ public abstract class TabAPI {
|
||||
*
|
||||
* @return collection of online players
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract @NotNull TabPlayer[] getOnlinePlayers();
|
||||
|
||||
|
||||
/**
|
||||
* Returns a stream of all online players
|
||||
*
|
||||
* @return stream of online players
|
||||
*/
|
||||
public abstract @NotNull Collection<? extends TabPlayer> onlinePlayers();
|
||||
|
||||
/**
|
||||
* Return BossBar manager instance if the feature is enabled. If not, returns {@code null}.
|
||||
*
|
||||
|
||||
@@ -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.3"
|
||||
version = "4.1.9"
|
||||
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(
|
||||
|
||||
@@ -2,7 +2,7 @@ dependencies {
|
||||
implementation(projects.shared)
|
||||
implementation("org.bstats:bstats-bukkit:3.0.1")
|
||||
compileOnly("org.purpurmc.purpur:purpur-api:1.16.5-R0.1-SNAPSHOT")
|
||||
compileOnly("me.clip:placeholderapi:2.11.2")
|
||||
compileOnly("me.clip:placeholderapi:2.11.6")
|
||||
compileOnly("com.mojang:authlib:1.5.25")
|
||||
compileOnly("com.github.MilkBowl:VaultAPI:1.7") {
|
||||
exclude("org.bukkit", "bukkit")
|
||||
|
||||
@@ -53,7 +53,7 @@ public class DataWatcher implements EntityData {
|
||||
loadSerializers();
|
||||
}
|
||||
if (BukkitReflection.is1_19_3Plus()) {
|
||||
Class<?> dataWatcher$Item = BukkitReflection.getClass("network.syncher.SynchedEntityData$DataValue", "network.syncher.DataWatcher$c");
|
||||
Class<?> dataWatcher$Item = BukkitReflection.getClass("network.syncher.SynchedEntityData$DataValue", "network.syncher.DataWatcher$c", "network.syncher.DataWatcher$b");
|
||||
Class<?> dataWatcherSerializer = BukkitReflection.getClass("network.syncher.EntityDataSerializer",
|
||||
"network.syncher.DataWatcherSerializer", "DataWatcherSerializer");
|
||||
newDataWatcher$Item = dataWatcher$Item.getConstructor(int.class, dataWatcherSerializer, Object.class);
|
||||
@@ -110,7 +110,7 @@ public class DataWatcher implements EntityData {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets value into data values
|
||||
*
|
||||
@@ -270,4 +270,4 @@ public class DataWatcher implements EntityData {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-7
@@ -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(
|
||||
@@ -101,13 +97,13 @@ 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);
|
||||
if (p == null) return "<Player is not loaded>";
|
||||
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
|
||||
|
||||
@@ -29,8 +29,8 @@ public class ComponentConverter {
|
||||
private final FunctionWithException<String, Object> newTextComponent;
|
||||
private final BiFunction<ChatModifier, Boolean, Object> convertModifier;
|
||||
|
||||
private final Class<?> ChatModifier = BukkitReflection.getClass("network.chat.ChatModifier", "ChatModifier");
|
||||
private final Class<Enum> EnumChatFormat = (Class<Enum>) BukkitReflection.getClass("EnumChatFormat");
|
||||
private final Class<?> ChatModifier = BukkitReflection.getClass("network.chat.Style", "network.chat.ChatModifier", "ChatModifier");
|
||||
private final Class<Enum> EnumChatFormat = (Class<Enum>) BukkitReflection.getClass("ChatFormatting", "EnumChatFormat");
|
||||
private final Constructor<?> newChatModifier;
|
||||
private final Method ChatBaseComponent_addSibling;
|
||||
private final Field Component_modifier;
|
||||
@@ -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.
|
||||
@@ -50,30 +50,30 @@ public class ComponentConverter {
|
||||
* If something failed
|
||||
*/
|
||||
private ComponentConverter() throws ReflectiveOperationException {
|
||||
Class<?> IChatBaseComponent = BukkitReflection.getClass("network.chat.IChatBaseComponent", "IChatBaseComponent");
|
||||
Class<?> IChatBaseComponent = BukkitReflection.getClass("network.chat.Component", "network.chat.IChatBaseComponent", "IChatBaseComponent");
|
||||
if (BukkitReflection.getMinorVersion() >= 19) {
|
||||
Method IChatBaseComponent_b = ReflectionUtils.getMethod(IChatBaseComponent, new String[] {"b", "literal"}, String.class);
|
||||
newTextComponent = text -> IChatBaseComponent_b.invoke(null, text);
|
||||
Class<?> IChatMutableComponent = BukkitReflection.getClass("network.chat.IChatMutableComponent", "IChatMutableComponent");
|
||||
Class<?> IChatMutableComponent = BukkitReflection.getClass("network.chat.MutableComponent", "network.chat.IChatMutableComponent", "IChatMutableComponent");
|
||||
Component_modifier = ReflectionUtils.getOnlyField(IChatMutableComponent, ChatModifier);
|
||||
ChatBaseComponent_addSibling = ReflectionUtils.getOnlyMethod(IChatMutableComponent, IChatMutableComponent, IChatBaseComponent);
|
||||
} else {
|
||||
Class<?> ChatComponentText = BukkitReflection.getClass("network.chat.ChatComponentText", "ChatComponentText");
|
||||
Class<?> ChatComponentText = BukkitReflection.getClass("network.chat.TextComponent", "network.chat.ChatComponentText", "ChatComponentText");
|
||||
Constructor<?> newChatComponentText = ChatComponentText.getConstructor(String.class);
|
||||
newTextComponent = newChatComponentText::newInstance;
|
||||
Class<?> ChatBaseComponent = BukkitReflection.getClass("network.chat.ChatBaseComponent", "ChatBaseComponent");
|
||||
Class<?> ChatBaseComponent = BukkitReflection.getClass("network.chat.BaseComponent", "network.chat.ChatBaseComponent", "ChatBaseComponent");
|
||||
Component_modifier = ReflectionUtils.getOnlyField(ChatBaseComponent, ChatModifier);
|
||||
ChatBaseComponent_addSibling = ReflectionUtils.getOnlyMethod(ChatComponentText, IChatBaseComponent, IChatBaseComponent);
|
||||
}
|
||||
if (BukkitReflection.getMinorVersion() >= 16) {
|
||||
Class<?> chatHexColor = BukkitReflection.getClass("network.chat.ChatHexColor", "ChatHexColor");
|
||||
Class<?> MinecraftKey = 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);
|
||||
ChatHexColor_fromRGB = ReflectionUtils.getOnlyMethod(chatHexColor, chatHexColor, int.class);
|
||||
Class<?> chatHexColor = BukkitReflection.getClass("network.chat.TextColor", "network.chat.ChatHexColor", "ChatHexColor");
|
||||
Class<?> ResourceLocation = BukkitReflection.getClass("resources.ResourceLocation", "resources.MinecraftKey", "MinecraftKey");
|
||||
Class<?> chatClickable = BukkitReflection.getClass("network.chat.ClickEvent", "network.chat.ChatClickable", "ChatClickable");
|
||||
Class<?> chatHoverable = BukkitReflection.getClass("network.chat.HoverEvent", "network.chat.ChatHoverable", "ChatHoverable");
|
||||
ResourceLocation_tryParse = ReflectionUtils.getMethod(ResourceLocation, new String[]{"tryParse", "m_135820_", "a"}, String.class);
|
||||
ChatHexColor_fromRGB = ReflectionUtils.getMethods(chatHexColor, chatHexColor, int.class).get(0); // There should only be 1, but some mods add more
|
||||
newChatModifier = ReflectionUtils.setAccessible(ChatModifier.getDeclaredConstructor(chatHexColor, Boolean.class, Boolean.class, Boolean.class,
|
||||
Boolean.class, Boolean.class, chatClickable, chatHoverable, String.class, 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) {
|
||||
|
||||
+13
-8
@@ -16,6 +16,8 @@ import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Class storing all team related fields and methods.
|
||||
@@ -29,7 +31,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;
|
||||
@@ -71,7 +72,12 @@ public class TeamPacketData {
|
||||
emptyScoreboard = Scoreboard.getConstructor().newInstance();
|
||||
newScoreboardTeam = scoreboardTeam.getConstructor(Scoreboard, String.class);
|
||||
TeamPacket_NAME = ReflectionUtils.getFields(TeamPacketClass, String.class).get(0);
|
||||
TeamPacket_ACTION = ReflectionUtils.getInstanceFields(TeamPacketClass, int.class).get(0);
|
||||
List<Field> intFields = ReflectionUtils.getInstanceFields(TeamPacketClass, int.class);
|
||||
if (minorVersion >= 8 && minorVersion <= 12) {
|
||||
TeamPacket_ACTION = intFields.get(1);
|
||||
} else {
|
||||
TeamPacket_ACTION = intFields.get(0);
|
||||
}
|
||||
TeamPacket_PLAYERS = ReflectionUtils.getOnlyField(TeamPacketClass, Collection.class);
|
||||
ScoreboardTeam_getPlayerNameSet = ReflectionUtils.getOnlyMethod(scoreboardTeam, Collection.class);
|
||||
chatFormats = (Enum<?>[]) enumChatFormatClass.getMethod("values").invoke(null);
|
||||
@@ -85,12 +91,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,
|
||||
@@ -305,8 +309,9 @@ public class TeamPacketData {
|
||||
public void onPacketSend(@NonNull TabPlayer player, @NonNull Object packet) {
|
||||
if (!TeamPacketClass.isInstance(packet)) return;
|
||||
int action = TeamPacket_ACTION.getInt(packet);
|
||||
if (action == TeamAction.REMOVE || action == TeamAction.UPDATE) return;
|
||||
TeamPacket_PLAYERS.set(packet, player.getScoreboard().onTeamPacket(
|
||||
action, (String) TeamPacket_NAME.get(packet), (Collection<String>) TeamPacket_PLAYERS.get(packet)));
|
||||
if (action == TeamAction.UPDATE) return;
|
||||
Collection<String> players = (Collection<String>) TeamPacket_PLAYERS.get(packet);
|
||||
if (players == null) players = Collections.emptyList();
|
||||
TeamPacket_PLAYERS.set(packet, player.getScoreboard().onTeamPacket(action, (String) TeamPacket_NAME.get(packet), players));
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
dependencies {
|
||||
implementation(projects.shared)
|
||||
implementation("org.bstats:bstats-bungeecord:3.0.1")
|
||||
compileOnly("net.md-5:bungeecord-proxy:1.20-R0.2-SNAPSHOT")
|
||||
compileOnly("net.md-5:bungeecord-proxy:1.20-R0.3-SNAPSHOT")
|
||||
compileOnly("com.github.limework.redisbungee:RedisBungee-Bungee:0.11.0")
|
||||
compileOnly("com.github.LeonMangler:PremiumVanishAPI:2.8.8")
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
+5
-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(() -> {
|
||||
@@ -57,6 +59,7 @@ public class BungeeEventListener implements EventListener<ProxiedPlayer>, Listen
|
||||
// Sending these packets before login packet will also crash the client on 1.20.3
|
||||
if (player.getVersion().getNetworkId() >= ProtocolVersion.V1_20_2.getNetworkId()) {
|
||||
player.getScoreboard().freeze();
|
||||
player.getBossBar().freeze();
|
||||
}
|
||||
|
||||
tab.getFeatureManager().onJoin(player);
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -14,6 +14,8 @@ import net.md_5.bungee.protocol.packet.*;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Scoreboard handler for BungeeCord. Because it does not offer
|
||||
@@ -158,8 +160,9 @@ public class BungeeScoreboard extends Scoreboard<BungeeTabPlayer, BaseComponent>
|
||||
}
|
||||
if (isAntiOverrideTeams() && packet instanceof Team) {
|
||||
Team team = (Team) packet;
|
||||
if (team.getMode() == TeamAction.REMOVE || team.getMode() == TeamAction.UPDATE) return;
|
||||
team.setPlayers(onTeamPacket(team.getMode(), team.getName(), Lists.newArrayList(team.getPlayers())).toArray(new String[0]));
|
||||
if (team.getMode() == TeamAction.UPDATE) return;
|
||||
List<String> players = team.getPlayers() == null ? Collections.emptyList() : Lists.newArrayList(team.getPlayers());
|
||||
team.setPlayers(onTeamPacket(team.getMode(), team.getName(), players).toArray(new String[0]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -71,7 +71,20 @@ public class BungeeTabPlayer extends ProxyTabPlayer {
|
||||
|
||||
@Override
|
||||
public void sendMessage(@NotNull TabComponent message) {
|
||||
getPlayer().sendMessage((BaseComponent) message.convert(getVersion()));
|
||||
try {
|
||||
getPlayer().sendMessage((BaseComponent) message.convert(getVersion()));
|
||||
} catch (NullPointerException BungeeCordBug) {
|
||||
// java.lang.NullPointerException: Cannot invoke "net.md_5.bungee.protocol.MinecraftEncoder.getProtocol()" because the return value of "io.netty.channel.ChannelPipeline.get(java.lang.Class)" is null
|
||||
// at net.md_5.bungee.netty.ChannelWrapper.getEncodeProtocol(ChannelWrapper.java:51)
|
||||
// at net.md_5.bungee.UserConnection.sendPacketQueued(UserConnection.java:198)
|
||||
// at net.md_5.bungee.UserConnection.sendMessage(UserConnection.java:565)
|
||||
// at net.md_5.bungee.UserConnection.sendMessage(UserConnection.java:520)
|
||||
// at net.md_5.bungee.UserConnection.sendMessage(UserConnection.java:508)
|
||||
if (TAB.getInstance().getConfiguration().isDebugMode()) {
|
||||
TAB.getInstance().getErrorManager().printError("Failed to send message to player " + getName() +
|
||||
" (online = " + getPlayer().isConnected() + "): " + message.convert(getVersion()), BungeeCordBug);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -80,8 +93,13 @@ public class BungeeTabPlayer extends ProxyTabPlayer {
|
||||
LoginResult loginResult = ((InitialHandler)getPlayer().getPendingConnection()).getLoginProfile();
|
||||
if (loginResult == null) return null;
|
||||
Property[] properties = loginResult.getProperties();
|
||||
if (properties == null || properties.length == 0) return null; //Offline mode
|
||||
return new TabList.Skin(properties[0].getValue(), properties[0].getSignature());
|
||||
if (properties == null) return null; //Offline mode
|
||||
for (Property property : properties) {
|
||||
if (property.getName().equals(TabList.TEXTURES_PROPERTY)) {
|
||||
return new TabList.Skin(property.getValue(), property.getSignature());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -112,19 +130,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())});
|
||||
|
||||
+19
-3
@@ -20,10 +20,19 @@ public class BungeeTabList1193 extends BungeeTabList {
|
||||
private static final Map<Action, EnumSet<PlayerListItemUpdate.Action>> actions = new EnumMap<>(Action.class);
|
||||
|
||||
static {
|
||||
actions.put(Action.ADD_PLAYER, EnumSet.allOf(PlayerListItemUpdate.Action.class));
|
||||
// Do not use allOf because <1.21.2 does not support UPDATE_LIST_ORDER
|
||||
// TODO Once bungeecord dependency is updated, support it properly
|
||||
actions.put(Action.ADD_PLAYER, EnumSet.of(
|
||||
PlayerListItemUpdate.Action.ADD_PLAYER,
|
||||
PlayerListItemUpdate.Action.UPDATE_GAMEMODE,
|
||||
PlayerListItemUpdate.Action.UPDATE_LISTED,
|
||||
PlayerListItemUpdate.Action.UPDATE_LATENCY,
|
||||
PlayerListItemUpdate.Action.UPDATE_DISPLAY_NAME
|
||||
));
|
||||
actions.put(Action.UPDATE_GAME_MODE, EnumSet.of(PlayerListItemUpdate.Action.UPDATE_GAMEMODE));
|
||||
actions.put(Action.UPDATE_DISPLAY_NAME, EnumSet.of(PlayerListItemUpdate.Action.UPDATE_DISPLAY_NAME));
|
||||
actions.put(Action.UPDATE_LATENCY, EnumSet.of(PlayerListItemUpdate.Action.UPDATE_LATENCY));
|
||||
actions.put(Action.UPDATE_LISTED, EnumSet.of(PlayerListItemUpdate.Action.UPDATE_LISTED));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -66,9 +75,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:1.21.1")
|
||||
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.100.1+1.21"
|
||||
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) -> {
|
||||
|
||||
@@ -4,7 +4,7 @@ import com.mojang.authlib.properties.Property;
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.SneakyThrows;
|
||||
import me.neznamy.tab.platforms.fabric.loader.Loader;
|
||||
import me.neznamy.tab.platforms.fabric.loader.Loader_1_20_5;
|
||||
import me.neznamy.tab.platforms.fabric.loader.Loader_1_21_1;
|
||||
import me.neznamy.tab.shared.ProtocolVersion;
|
||||
import me.neznamy.tab.shared.backend.EntityData;
|
||||
import me.neznamy.tab.shared.backend.Location;
|
||||
@@ -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_21_1();
|
||||
|
||||
/** 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);
|
||||
}
|
||||
+17
-16
@@ -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;
|
||||
@@ -40,14 +42,13 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Method loader compiled using Minecraft 1.20.5.
|
||||
* Method loader compiled using Minecraft 1.21.1.
|
||||
*/
|
||||
@SuppressWarnings({
|
||||
"unchecked", // Java generic types
|
||||
"DataFlowIssue", // Profile is not null on add action
|
||||
"unused" // Actually used, just via reflection
|
||||
"DataFlowIssue" // Profile is not null on add action
|
||||
})
|
||||
public class Loader_1_20_5 implements Loader {
|
||||
public class Loader_1_21_1 implements Loader {
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
@@ -94,7 +95,7 @@ public class Loader_1_20_5 implements Loader {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
modifier.getFont() == null ? null : new ResourceLocation(modifier.getFont())
|
||||
modifier.getFont() == null ? null : ResourceLocation.tryParse(modifier.getFont())
|
||||
);
|
||||
}
|
||||
|
||||
@@ -143,8 +144,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.UPDATE) return;
|
||||
team.players = scoreboard.onTeamPacket(team.method, team.getName(), team.players);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -211,7 +215,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 +295,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();
|
||||
}
|
||||
|
||||
@@ -315,12 +319,12 @@ public class Loader_1_20_5 implements Loader {
|
||||
|
||||
@Override
|
||||
public void logInfo(@NotNull TabComponent message) {
|
||||
MinecraftServer.LOGGER.info("[TAB] " + message.toLegacyText());
|
||||
MinecraftServer.LOGGER.info("[TAB] " + message.toRawText());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logWarn(@NotNull TabComponent message) {
|
||||
MinecraftServer.LOGGER.warn("[TAB] " + message.toLegacyText());
|
||||
MinecraftServer.LOGGER.warn("[TAB] " + message.toRawText());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -354,11 +358,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();
|
||||
|
||||
public static EnumSet<ClientboundPlayerInfoUpdatePacket.Action> convertAction(TabList.Action action) {
|
||||
return EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.valueOf(action.name()));
|
||||
}
|
||||
static final Map<TabList.Action, EnumSet<ClientboundPlayerInfoUpdatePacket.Action>> actionMap = createActionMap();
|
||||
|
||||
private static Map<TabList.Action, EnumSet<ClientboundPlayerInfoUpdatePacket.Action>> createActionMap() {
|
||||
Map<TabList.Action, EnumSet<ClientboundPlayerInfoUpdatePacket.Action>> actions = new EnumMap<>(TabList.Action.class);
|
||||
@@ -366,6 +366,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", "1.21.1"
|
||||
]
|
||||
},
|
||||
"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;
|
||||
|
||||
|
||||
+20
-45
@@ -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.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);
|
||||
}
|
||||
|
||||
@@ -344,13 +319,13 @@ public class Loader_1_14_4 implements Loader {
|
||||
@SneakyThrows
|
||||
public void logInfo(@NotNull TabComponent message) {
|
||||
Object logger = ReflectionUtils.getFields(MinecraftServer.class, Class.forName("org.apache.logging.log4j.Logger")).get(0).get(null);
|
||||
logger.getClass().getMethod("info", String.class).invoke(logger, "[TAB] " + message.toLegacyText());
|
||||
logger.getClass().getMethod("info", String.class).invoke(logger, "[TAB] " + message.toRawText());
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void logWarn(@NotNull TabComponent message) {
|
||||
Object logger = ReflectionUtils.getFields(MinecraftServer.class, Class.forName("org.apache.logging.log4j.Logger")).get(0).get(null);
|
||||
logger.getClass().getMethod("warn", String.class).invoke(logger, "[TAB] " + message.toLegacyText());
|
||||
logger.getClass().getMethod("warn", String.class).invoke(logger, "[TAB] " + message.toRawText());
|
||||
}
|
||||
}
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package me.neznamy.tab.shared;
|
||||
import lombok.Getter;
|
||||
import me.neznamy.tab.api.event.TabEvent;
|
||||
import me.neznamy.tab.shared.chat.EnumChatFormat;
|
||||
import me.neznamy.tab.shared.chat.SimpleComponent;
|
||||
import me.neznamy.tab.shared.chat.TabComponent;
|
||||
import me.neznamy.tab.shared.platform.TabPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -118,13 +118,13 @@ public class ErrorManager {
|
||||
if (file.length() < TabConstants.MAX_LOG_SIZE)
|
||||
buf.write(dateFormat.format(new Date()) + "[TAB v" + TabConstants.PLUGIN_VERSION + "] " + EnumChatFormat.decolor(message) + System.lineSeparator());
|
||||
if (intoConsoleToo || TAB.getInstance().getConfiguration().isDebugMode())
|
||||
TAB.getInstance().getPlatform().logWarn(new SimpleComponent(message));
|
||||
TAB.getInstance().getPlatform().logWarn(TabComponent.fromColoredText(message));
|
||||
}
|
||||
for (String line : error) {
|
||||
if (file.length() < TabConstants.MAX_LOG_SIZE)
|
||||
buf.write(dateFormat.format(new Date()) + line + System.lineSeparator());
|
||||
if (intoConsoleToo || TAB.getInstance().getConfiguration().isDebugMode())
|
||||
TAB.getInstance().getPlatform().logWarn(new SimpleComponent(line));
|
||||
TAB.getInstance().getPlatform().logWarn(TabComponent.fromColoredText(line));
|
||||
}
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
@@ -134,7 +134,7 @@ public class ErrorManager {
|
||||
lines.add("Original error: " + message);
|
||||
lines.addAll(error);
|
||||
for (String line : lines) {
|
||||
TAB.getInstance().getPlatform().logWarn(new SimpleComponent(line));
|
||||
TAB.getInstance().getPlatform().logWarn(TabComponent.fromColoredText(line));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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}.
|
||||
*
|
||||
|
||||
@@ -3,6 +3,7 @@ package me.neznamy.tab.shared;
|
||||
import java.util.*;
|
||||
|
||||
import me.neznamy.tab.api.placeholder.PlayerPlaceholder;
|
||||
import me.neznamy.tab.shared.chat.TabComponent;
|
||||
import me.neznamy.tab.shared.config.Configs;
|
||||
import me.neznamy.tab.shared.config.mysql.MySQLUserConfiguration;
|
||||
import me.neznamy.tab.shared.features.*;
|
||||
@@ -75,6 +76,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()) {
|
||||
@@ -484,6 +488,18 @@ public class FeatureManager {
|
||||
NameTag unlimited = TAB.getInstance().getPlatform().getUnlimitedNameTags();
|
||||
if (unlimited instanceof NameTagX) {
|
||||
featureManager.registerFeature(TabConstants.Feature.UNLIMITED_NAME_TAGS, unlimited);
|
||||
for (String message : new String[]{
|
||||
"---------------------------------------------------------------------",
|
||||
"You have unlimited nametag mode feature enabled.",
|
||||
"This feature is scheduled for removal in a future TAB release.",
|
||||
"Please considering the alternative solutions available to achieve your desired result.",
|
||||
"No bug reports with this feature will be accepted anymore.",
|
||||
"No support with this feature will be provided anymore.",
|
||||
"See https://gist.github.com/NEZNAMY/f4cabf2fd9251a836b5eb877720dee5c/ for more info.",
|
||||
"---------------------------------------------------------------------"
|
||||
}) {
|
||||
TAB.getInstance().getPlatform().logWarn(TabComponent.fromColoredText(message));
|
||||
}
|
||||
} else {
|
||||
featureManager.registerFeature(TabConstants.Feature.NAME_TAGS, unlimited);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,9 @@ import org.jetbrains.annotations.NotNull;
|
||||
public enum ProtocolVersion {
|
||||
|
||||
UNKNOWN,
|
||||
V1_21_1 (767),
|
||||
V1_21 (767),
|
||||
V1_20_6 (766),
|
||||
V1_20_5 (766),
|
||||
V1_20_4 (765),
|
||||
V1_20_3 (765),
|
||||
@@ -76,8 +79,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 = VALUES[1];
|
||||
|
||||
/** Version's network id found at <a href="https://wiki.vg/Protocol_version_numbers">wiki.vg</a> */
|
||||
private final int networkId;
|
||||
@@ -146,7 +152,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;
|
||||
|
||||
@@ -10,7 +10,7 @@ import me.neznamy.tab.api.scoreboard.ScoreboardManager;
|
||||
import me.neznamy.tab.api.tablist.HeaderFooterManager;
|
||||
import me.neznamy.tab.api.tablist.TabListFormatManager;
|
||||
import me.neznamy.tab.shared.chat.EnumChatFormat;
|
||||
import me.neznamy.tab.shared.chat.SimpleComponent;
|
||||
import me.neznamy.tab.shared.chat.TabComponent;
|
||||
import me.neznamy.tab.shared.config.helper.ConfigHelper;
|
||||
import me.neznamy.tab.shared.cpu.CpuManager;
|
||||
import me.neznamy.tab.shared.features.nametags.NameTag;
|
||||
@@ -28,6 +28,8 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.yaml.snakeyaml.error.YAMLException;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@@ -184,10 +186,10 @@ public class TAB extends TabAPI {
|
||||
cpu.enable();
|
||||
configHelper.startup().checkErrorLog();
|
||||
configHelper.startup().printWarnCount();
|
||||
platform.logInfo(new SimpleComponent(EnumChatFormat.GREEN + "Enabled in " + (System.currentTimeMillis()-time) + "ms"));
|
||||
platform.logInfo(TabComponent.fromColoredText(EnumChatFormat.GREEN + "Enabled in " + (System.currentTimeMillis()-time) + "ms"));
|
||||
return configuration.getMessages().getReloadSuccess();
|
||||
} catch (YAMLException e) {
|
||||
platform.logWarn(new SimpleComponent(EnumChatFormat.RED + "Did not enable due to a broken configuration file."));
|
||||
platform.logWarn(TabComponent.fromColoredText(EnumChatFormat.RED + "Did not enable due to a broken configuration file."));
|
||||
kill();
|
||||
return (configuration == null ? "&4Failed to reload, file %file% has broken syntax. Check console for more info."
|
||||
: configuration.getMessages().getReloadFailBrokenFile()).replace("%file%", brokenFile);
|
||||
@@ -208,7 +210,7 @@ public class TAB extends TabAPI {
|
||||
long time = System.currentTimeMillis();
|
||||
if (configuration.getMysql() != null) configuration.getMysql().closeConnection();
|
||||
featureManager.unload();
|
||||
platform.logInfo(new SimpleComponent(EnumChatFormat.GREEN + "Disabled in " + (System.currentTimeMillis()-time) + "ms"));
|
||||
platform.logInfo(TabComponent.fromColoredText(EnumChatFormat.GREEN + "Disabled in " + (System.currentTimeMillis()-time) + "ms"));
|
||||
} catch (Throwable e) {
|
||||
errorManager.criticalError("Failed to disable", e);
|
||||
}
|
||||
@@ -293,6 +295,11 @@ public class TAB extends TabAPI {
|
||||
return featureManager.getFeature(TabConstants.Feature.HEADER_FOOTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Collection<? extends TabPlayer> onlinePlayers() {
|
||||
return Collections.unmodifiableCollection(data.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable TabListFormatManager getTabListFormatManager() {
|
||||
return featureManager.getFeature(TabConstants.Feature.PLAYER_LIST);
|
||||
@@ -317,6 +324,6 @@ public class TAB extends TabAPI {
|
||||
*/
|
||||
public void debug(@NotNull String message) {
|
||||
if (configuration != null && configuration.isDebugMode())
|
||||
platform.logInfo(new SimpleComponent(EnumChatFormat.BLUE + "[DEBUG] " + message));
|
||||
platform.logInfo(TabComponent.fromColoredText(EnumChatFormat.BLUE + "[DEBUG] " + message));
|
||||
}
|
||||
}
|
||||
+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;
|
||||
}
|
||||
}
|
||||
@@ -19,4 +19,11 @@ public class SimpleComponent extends TabComponent {
|
||||
public String toLegacyText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String toRawText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -115,17 +115,14 @@ public class StructuredComponent extends TabComponent {
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns raw text without colors, only works correctly when component is organized
|
||||
*
|
||||
* @return raw text in this component and all child components
|
||||
*/
|
||||
public @NotNull String toRawText() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(text);
|
||||
for (StructuredComponent child : getExtra()) {
|
||||
builder.append(child.text);
|
||||
@Override
|
||||
@NotNull
|
||||
public String toRawText() {
|
||||
StringBuilder builder = new StringBuilder(text);
|
||||
for (StructuredComponent extra : getExtra()) {
|
||||
builder.append(extra.toRawText());
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -64,6 +64,15 @@ public abstract class TabComponent {
|
||||
*/
|
||||
public abstract String toLegacyText();
|
||||
|
||||
/**
|
||||
* Converts this component into a string that only consists of text without any formatting.
|
||||
*
|
||||
* @return String containing text of the component and extras
|
||||
*/
|
||||
@NotNull
|
||||
public abstract String toRawText();
|
||||
|
||||
|
||||
/**
|
||||
* Returns the most optimized component based on text. Returns null if text is null,
|
||||
* organized component if RGB colors are used or simple component with only text field
|
||||
@@ -213,8 +222,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());
|
||||
|
||||
@@ -14,13 +14,17 @@ public class MiniMessageFormat implements RGBFormatter {
|
||||
private static final LegacyComponentSerializer SERIALIZER = LegacyComponentSerializer.builder()
|
||||
.hexColors().useUnusualXRepeatedCharacterHexFormat().build();
|
||||
|
||||
/** Dummy character to append to disable MiniMessage's color compacting that prevents team color from being detected as last color of prefix */
|
||||
private static final char dummyChar = Character.MAX_VALUE;
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String reformat(@NotNull String text) {
|
||||
if (!text.contains("<")) return text; // User did not even attempt to use MiniMessage
|
||||
if (text.contains(EnumChatFormat.COLOR_STRING)) return text;
|
||||
try {
|
||||
return SERIALIZER.serialize(MiniMessage.miniMessage().deserialize(text));
|
||||
String serialized = SERIALIZER.serialize(MiniMessage.miniMessage().deserialize(text + dummyChar));
|
||||
return serialized.substring(0, serialized.length()-1); // Remove the dummy char back
|
||||
} catch (Throwable ignored) {
|
||||
return text;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import java.text.DecimalFormat;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import me.neznamy.tab.shared.chat.SimpleComponent;
|
||||
import me.neznamy.tab.shared.chat.TabComponent;
|
||||
import me.neznamy.tab.shared.cpu.CpuReport;
|
||||
import me.neznamy.tab.shared.platform.TabPlayer;
|
||||
import me.neznamy.tab.shared.chat.EnumChatFormat;
|
||||
@@ -74,13 +74,13 @@ public class CpuCommand extends SubCommand {
|
||||
}
|
||||
|
||||
public void sendToConsole(@NotNull Map<String, Map<String, Float>> features) {
|
||||
TAB.getInstance().getPlatform().logInfo(new SimpleComponent(EnumChatFormat.color("&8&l" + LINE_CHAR + " &6Features:")));
|
||||
TAB.getInstance().getPlatform().logInfo(TabComponent.fromColoredText(EnumChatFormat.color("&8&l" + LINE_CHAR + " &6Features:")));
|
||||
for (Entry<String, Map<String, Float>> entry : features.entrySet()) {
|
||||
TAB.getInstance().getPlatform().logInfo(new SimpleComponent(EnumChatFormat.color(
|
||||
TAB.getInstance().getPlatform().logInfo(TabComponent.fromColoredText(EnumChatFormat.color(
|
||||
String.format("&8&l%s &7%s &7(%s%%&7):", LINE_CHAR, entry.getKey(),
|
||||
colorize(decimal3.format(entry.getValue().values().stream().mapToDouble(Float::floatValue).sum()), 5, 1)))));
|
||||
for (Entry<String, Float> type : entry.getValue().entrySet()) {
|
||||
TAB.getInstance().getPlatform().logInfo(new SimpleComponent(EnumChatFormat.color(
|
||||
TAB.getInstance().getPlatform().logInfo(TabComponent.fromColoredText(EnumChatFormat.color(
|
||||
String.format("&8&l%s &7%s - %s%%", LINE_CHAR, type.getKey(), colorize(decimal3.format(type.getValue()), 5, 1)))));
|
||||
}
|
||||
}
|
||||
@@ -91,7 +91,7 @@ public class CpuCommand extends SubCommand {
|
||||
for (Entry<String, Map<String, Float>> entry : features.entrySet()) {
|
||||
double featureTotal = entry.getValue().values().stream().mapToDouble(Float::floatValue).sum();
|
||||
String core = String.format("&8&l%s &7%s &7(%s%%&7):", LINE_CHAR, entry.getKey(), colorize(decimal3.format(featureTotal), 5, 1));
|
||||
sender.sendMessage(new SimpleComponent(EnumChatFormat.color(core)));
|
||||
sender.sendMessage(TabComponent.fromColoredText(EnumChatFormat.color(core)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -42,7 +42,7 @@ public abstract class PropertyCommand extends SubCommand {
|
||||
server = args[args.length-1];
|
||||
value = value.startsWith("-s") ? "" : value.substring(0, value.length()-server.length()-4);
|
||||
}
|
||||
if ((value.startsWith("\"") && value.endsWith("\"")) || (value.startsWith("'") && value.endsWith("'"))) {
|
||||
if (((value.startsWith("\"") && value.endsWith("\"")) || (value.startsWith("'") && value.endsWith("'"))) && value.length() > 1) {
|
||||
value = value.substring(1, value.length()-1);
|
||||
}
|
||||
String property = args[1].toLowerCase();
|
||||
|
||||
+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);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package me.neznamy.tab.shared.config;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.TabConstants;
|
||||
import me.neznamy.tab.shared.chat.EnumChatFormat;
|
||||
import me.neznamy.tab.shared.chat.SimpleComponent;
|
||||
import me.neznamy.tab.shared.chat.TabComponent;
|
||||
import me.neznamy.tab.shared.config.file.ConfigurationFile;
|
||||
import me.neznamy.tab.shared.config.file.YamlConfigurationFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -25,7 +25,7 @@ public class Converter {
|
||||
|
||||
public void convert2810to290(@NotNull ConfigurationFile animations) {
|
||||
if (animations.getValues().size() == 1 && animations.getValues().containsKey("animations")) {
|
||||
TAB.getInstance().getPlatform().logInfo(new SimpleComponent(EnumChatFormat.YELLOW + "Performing configuration conversion from 2.8.10 to 2.9.0"));
|
||||
TAB.getInstance().getPlatform().logInfo(TabComponent.fromColoredText(EnumChatFormat.YELLOW + "Performing configuration conversion from 2.8.10 to 2.9.0"));
|
||||
animations.setValues(animations.getConfigurationSection("animations"));
|
||||
animations.save();
|
||||
}
|
||||
@@ -42,7 +42,7 @@ public class Converter {
|
||||
*/
|
||||
public void convert292to300(@NotNull ConfigurationFile currentConfig) throws IOException {
|
||||
if (!currentConfig.hasConfigOption("change-nametag-prefix-suffix")) return;
|
||||
TAB.getInstance().getPlatform().logInfo(new SimpleComponent(EnumChatFormat.YELLOW + "Performing configuration conversion from 2.9.2 to 3.0.0"));
|
||||
TAB.getInstance().getPlatform().logInfo(TabComponent.fromColoredText(EnumChatFormat.YELLOW + "Performing configuration conversion from 2.9.2 to 3.0.0"));
|
||||
|
||||
File folder = TAB.getInstance().getDataFolder();
|
||||
moveOldFiles();
|
||||
@@ -346,13 +346,13 @@ public class Converter {
|
||||
|
||||
public void convert301to302(@NotNull ConfigurationFile config) {
|
||||
if (config.removeOption("placeholders.remove-strings")) {
|
||||
TAB.getInstance().getPlatform().logInfo(new SimpleComponent(EnumChatFormat.YELLOW + "Performing configuration conversion from 3.0.1 to 3.0.2"));
|
||||
TAB.getInstance().getPlatform().logInfo(TabComponent.fromColoredText(EnumChatFormat.YELLOW + "Performing configuration conversion from 3.0.1 to 3.0.2"));
|
||||
}
|
||||
}
|
||||
|
||||
public void convert331to332(@NotNull ConfigurationFile config) {
|
||||
if (config.removeOption("scoreboard-teams.unlimited-nametag-mode.use-marker-tag-for-1-8-x-clients")) {
|
||||
TAB.getInstance().getPlatform().logInfo(new SimpleComponent(EnumChatFormat.YELLOW + "Performing configuration conversion from 3.3.1 to 3.3.2)"));
|
||||
TAB.getInstance().getPlatform().logInfo(TabComponent.fromColoredText(EnumChatFormat.YELLOW + "Performing configuration conversion from 3.3.1 to 3.3.2)"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,7 +360,7 @@ public class Converter {
|
||||
public void convert332to400(@NotNull ConfigurationFile config) throws IOException {
|
||||
// Removed config options
|
||||
if (config.hasConfigOption("fix-pet-names")) {
|
||||
TAB.getInstance().getPlatform().logInfo(new SimpleComponent(EnumChatFormat.YELLOW + "Performing configuration conversion from 3.3.2 to 4.0.0"));
|
||||
TAB.getInstance().getPlatform().logInfo(TabComponent.fromColoredText(EnumChatFormat.YELLOW + "Performing configuration conversion from 3.3.2 to 4.0.0"));
|
||||
config.set("fix-pet-names", null);
|
||||
config.set("bossbar.disable-in-worlds", null);
|
||||
config.set("bossbar.disable-in-servers", null);
|
||||
@@ -425,13 +425,13 @@ public class Converter {
|
||||
|
||||
public void convert403to404(@NotNull ConfigurationFile config) {
|
||||
if (config.removeOption("global-playerlist.update-latency")) {
|
||||
TAB.getInstance().getPlatform().logInfo(new SimpleComponent(EnumChatFormat.YELLOW + "Performing configuration conversion from 4.0.3 to 4.0.4"));
|
||||
TAB.getInstance().getPlatform().logInfo(TabComponent.fromColoredText(EnumChatFormat.YELLOW + "Performing configuration conversion from 4.0.3 to 4.0.4"));
|
||||
}
|
||||
}
|
||||
|
||||
public void convert409to410(@NotNull ConfigurationFile config) {
|
||||
if (config.hasConfigOption("yellow-number-in-tablist")) {
|
||||
TAB.getInstance().getPlatform().logInfo(new SimpleComponent(EnumChatFormat.YELLOW + "Performing configuration conversion from 4.0.9 to 4.1.0"));
|
||||
TAB.getInstance().getPlatform().logInfo(TabComponent.fromColoredText(EnumChatFormat.YELLOW + "Performing configuration conversion from 4.0.9 to 4.1.0"));
|
||||
Map<Object, Object> section = config.getConfigurationSection("yellow-number-in-tablist");
|
||||
section.put("fancy-value", "&7Ping: %ping%");
|
||||
config.set("yellow-number-in-tablist", null);
|
||||
|
||||
@@ -14,7 +14,7 @@ import java.util.List;
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.chat.EnumChatFormat;
|
||||
import me.neznamy.tab.shared.chat.SimpleComponent;
|
||||
import me.neznamy.tab.shared.chat.TabComponent;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.yaml.snakeyaml.DumperOptions;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
@@ -56,13 +56,13 @@ public class YamlConfigurationFile extends ConfigurationFile {
|
||||
if (input != null) input.close();
|
||||
TAB tab = TAB.getInstance();
|
||||
tab.setBrokenFile(destination.getName());
|
||||
tab.getPlatform().logWarn(new SimpleComponent("File " + destination + " has broken syntax."));
|
||||
tab.getPlatform().logInfo(new SimpleComponent(EnumChatFormat.GOLD + "Error message from yaml parser: " + e.getMessage()));
|
||||
tab.getPlatform().logWarn(TabComponent.fromColoredText("File " + destination + " has broken syntax."));
|
||||
tab.getPlatform().logInfo(TabComponent.fromColoredText(EnumChatFormat.GOLD + "Error message from yaml parser: " + e.getMessage()));
|
||||
List<String> suggestions = YamlAssist.getSuggestions(file);
|
||||
if (!suggestions.isEmpty()) {
|
||||
tab.getPlatform().logInfo(new SimpleComponent(EnumChatFormat.LIGHT_PURPLE + "Suggestions to fix yaml syntax:"));
|
||||
tab.getPlatform().logInfo(TabComponent.fromColoredText(EnumChatFormat.LIGHT_PURPLE + "Suggestions to fix yaml syntax:"));
|
||||
for (String suggestion : suggestions) {
|
||||
tab.getPlatform().logInfo(new SimpleComponent(EnumChatFormat.LIGHT_PURPLE + "- " + suggestion));
|
||||
tab.getPlatform().logInfo(TabComponent.fromColoredText(EnumChatFormat.LIGHT_PURPLE + "- " + suggestion));
|
||||
}
|
||||
}
|
||||
throw e;
|
||||
@@ -79,7 +79,7 @@ public class YamlConfigurationFile extends ConfigurationFile {
|
||||
writer.close();
|
||||
fixHeader();
|
||||
} catch (IOException e) {
|
||||
TAB.getInstance().getPlatform().logWarn(new SimpleComponent("Failed to save yaml file " + file.getPath() + " with content " + values.toString()));
|
||||
TAB.getInstance().getPlatform().logWarn(TabComponent.fromColoredText("Failed to save yaml file " + file.getPath() + " with content " + values.toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ package me.neznamy.tab.shared.config.helper;
|
||||
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.chat.EnumChatFormat;
|
||||
import me.neznamy.tab.shared.chat.SimpleComponent;
|
||||
import me.neznamy.tab.shared.chat.TabComponent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Map;
|
||||
@@ -100,6 +100,6 @@ public class HintPrinter {
|
||||
* Message to log
|
||||
*/
|
||||
private void hint(@NotNull String message) {
|
||||
TAB.getInstance().getPlatform().logInfo(new SimpleComponent(EnumChatFormat.GOLD + "[Hint] " + message));
|
||||
TAB.getInstance().getPlatform().logInfo(TabComponent.fromColoredText(EnumChatFormat.GOLD + "[Hint] " + message));
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package me.neznamy.tab.shared.config.helper;
|
||||
import me.neznamy.tab.api.bossbar.BossBar;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.chat.EnumChatFormat;
|
||||
import me.neznamy.tab.shared.chat.SimpleComponent;
|
||||
import me.neznamy.tab.shared.chat.TabComponent;
|
||||
import me.neznamy.tab.shared.features.sorting.types.SortingType;
|
||||
import me.neznamy.tab.shared.platform.TabPlayer;
|
||||
import me.neznamy.tab.shared.proxy.ProxyTabPlayer;
|
||||
@@ -196,6 +196,6 @@ public class RuntimeErrorPrinter {
|
||||
* Message to log
|
||||
*/
|
||||
private void error(@NotNull String message) {
|
||||
TAB.getInstance().getPlatform().logWarn(new SimpleComponent(message));
|
||||
TAB.getInstance().getPlatform().logWarn(TabComponent.fromColoredText(message));
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import me.neznamy.tab.api.bossbar.BarColor;
|
||||
import me.neznamy.tab.api.bossbar.BarStyle;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.TabConstants;
|
||||
import me.neznamy.tab.shared.chat.SimpleComponent;
|
||||
import me.neznamy.tab.shared.chat.TabComponent;
|
||||
import me.neznamy.tab.shared.features.layout.GroupPattern;
|
||||
import me.neznamy.tab.shared.features.layout.LayoutManagerImpl;
|
||||
import me.neznamy.tab.shared.features.sorting.types.SortingType;
|
||||
@@ -389,7 +389,7 @@ public class StartupWarnPrinter {
|
||||
private void startupWarn(@NotNull String... messages) {
|
||||
warnCount++;
|
||||
for (String message : messages) {
|
||||
TAB.getInstance().getPlatform().logWarn(new SimpleComponent(message));
|
||||
TAB.getInstance().getPlatform().logWarn(TabComponent.fromColoredText(message));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -398,7 +398,7 @@ public class StartupWarnPrinter {
|
||||
*/
|
||||
public void printWarnCount() {
|
||||
if (warnCount == 0) return;
|
||||
TAB.getInstance().getPlatform().logWarn(new SimpleComponent("Found a total of " + warnCount + " issues."));
|
||||
TAB.getInstance().getPlatform().logWarn(TabComponent.fromColoredText("Found a total of " + warnCount + " issues."));
|
||||
// Reset after printing to prevent count going up on each reload
|
||||
warnCount = 0;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.chat.EnumChatFormat;
|
||||
import me.neznamy.tab.shared.chat.SimpleComponent;
|
||||
import me.neznamy.tab.shared.chat.TabComponent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -37,7 +37,7 @@ public class MySQL {
|
||||
properties.setProperty("useSSL", String.valueOf(useSSL));
|
||||
properties.setProperty("characterEncoding", "UTF-8");
|
||||
con = DriverManager.getConnection(String.format("jdbc:mysql://%s:%d/%s", host, port, database), properties);
|
||||
TAB.getInstance().getPlatform().logInfo(new SimpleComponent(EnumChatFormat.GREEN + "Successfully connected to MySQL"));
|
||||
TAB.getInstance().getPlatform().logInfo(TabComponent.fromColoredText(EnumChatFormat.GREEN + "Successfully connected to MySQL"));
|
||||
}
|
||||
|
||||
public void closeConnection() throws SQLException {
|
||||
|
||||
@@ -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));
|
||||
"Layout-" + name + "-SLOT-" + slot, skin, "Layout-" + name + "-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;
|
||||
}
|
||||
}
|
||||
@@ -227,6 +227,16 @@ public abstract class RedisSupport extends TabFeature implements JoinListener, Q
|
||||
}
|
||||
return count;
|
||||
});
|
||||
TAB.getInstance().getPlaceholderManager().registerPlayerPlaceholder(TabConstants.Placeholder.SERVER_ONLINE, 1000, p -> {
|
||||
int count = 0;
|
||||
for (TabPlayer player : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (((TabPlayer)p).getServer().equals(player.getServer()) && !player.isVanished()) count++;
|
||||
}
|
||||
for (RedisPlayer player : redisPlayers.values()) {
|
||||
if (((TabPlayer)p).getServer().equals(player.getServer()) && !player.isVanished()) count++;
|
||||
}
|
||||
return count;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+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();
|
||||
}
|
||||
}
|
||||
Loaded 100 of 136 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user