mirror of
https://github.com/NEZNAMY/TAB.git
synced 2026-11-12 20:22:01 -05:00
Compare commits
34
Commits
2.9.0
..
2.9.2-pre1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
341b552d0b | ||
|
|
1586bd9768 | ||
|
|
e8dde3a756 | ||
|
|
bb591bf56d | ||
|
|
8cf83b276a | ||
|
|
a1547a7288 | ||
|
|
0722403a23 | ||
|
|
cd4a91d975 | ||
|
|
c7870b4e9d | ||
|
|
239dae5a65 | ||
|
|
13c89d18d7 | ||
|
|
c5dc42eafe | ||
|
|
59b3faab1e | ||
|
|
b88beb5002 | ||
|
|
9fea35c25d | ||
|
|
372013bcc6 | ||
|
|
20ca58b570 | ||
|
|
9c4cca20fb | ||
|
|
6b8536a86e | ||
|
|
3b41857637 | ||
|
|
fa78ac2157 | ||
|
|
0a0bb9c83c | ||
|
|
36834a039e | ||
|
|
4960c898bb | ||
|
|
af61edbc5c | ||
|
|
237bfc08a1 | ||
|
|
032e9a089d | ||
|
|
ba83779dde | ||
|
|
267d72f844 | ||
|
|
b533cdb89f | ||
|
|
3f118ac76b | ||
|
|
08a8f0097c | ||
|
|
c7a3599e46 | ||
|
|
62f80baa69 |
No files matched your search
@@ -5,7 +5,7 @@ It's already been a year and I still can't see any positives of it. This way I j
|
||||
|
||||
## Compiling
|
||||
Plugin can be compiled using maven. Once you've purchased the premium version, you can enable premium features by setting [this line to return true](https://github.com/NEZNAMY/TAB/blob/master/shared/src/main/java/me/neznamy/tab/shared/TAB.java#L78) and apply your code improvements. Enabling it without purchasing the plugin may result in the features not working correctly.
|
||||
**No support is provided for self-compiled jars, only for official compilations.** If you compiled it yourself, it is highly likely you modified something, which might be the reason why is the plugin not working. If you didn't modify anything, you can just get the plugin from official download places.
|
||||
**No support is provided for self-compiled jars, only for official compilations.** If you compiled it yourself, it is highly likely you modified something, which might be the reason why is the plugin not working. If you didn't modify anything, you can just get the plugin from official download locations.
|
||||
|
||||
|
||||
## Links
|
||||
@@ -34,8 +34,8 @@ Discord invite link: https://discord.gg/EaSvdk6
|
||||
<!-- TAB -->
|
||||
<dependency>
|
||||
<groupId>com.github.NEZNAMY</groupId>
|
||||
<artifactId>TAB-API</artifactId>
|
||||
<version>2.8.10</version>
|
||||
<artifactId>TAB</artifactId>
|
||||
<version>2.9.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
```
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>me.neznamy</groupId>
|
||||
<artifactId>TAB</artifactId>
|
||||
<version>2.9.0</version>
|
||||
<version>2.9.2-pre1</version>
|
||||
</parent>
|
||||
<artifactId>bukkit</artifactId>
|
||||
|
||||
|
||||
@@ -32,7 +32,20 @@ public class BukkitEventListener implements Listener {
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onJoin(PlayerJoinEvent e) {
|
||||
if (TAB.getInstance().isDisabled()) return;
|
||||
TAB.getInstance().getCPUManager().runTask("processing PlayerJoinEvent", () -> TAB.getInstance().getFeatureManager().onJoin(new BukkitTabPlayer(e.getPlayer())));
|
||||
TAB.getInstance().getCPUManager().runTask("processing PlayerJoinEvent", () -> {
|
||||
try {
|
||||
int i = 0;
|
||||
int version;
|
||||
while ((version = Main.getProtocolVersion(e.getPlayer())) == -1 && ++i < 50) {
|
||||
Thread.sleep(1);
|
||||
}
|
||||
if (!e.getPlayer().isOnline()) return;
|
||||
if (i == 50) {
|
||||
TAB.getInstance().getErrorManager().printError("Failed to get protocol version of " + e.getPlayer().getName() + " after 50 retries");
|
||||
}
|
||||
TAB.getInstance().getFeatureManager().onJoin(new BukkitTabPlayer(e.getPlayer(), version));
|
||||
} catch (InterruptedException e1) {}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+11
-14
@@ -146,43 +146,40 @@ public class BukkitPlaceholderRegistry implements PlaceholderRegistry {
|
||||
String yesAfk = TAB.getInstance().getConfiguration().config.getString("placeholders.afk-yes", " &4*&4&lAFK&4*&r");
|
||||
placeholders.add(new PlayerPlaceholder("%afk%", 500) {
|
||||
public String get(TabPlayer p) {
|
||||
boolean afk = false;
|
||||
try {
|
||||
if (Bukkit.getPluginManager().isPluginEnabled("Essentials")) {
|
||||
Object user = Bukkit.getPluginManager().getPlugin("Essentials").getClass().getMethod("getUser", Player.class).invoke(Bukkit.getPluginManager().getPlugin("Essentials"), p.getPlayer());
|
||||
afk = (boolean) user.getClass().getMethod("isAfk").invoke(user);
|
||||
if ((boolean) user.getClass().getMethod("isAfk").invoke(user)) return yesAfk;
|
||||
}
|
||||
if (Bukkit.getPluginManager().isPluginEnabled("AFKPlus")) {
|
||||
Object AFKPlus = Bukkit.getPluginManager().getPlugin("AFKPlus");
|
||||
Object AFKPlusPlayer = AFKPlus.getClass().getMethod("getPlayer", UUID.class).invoke(AFKPlus, p.getUniqueId());
|
||||
afk = (boolean) AFKPlusPlayer.getClass().getMethod("isAFK").invoke(AFKPlusPlayer);
|
||||
if ((boolean) AFKPlusPlayer.getClass().getMethod("isAFK").invoke(AFKPlusPlayer)) return yesAfk;
|
||||
}
|
||||
if (Bukkit.getPluginManager().isPluginEnabled("AntiAFKPlus")) {
|
||||
Object api = Class.forName("de.kinglol12345.AntiAFKPlus.api.AntiAFKPlusAPI").getDeclaredMethod("getAPI").invoke(null);
|
||||
afk = (boolean) api.getClass().getMethod("isAFK", Player.class).invoke(api, p.getPlayer());
|
||||
if ((boolean) api.getClass().getMethod("isAFK", Player.class).invoke(api, p.getPlayer())) return yesAfk;
|
||||
}
|
||||
if (Bukkit.getPluginManager().isPluginEnabled("xAntiAFK")) {
|
||||
afk = (boolean) Class.forName("ch.soolz.xantiafk.xAntiAFKAPI").getMethod("isAfk", Player.class).invoke(null, p.getPlayer());
|
||||
if ((boolean) Class.forName("ch.soolz.xantiafk.xAntiAFKAPI").getMethod("isAfk", Player.class).invoke(null, p.getPlayer())) return yesAfk;
|
||||
}
|
||||
if (Bukkit.getPluginManager().isPluginEnabled("AutoAFK")) {
|
||||
Object plugin = Bukkit.getPluginManager().getPlugin("AutoAFK");
|
||||
Field f = plugin.getClass().getDeclaredField("afkList");
|
||||
f.setAccessible(true);
|
||||
HashMap<?, ?> map = (HashMap<?, ?>) f.get(plugin);
|
||||
afk = map.containsKey(p.getPlayer());
|
||||
if (map.containsKey(p.getPlayer())) return yesAfk;
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
return TAB.getInstance().getErrorManager().printError("", "Failed to check AFK status of " + p.getName(), t);
|
||||
}
|
||||
if (!afk) {
|
||||
try {
|
||||
//purpur AFK API
|
||||
afk = (boolean) p.getPlayer().getClass().getMethod("isAfk").invoke(p.getPlayer());
|
||||
} catch (Throwable t) {
|
||||
//not purpur
|
||||
}
|
||||
try {
|
||||
//purpur AFK API
|
||||
if ((boolean) p.getPlayer().getClass().getMethod("isAfk").invoke(p.getPlayer())) return yesAfk;
|
||||
} catch (Throwable t) {
|
||||
//not purpur
|
||||
}
|
||||
return afk ? yesAfk : noAfk;
|
||||
return noAfk;
|
||||
}
|
||||
@Override
|
||||
public String[] getNestedStrings(){
|
||||
|
||||
@@ -115,7 +115,7 @@ public class BukkitPlatform implements Platform {
|
||||
}
|
||||
|
||||
for (Player p : getOnlinePlayers()) {
|
||||
tab.addPlayer(new BukkitTabPlayer(p));
|
||||
tab.addPlayer(new BukkitTabPlayer(p, Main.getProtocolVersion(p)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,11 +186,12 @@ public class BukkitPlatform implements Platform {
|
||||
* @param refresh - refresh interval in milliseconds
|
||||
*/
|
||||
private void registerServerPlaceholder(String identifier, int refresh) {
|
||||
BukkitPlatform pl = this;
|
||||
TAB.getInstance().getPlaceholderManager().registerPlaceholder(new ServerPlaceholder(identifier, TAB.getInstance().getErrorManager().fixPlaceholderInterval(identifier, refresh)){
|
||||
|
||||
@Override
|
||||
public String get() {
|
||||
return setPlaceholders(null, identifier);
|
||||
return pl.setPlaceholders(null, identifier);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -201,11 +202,12 @@ public class BukkitPlatform implements Platform {
|
||||
* @param refresh - refresh interval in milliseconds
|
||||
*/
|
||||
private void registerPlayerPlaceholder(String identifier, int refresh) {
|
||||
BukkitPlatform pl = this;
|
||||
TAB.getInstance().getPlaceholderManager().registerPlaceholder(new PlayerPlaceholder(identifier, TAB.getInstance().getErrorManager().fixPlaceholderInterval(identifier, refresh)) {
|
||||
|
||||
@Override
|
||||
public String get(TabPlayer p) {
|
||||
return setPlaceholders((Player) p.getPlayer(), identifier);
|
||||
return pl.setPlaceholders((Player) p.getPlayer(), identifier);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ public class BukkitTabPlayer extends ITabPlayer {
|
||||
* Constructs new instance with given parameter
|
||||
* @param p - bukkit player
|
||||
*/
|
||||
public BukkitTabPlayer(Player p){
|
||||
public BukkitTabPlayer(Player p, int protocolVersion){
|
||||
player = p;
|
||||
world = p.getWorld().getName();
|
||||
try {
|
||||
@@ -65,55 +65,10 @@ public class BukkitTabPlayer extends ITabPlayer {
|
||||
}
|
||||
uniqueId = p.getUniqueId();
|
||||
name = p.getName();
|
||||
version = ProtocolVersion.fromNetworkId(getProtocolVersion());
|
||||
version = ProtocolVersion.fromNetworkId(protocolVersion);
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets protocol version and returns it
|
||||
* @return protocol version of this player
|
||||
*/
|
||||
private int getProtocolVersion() {
|
||||
if (Bukkit.getPluginManager().isPluginEnabled("ProtocolSupport")){
|
||||
int version = getProtocolVersionPS();
|
||||
//some PS versions return -1 on unsupported server versions instead of throwing exception
|
||||
if (version != -1 && version < ProtocolVersion.SERVER_VERSION.getNetworkId()) return version;
|
||||
}
|
||||
if (((BukkitPlatform)TAB.getInstance().getPlatform()).viaversion) {
|
||||
return getProtocolVersionVia();
|
||||
}
|
||||
return ProtocolVersion.SERVER_VERSION.getNetworkId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns protocol version of this player using ProtocolSupport
|
||||
* @return protocol version of this player using ProtocolSupport
|
||||
*/
|
||||
private int getProtocolVersionPS(){
|
||||
try {
|
||||
Object protocolVersion = Class.forName("protocolsupport.api.ProtocolSupportAPI").getMethod("getProtocolVersion", Player.class).invoke(null, player);
|
||||
int version = (int) protocolVersion.getClass().getMethod("getId").invoke(protocolVersion);
|
||||
TAB.getInstance().debug("ProtocolSupport returned protocol version " + version + " for " + getName());
|
||||
return version;
|
||||
} catch (Throwable e) {
|
||||
return TAB.getInstance().getErrorManager().printError(ProtocolVersion.SERVER_VERSION.getNetworkId(), "Failed to get protocol version of " + getName() + " using ProtocolSupport", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns protocol version of this player using ViaVersion
|
||||
* @return protocol version of this player using ViaVersion
|
||||
*/
|
||||
private int getProtocolVersionVia(){
|
||||
try {
|
||||
int version = Via.getAPI().getPlayerVersion(uniqueId);
|
||||
TAB.getInstance().debug("ViaVersion returned protocol version " + version + " for " + getName());
|
||||
return version;
|
||||
} catch (Throwable e) {
|
||||
return TAB.getInstance().getErrorManager().printError(ProtocolVersion.SERVER_VERSION.getNetworkId(), "Failed to get protocol version of " + getName() + " using ViaVersion v" + Bukkit.getPluginManager().getPlugin("ViaVersion").getDescription().getVersion() + ". Is it the latest version?", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String permission) {
|
||||
return player.hasPermission(permission);
|
||||
@@ -179,12 +134,8 @@ public class BukkitTabPlayer extends ITabPlayer {
|
||||
bossbars.get(packet.id).setTitle(RGBUtils.getInstance().convertToBukkitFormat(packet.name, getVersion().getMinorVersion() >= 16 && NMSStorage.getInstance().minorVersion >= 16));
|
||||
break;
|
||||
case UPDATE_STYLE:
|
||||
bar = bossbars.get(packet.id);
|
||||
//yet another platform with yet another buggy bossbar API, how lovely it is regressing back to APIs instead of internals
|
||||
bar.removePlayer(player);
|
||||
bar.setColor(BarColor.valueOf(packet.color.name()));
|
||||
bar.setStyle(BarStyle.valueOf(packet.overlay.name().replace("PROGRESS", "SOLID").replace("NOTCHED", "SEGMENTED")));
|
||||
bar.addPlayer(player);
|
||||
bossbars.get(packet.id).setColor(BarColor.valueOf(packet.color.name()));
|
||||
bossbars.get(packet.id).setStyle(BarStyle.valueOf(packet.overlay.name().replace("PROGRESS", "SOLID").replace("NOTCHED", "SEGMENTED")));
|
||||
break;
|
||||
case UPDATE_PROPERTIES:
|
||||
bar = bossbars.get(packet.id);
|
||||
|
||||
@@ -8,6 +8,8 @@ import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.NMSStorage;
|
||||
import me.neznamy.tab.shared.ProtocolVersion;
|
||||
@@ -80,16 +82,63 @@ public class Main extends JavaPlugin {
|
||||
if (SUPPORTED_VERSIONS.contains(serverPackage)) {
|
||||
return true;
|
||||
} else {
|
||||
Bukkit.getConsoleSender().sendMessage("\u00a7c[TAB] This plugin version does not claim to support your server version. This jar has only been tested on 1.7.x - 1.16.5. Disabling.");
|
||||
Bukkit.getConsoleSender().sendMessage("\u00a7c[TAB] No compatibility issue was found, but this plugin version does not claim to support your server version. This jar has only been tested on 1.5.x - 1.17. Disabling just to stay safe.");
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
if (SUPPORTED_VERSIONS.contains(serverPackage)) {
|
||||
Bukkit.getConsoleSender().sendMessage("\u00a7c[TAB] Your server version is marked as compatible, but a compatibility issue was found. Please report the error below (include your server version & fork too)");
|
||||
e.printStackTrace();
|
||||
} else {
|
||||
Bukkit.getConsoleSender().sendMessage("\u00a7c[TAB] Your server version is completely unsupported. This plugin version only supports 1.7.x - 1.16.5. Disabling.");
|
||||
Bukkit.getConsoleSender().sendMessage("\u00a7c[TAB] Your server version is completely unsupported. This plugin version only supports 1.5.x - 1.17. Disabling.");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets protocol version and returns it
|
||||
* @return protocol version of this player
|
||||
*/
|
||||
public static int getProtocolVersion(Player player) {
|
||||
if (Bukkit.getPluginManager().isPluginEnabled("ProtocolSupport")){
|
||||
int version = getProtocolVersionPS(player);
|
||||
//some PS versions return -1 on unsupported server versions instead of throwing exception
|
||||
if (version != -1 && version < ProtocolVersion.SERVER_VERSION.getNetworkId()) return version;
|
||||
}
|
||||
if (((BukkitPlatform)TAB.getInstance().getPlatform()).viaversion) {
|
||||
return getProtocolVersionVia(player);
|
||||
}
|
||||
return ProtocolVersion.SERVER_VERSION.getNetworkId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns protocol version of this player using ProtocolSupport
|
||||
* @return protocol version of this player using ProtocolSupport
|
||||
*/
|
||||
private static int getProtocolVersionPS(Player player){
|
||||
try {
|
||||
Object protocolVersion = Class.forName("protocolsupport.api.ProtocolSupportAPI").getMethod("getProtocolVersion", Player.class).invoke(null, player);
|
||||
int version = (int) protocolVersion.getClass().getMethod("getId").invoke(protocolVersion);
|
||||
TAB.getInstance().debug("ProtocolSupport returned protocol version " + version + " for " + player.getName() + "(online=" + player.isOnline() + ")");
|
||||
return version;
|
||||
} catch (Throwable e) {
|
||||
TAB.getInstance().getErrorManager().printError("Failed to get protocol version of " + player.getName() + " using ProtocolSupport", e);
|
||||
return ProtocolVersion.SERVER_VERSION.getNetworkId();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns protocol version of this player using ViaVersion
|
||||
* @return protocol version of this player using ViaVersion
|
||||
*/
|
||||
private static int getProtocolVersionVia(Player player){
|
||||
try {
|
||||
int version = Via.getAPI().getPlayerVersion(player.getUniqueId());
|
||||
TAB.getInstance().debug("ViaVersion returned protocol version " + version + " for " + player.getName() + "(online=" + player.isOnline() + ")");
|
||||
return version;
|
||||
} catch (Throwable e) {
|
||||
TAB.getInstance().getErrorManager().printError("Failed to get protocol version of " + player.getName() + " using ViaVersion v" + Bukkit.getPluginManager().getPlugin("ViaVersion").getDescription().getVersion(), e);
|
||||
return ProtocolVersion.SERVER_VERSION.getNetworkId();
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -43,7 +43,9 @@ public class PerWorldPlayerlist implements Loadable, Listener {
|
||||
ignoredWorlds = tab.getConfiguration().config.getStringList("per-world-playerlist.ignore-effect-in-worlds", Arrays.asList("ignoredworld", "build"));
|
||||
sharedWorlds = tab.getConfiguration().config.getConfigurationSection("per-world-playerlist.shared-playerlist-world-groups");
|
||||
for (String group : sharedWorlds.keySet()) {
|
||||
if (sharedWorlds.get(group).size() == 1) {
|
||||
if (sharedWorlds.get(group) == null) {
|
||||
tab.getErrorManager().startupWarn("World group \"" + group + "\" in per-world-playerlist does not contain any worlds. You can just remove the group.");
|
||||
} else if (sharedWorlds.get(group).size() == 1) {
|
||||
tab.getErrorManager().startupWarn("World group \"" + group + "\" in per-world-playerlist only contain a single world (\"" + sharedWorlds.get(group).get(0) +
|
||||
"\"), which has no effect and only makes config less readable. Delete the group entirely for a cleaner config.");
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ public class PetFix implements RawPacketListener, QuitEventListener {
|
||||
//last interact packet was sent right now, cancelling to prevent double-toggle due to this feature enabled
|
||||
return null;
|
||||
}
|
||||
if (nms.PacketPlayInUseEntity_ACTION.get(packet).toString().equals("INTERACT")) {
|
||||
if (isInteract(nms.PacketPlayInUseEntity_ACTION.get(packet))) {
|
||||
//this is the first packet, saving player so the next packet can be cancelled
|
||||
lastInteractFix.put(sender.getName(), System.currentTimeMillis());
|
||||
}
|
||||
@@ -81,6 +81,14 @@ public class PetFix implements RawPacketListener, QuitEventListener {
|
||||
return packet;
|
||||
}
|
||||
|
||||
private boolean isInteract(Object action) {
|
||||
if (nms.minorVersion >= 17) {
|
||||
return action.getClass().getSimpleName().equals("d");
|
||||
} else {
|
||||
return action.toString().equals("INTERACT");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes pet owner field from datawatcher
|
||||
*/
|
||||
|
||||
+10
-13
@@ -66,20 +66,15 @@ public class PacketListener implements RawPacketListener {
|
||||
if (!receiver.isLoaded() || nameTagX.isDisabledWorld(world) || nameTagX.isDisabledWorld(nameTagX.disabledUnlimitedWorlds, world)) return;
|
||||
if (nms.PacketPlayOutEntity.isInstance(packet) && !nms.PacketPlayOutEntityLook.isInstance(packet)) { //ignoring head rotation only packets
|
||||
onEntityMove(receiver, nms.PacketPlayOutEntity_ENTITYID.getInt(packet));
|
||||
}
|
||||
if (nms.PacketPlayOutEntityTeleport.isInstance(packet)) {
|
||||
} else if (nms.PacketPlayOutEntityTeleport.isInstance(packet)) {
|
||||
onEntityMove(receiver, nms.PacketPlayOutEntityTeleport_ENTITYID.getInt(packet));
|
||||
}
|
||||
if (nms.PacketPlayOutNamedEntitySpawn.isInstance(packet)) {
|
||||
} else if (nms.PacketPlayOutNamedEntitySpawn.isInstance(packet)) {
|
||||
onEntitySpawn(receiver, nms.PacketPlayOutNamedEntitySpawn_ENTITYID.getInt(packet));
|
||||
}
|
||||
if (nms.PacketPlayOutEntityDestroy.isInstance(packet)) {
|
||||
} else if (nms.PacketPlayOutEntityDestroy.isInstance(packet)) {
|
||||
if (nms.minorVersion >= 17) {
|
||||
onEntityDestroy(receiver, nms.PacketPlayOutEntityDestroy_ENTITIES.getInt(packet));
|
||||
} else {
|
||||
for (int entity : (int[]) nms.PacketPlayOutEntityDestroy_ENTITIES.get(packet)) {
|
||||
onEntityDestroy(receiver, entity);
|
||||
}
|
||||
onEntityDestroy(receiver, (int[]) nms.PacketPlayOutEntityDestroy_ENTITIES.get(packet));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -113,10 +108,12 @@ public class PacketListener implements RawPacketListener {
|
||||
}
|
||||
}
|
||||
|
||||
public void onEntityDestroy(TabPlayer receiver, int entity) {
|
||||
TabPlayer despawnedPlayer = nameTagX.entityIdMap.get(entity);
|
||||
if (despawnedPlayer != null && despawnedPlayer.isLoaded())
|
||||
tab.getCPUManager().runMeasuredTask("processing EntityDestroy", getFeatureType(), UsageType.PACKET_ENTITY_DESTROY, () -> despawnedPlayer.getArmorStandManager().destroy(receiver));
|
||||
public void onEntityDestroy(TabPlayer receiver, int... entities) {
|
||||
for (int entity : entities) {
|
||||
TabPlayer despawnedPlayer = nameTagX.entityIdMap.get(entity);
|
||||
if (despawnedPlayer != null && despawnedPlayer.isLoaded())
|
||||
tab.getCPUManager().runMeasuredTask("processing EntityDestroy", getFeatureType(), UsageType.PACKET_ENTITY_DESTROY, () -> despawnedPlayer.getArmorStandManager().destroy(receiver));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -157,10 +157,10 @@ public class NMSStorage {
|
||||
public Constructor<?> newPlayerInfoData;
|
||||
public Field PacketPlayOutPlayerInfo_ACTION;
|
||||
public Field PacketPlayOutPlayerInfo_PLAYERS;
|
||||
public Method PlayerInfoData_getProfile;
|
||||
public Method PlayerInfoData_getLatency;
|
||||
public Method PlayerInfoData_getGamemode;
|
||||
public Method PlayerInfoData_getDisplayName;
|
||||
public Method PlayerInfoData_getProfile;
|
||||
public Method PlayerInfoData_getLatency;
|
||||
public Method PlayerInfoData_getGamemode;
|
||||
public Method PlayerInfoData_getDisplayName;
|
||||
|
||||
public Class<?> PacketPlayOutEntityDestroy;
|
||||
public Constructor<?> newPacketPlayOutEntityDestroy;
|
||||
@@ -345,7 +345,6 @@ public class NMSStorage {
|
||||
newChatHoverable = ChatHoverable.getConstructors()[0];
|
||||
}
|
||||
if (minorVersion >= 8) {
|
||||
newPacketPlayOutPlayerListHeaderFooter = PacketPlayOutPlayerListHeaderFooter.getConstructors()[0];
|
||||
newPacketPlayOutPlayerInfo = PacketPlayOutPlayerInfo.getConstructor(EnumPlayerInfoAction, Array.newInstance(EntityPlayer, 0).getClass());
|
||||
newPlayerInfoData = PlayerInfoData.getConstructors()[0];
|
||||
}
|
||||
@@ -377,7 +376,10 @@ public class NMSStorage {
|
||||
newPacketPlayOutChat = PacketPlayOutChat.getConstructor(IChatBaseComponent);
|
||||
}
|
||||
}
|
||||
if (minorVersion < 17) {
|
||||
if (minorVersion >= 17) {
|
||||
newPacketPlayOutPlayerListHeaderFooter = PacketPlayOutPlayerListHeaderFooter.getConstructor(IChatBaseComponent, IChatBaseComponent);
|
||||
} else {
|
||||
newPacketPlayOutPlayerListHeaderFooter = PacketPlayOutPlayerListHeaderFooter.getConstructor();
|
||||
newPacketPlayOutScoreboardTeam = PacketPlayOutScoreboardTeam.getConstructor(ScoreboardTeam, int.class);
|
||||
}
|
||||
}
|
||||
@@ -387,6 +389,7 @@ public class NMSStorage {
|
||||
* @throws Exception - if something fails
|
||||
*/
|
||||
private void initializeFields() throws Exception {
|
||||
PING = getField(EntityPlayer, "ping", "latency", "e");
|
||||
PLAYER_CONNECTION = getFields(EntityPlayer, PlayerConnection).get(0);
|
||||
|
||||
PacketPlayOutScoreboardDisplayObjective_POSITION = getFields(PacketPlayOutScoreboardDisplayObjective, int.class).get(0);
|
||||
@@ -488,16 +491,6 @@ public class NMSStorage {
|
||||
ChatHoverable_value = getFields(ChatHoverable, IChatBaseComponent).get(0);
|
||||
ChatModifier_color = getFields(ChatModifier, EnumChatFormat).get(0);
|
||||
}
|
||||
if (minorVersion >= 17) {
|
||||
try {
|
||||
PING = getField(EntityPlayer, "e");
|
||||
} catch (NoSuchFieldException e) {
|
||||
//deobfuscated spigot jat
|
||||
PING = getField(EntityPlayer, "latency");
|
||||
}
|
||||
} else {
|
||||
PING = getField(EntityPlayer, "ping");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -661,4 +654,13 @@ public class NMSStorage {
|
||||
}
|
||||
throw new NoSuchMethodException("No constructor found in class " + clazz.getName() + " with " + parameterCount + " parameters");
|
||||
}
|
||||
|
||||
private Field getField(Class<?> clazz, String... potentialNames) throws NoSuchFieldException {
|
||||
for (String name : potentialNames) {
|
||||
try {
|
||||
return getField(clazz, name);
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
throw new NoSuchFieldException("No field found in class " + clazz.getName() + " with potential names " + Arrays.toString(potentialNames));
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -77,8 +77,8 @@ public class DataWatcherHelper {
|
||||
} else if (NMSStorage.getInstance().minorVersion >= 8){
|
||||
data.setValue(new DataWatcherObject(2, registry.String), customName);
|
||||
} else {
|
||||
//name length is limited to 64 characters on <1.8
|
||||
String cutName = (customName.length() > 64 ? customName.substring(0, 64) : customName);
|
||||
data.setValue(new DataWatcherObject(10, registry.String), cutName);
|
||||
if (NMSStorage.getInstance().minorVersion >= 6){
|
||||
data.setValue(new DataWatcherObject(10, registry.String), cutName);
|
||||
} else {
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>me.neznamy</groupId>
|
||||
<artifactId>TAB</artifactId>
|
||||
<version>2.9.0</version>
|
||||
<version>2.9.2-pre1</version>
|
||||
</parent>
|
||||
<artifactId>bungeecord</artifactId>
|
||||
|
||||
|
||||
+26
-31
@@ -1,7 +1,11 @@
|
||||
package me.neznamy.tab.platforms.bungeecord;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
@@ -15,6 +19,7 @@ import me.neznamy.tab.shared.cpu.TabFeature;
|
||||
import me.neznamy.tab.shared.cpu.UsageType;
|
||||
import me.neznamy.tab.shared.features.PipelineInjector;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.protocol.DefinedPacket;
|
||||
import net.md_5.bungee.protocol.packet.Login;
|
||||
import net.md_5.bungee.protocol.packet.PlayerListItem;
|
||||
import net.md_5.bungee.protocol.packet.ScoreboardDisplay;
|
||||
@@ -25,6 +30,9 @@ public class BungeePipelineInjector extends PipelineInjector {
|
||||
|
||||
//handler to inject before
|
||||
private final String INJECT_POSITION = "inbound-boss";
|
||||
|
||||
//packets that must be deserialized and bungeecord does not do it automatically
|
||||
private Map<Class<? extends DefinedPacket>, Supplier<DefinedPacket>> extraPackets = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameter
|
||||
@@ -32,6 +40,9 @@ public class BungeePipelineInjector extends PipelineInjector {
|
||||
*/
|
||||
public BungeePipelineInjector(TAB tab) {
|
||||
super(tab);
|
||||
extraPackets.put(Team.class, Team::new);
|
||||
extraPackets.put(ScoreboardDisplay.class, ScoreboardDisplay::new);
|
||||
extraPackets.put(ScoreboardObjective.class, ScoreboardObjective::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -61,7 +72,7 @@ public class BungeePipelineInjector extends PipelineInjector {
|
||||
Collection<String> col = Lists.newArrayList(packet.getPlayers());
|
||||
for (TabPlayer p : tab.getPlayers()) {
|
||||
if (col.contains(p.getName()) && !tab.getFeatureManager().getNameTagFeature().isDisabledWorld(p.getWorldName()) &&
|
||||
!p.hasTeamHandlingPaused() && !p.getTeamName().equals(packet.getName())) {
|
||||
!p.hasTeamHandlingPaused() && !packet.getName().equals(p.getTeamName())) {
|
||||
logTeamOverride(packet.getName(), p.getName());
|
||||
col.remove(p.getName());
|
||||
}
|
||||
@@ -88,25 +99,20 @@ public class BungeePipelineInjector extends PipelineInjector {
|
||||
|
||||
@Override
|
||||
public void write(ChannelHandlerContext context, Object packet, ChannelPromise channelPromise) throws Exception {
|
||||
long time = System.nanoTime();
|
||||
Object modifiedPacket = packet instanceof ByteBuf ? deserialize((ByteBuf) packet) : packet;
|
||||
tab.getCPUManager().addTime(TabFeature.PACKET_DESERIALIZING, UsageType.PACKET_READING_OUT, System.nanoTime()-time);
|
||||
try {
|
||||
if (packet instanceof PlayerListItem) {
|
||||
super.write(context, tab.getFeatureManager().onPacketPlayOutPlayerInfo(player, packet), channelPromise);
|
||||
if (modifiedPacket instanceof PlayerListItem) {
|
||||
super.write(context, tab.getFeatureManager().onPacketPlayOutPlayerInfo(player, modifiedPacket), channelPromise);
|
||||
return;
|
||||
}
|
||||
Object modifiedPacket = packet;
|
||||
long time = System.nanoTime();
|
||||
if (packet instanceof ByteBuf) {
|
||||
modifiedPacket = deserialize((ByteBuf) packet);
|
||||
}
|
||||
tab.getCPUManager().addTime(TabFeature.PACKET_DESERIALIZING, UsageType.PACKET_READING_OUT, System.nanoTime()-time);
|
||||
if (tab.getFeatureManager().isFeatureEnabled("nametag16") && antiOverrideTeams) {
|
||||
time = System.nanoTime();
|
||||
if (modifiedPacket instanceof Team) {
|
||||
modifyPlayers((Team) modifiedPacket);
|
||||
tab.getCPUManager().addTime(TabFeature.NAMETAGS, UsageType.ANTI_OVERRIDE, System.nanoTime()-time);
|
||||
super.write(context, modifiedPacket, channelPromise);
|
||||
return;
|
||||
}
|
||||
tab.getCPUManager().addTime(TabFeature.NAMETAGS, UsageType.ANTI_OVERRIDE, System.nanoTime()-time);
|
||||
//for now protocolsupport will break the plugin
|
||||
/* if (modifiedPacket instanceof ByteBuf) {
|
||||
ByteBuf buf = ((ByteBuf) modifiedPacket);
|
||||
@@ -120,7 +126,6 @@ public class BungeePipelineInjector extends PipelineInjector {
|
||||
}
|
||||
buf.readerIndex(marker);
|
||||
}*/
|
||||
tab.getCPUManager().addTime(TabFeature.NAMETAGS, UsageType.ANTI_OVERRIDE, System.nanoTime()-time);
|
||||
}
|
||||
if (modifiedPacket instanceof ScoreboardDisplay && antiOverrideObjectives && tab.getFeatureManager().onDisplayObjective(player, modifiedPacket)) {
|
||||
return;
|
||||
@@ -138,7 +143,7 @@ public class BungeePipelineInjector extends PipelineInjector {
|
||||
} catch (Throwable e){
|
||||
tab.getErrorManager().printError("An error occurred when analyzing packets for player " + player.getName() + " with client version " + player.getVersion().getFriendlyName(), e);
|
||||
}
|
||||
super.write(context, packet, channelPromise);
|
||||
super.write(context, modifiedPacket, channelPromise);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,23 +155,13 @@ public class BungeePipelineInjector extends PipelineInjector {
|
||||
private Object deserialize(ByteBuf buf) {
|
||||
int marker = buf.readerIndex();
|
||||
int packetId = buf.readByte();
|
||||
if (packetId == ((BungeeTabPlayer)player).getPacketId(Team.class)) {
|
||||
Team team = new Team();
|
||||
team.read(buf, null, ((ProxiedPlayer)player.getPlayer()).getPendingConnection().getVersion());
|
||||
buf.release();
|
||||
return team;
|
||||
}
|
||||
if (packetId == ((BungeeTabPlayer)player).getPacketId(ScoreboardDisplay.class)) {
|
||||
ScoreboardDisplay display = new ScoreboardDisplay();
|
||||
display.read(buf, null, ((ProxiedPlayer)player.getPlayer()).getPendingConnection().getVersion());
|
||||
buf.release();
|
||||
return display;
|
||||
}
|
||||
if (packetId == ((BungeeTabPlayer)player).getPacketId(ScoreboardObjective.class)) {
|
||||
ScoreboardObjective objective = new ScoreboardObjective();
|
||||
objective.read(buf, null, ((ProxiedPlayer)player.getPlayer()).getPendingConnection().getVersion());
|
||||
buf.release();
|
||||
return objective;
|
||||
for (Entry<Class<? extends DefinedPacket>, Supplier<DefinedPacket>> e : extraPackets.entrySet()) {
|
||||
if (packetId == ((BungeeTabPlayer)player).getPacketId(e.getKey())) {
|
||||
DefinedPacket packet = e.getValue().get();
|
||||
packet.read(buf, null, ((ProxiedPlayer)player.getPlayer()).getPendingConnection().getVersion());
|
||||
buf.release();
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
buf.readerIndex(marker);
|
||||
return buf;
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>me.neznamy</groupId>
|
||||
<artifactId>TAB</artifactId>
|
||||
<version>2.9.0</version>
|
||||
<version>2.9.2-pre1</version>
|
||||
</parent>
|
||||
<artifactId>jar</artifactId>
|
||||
<build>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>me.neznamy</groupId>
|
||||
<artifactId>TAB</artifactId>
|
||||
<version>2.9.0</version>
|
||||
<version>2.9.2-pre1</version>
|
||||
<packaging>pom</packaging>
|
||||
<description>An all-in-one solution that works</description>
|
||||
<modules>
|
||||
|
||||
+2
-2
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>me.neznamy</groupId>
|
||||
<artifactId>TAB</artifactId>
|
||||
<version>2.9.0</version>
|
||||
<version>2.9.2-pre1</version>
|
||||
</parent>
|
||||
<artifactId>shared</artifactId>
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.16.5-R0.1-SNAPSHOT</version>
|
||||
<version>1.17-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
|
||||
@@ -73,6 +73,7 @@ public class TABAPI {
|
||||
* @see registerServerConstant
|
||||
*/
|
||||
public static void registerPlayerPlaceholder(PlayerPlaceholder placeholder) {
|
||||
if (placeholder == null) throw new IllegalArgumentException("placeholder cannot be null");
|
||||
APIPlaceholders.put(placeholder.getIdentifier(), placeholder);
|
||||
PlaceholderManager pl = TAB.getInstance().getPlaceholderManager();
|
||||
pl.registerPlaceholder(placeholder);
|
||||
@@ -87,6 +88,7 @@ public class TABAPI {
|
||||
* @see registerServerConstant
|
||||
*/
|
||||
public static void registerServerPlaceholder(ServerPlaceholder placeholder) {
|
||||
if (placeholder == null) throw new IllegalArgumentException("placeholder cannot be null");
|
||||
APIPlaceholders.put(placeholder.getIdentifier(), placeholder);
|
||||
PlaceholderManager pl = TAB.getInstance().getPlaceholderManager();
|
||||
pl.registerPlaceholder(placeholder);
|
||||
@@ -99,6 +101,7 @@ public class TABAPI {
|
||||
* @param placeholder - Placeholder handler
|
||||
*/
|
||||
public static void registerRelationalPlaceholder(RelationalPlaceholder placeholder) {
|
||||
if (placeholder == null) throw new IllegalArgumentException("placeholder cannot be null");
|
||||
APIPlaceholders.put(placeholder.getIdentifier(), placeholder);
|
||||
PlaceholderManager pl = TAB.getInstance().getPlaceholderManager();
|
||||
pl.registerPlaceholder(placeholder);
|
||||
|
||||
@@ -132,7 +132,8 @@ public abstract class ITabPlayer implements TabPlayer {
|
||||
|
||||
@Override
|
||||
public String getTemporaryValue(EnumProperty type) {
|
||||
return getProperty(type.toString()).getTemporaryValue();
|
||||
Property pr = getProperty(type.toString());
|
||||
return pr == null ? null : pr.getTemporaryValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -331,7 +332,7 @@ public abstract class ITabPlayer implements TabPlayer {
|
||||
@Override
|
||||
public void loadPropertyFromConfig(String property, String ifNotSet) {
|
||||
String playerGroupFromConfig = permissionGroup.replace(".", "@#@");
|
||||
String worldGroup = TAB.getInstance().getConfiguration().getWorldGroupOf(getWorldName());
|
||||
String worldGroup = TAB.getInstance().getConfiguration().getWorldGroupOf(TAB.getInstance().getConfiguration().config.getConfigurationSection("per-" + TAB.getInstance().getPlatform().getSeparatorType() + "-settings").keySet(), getWorldName());
|
||||
String value;
|
||||
if ((value = TAB.getInstance().getConfiguration().config.getString("per-" + TAB.getInstance().getPlatform().getSeparatorType() + "-settings." + worldGroup + ".Users." + getName() + "." + property)) != null) {
|
||||
setProperty(property, value, "Player: " + getName() + ", " + TAB.getInstance().getPlatform().getSeparatorType() + ": " + worldGroup);
|
||||
|
||||
@@ -28,9 +28,9 @@ public class PacketAPI {
|
||||
*/
|
||||
public static synchronized void registerScoreboardTeam(TabPlayer to, String teamName, String prefix, String suffix, boolean enumNameTagVisibility, boolean enumTeamPush, Collection<String> players, EnumChatFormat color, TabFeature feature) {
|
||||
if (to.getVersion().getMinorVersion() >= 8 && TAB.getInstance().getConfiguration().unregisterBeforeRegister && TAB.getInstance().getPlatform().getSeparatorType().equals("world")) {
|
||||
to.sendCustomPacket(new PacketPlayOutScoreboardTeam(teamName).setTeamOptions(69), feature);
|
||||
to.sendCustomPacket(new PacketPlayOutScoreboardTeam(teamName), feature);
|
||||
}
|
||||
to.sendCustomPacket(new PacketPlayOutScoreboardTeam(teamName, prefix, suffix, enumNameTagVisibility?"always":"never", enumTeamPush?"always":"never", players, 69).setColor(color), feature);
|
||||
to.sendCustomPacket(new PacketPlayOutScoreboardTeam(teamName, prefix, suffix, enumNameTagVisibility?"always":"never", enumTeamPush?"always":"never", players, 0).setColor(color), feature);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,7 +25,7 @@ public class TAB {
|
||||
private static TAB instance;
|
||||
|
||||
//version of plugin
|
||||
public static final String pluginVersion = "2.9.0";
|
||||
public static final String pluginVersion = "2.9.2-pre1";
|
||||
|
||||
//player data
|
||||
public final Map<UUID, TabPlayer> data = new ConcurrentHashMap<UUID, TabPlayer>();
|
||||
|
||||
@@ -65,6 +65,7 @@ public class DebugCommand extends SubCommand {
|
||||
sendMessage(sender, "&ePlayer: &a" + analyzed.getName());
|
||||
sendMessage(sender, getGroup(analyzed));
|
||||
sendMessage(sender, getTeamName(analyzed));
|
||||
sendMessage(sender, getTeamNameNote(analyzed));
|
||||
if (tab.getFeatureManager().isFeatureEnabled("playerlist")) {
|
||||
Playerlist playerlist = (Playerlist) tab.getFeatureManager().getFeature("playerlist");
|
||||
boolean disabledPlayerlist = playerlist.isDisabledWorld(playerlist.disabledWorlds, analyzed.getWorldName());
|
||||
@@ -158,14 +159,26 @@ public class DebugCommand extends SubCommand {
|
||||
if (TAB.getInstance().getFeatureManager().getNameTagFeature().isDisabledWorld(analyzed.getWorldName())) {
|
||||
return "&eTeam name: &cSorting is disabled in player's " + TAB.getInstance().getPlatform().getSeparatorType();
|
||||
} else {
|
||||
String s = "&eTeam name: &a" + analyzed.getTeamName();
|
||||
if (analyzed.getTeamNameNote() != null) s += "\n&eTeam name note: &a" + analyzed.getTeamNameNote();
|
||||
return s;
|
||||
return "&eTeam name: &a" + analyzed.getTeamName();
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns team name note of specified player
|
||||
* @param analyzed - player to get team name note of
|
||||
* @return team name note of specified player
|
||||
*/
|
||||
private String getTeamNameNote(TabPlayer analyzed) {
|
||||
if (TAB.getInstance().getFeatureManager().getNameTagFeature() != null &&
|
||||
!TAB.getInstance().getFeatureManager().getNameTagFeature().isDisabledWorld(analyzed.getWorldName()) &&
|
||||
analyzed.getTeamNameNote() != null)
|
||||
return "&eTeam name note: &a" + analyzed.getTeamNameNote();
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of extra properties if unlimited nametag mode is enabled
|
||||
* @return list of extra properties
|
||||
|
||||
@@ -180,17 +180,20 @@ public class Configs {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns name of world group of specified world in per-server-settings that may consist of multiple
|
||||
* world separated with "-" or something else defined in config
|
||||
* Returns name of world group in specified set that may consist of multiple
|
||||
* worlds separated with "-" or something else defined in config
|
||||
* @param world - name of world to find group of
|
||||
* @return name of world group
|
||||
*/
|
||||
public String getWorldGroupOf(String world) {
|
||||
Map<String, Object> worlds = config.getConfigurationSection("per-" + tab.getPlatform().getSeparatorType() + "-settings");
|
||||
if (worlds.isEmpty()) return world;
|
||||
for (String worldGroup : worlds.keySet()) {
|
||||
for (String localWorld : worldGroup.split(multiWorldSeparator)) {
|
||||
if (localWorld.equalsIgnoreCase(world)) return worldGroup;
|
||||
public String getWorldGroupOf(Set<?> groups, String world) {
|
||||
if (groups.isEmpty()) return world;
|
||||
for (Object worldGroup : groups) {
|
||||
for (String definedWorld : worldGroup.toString().split(multiWorldSeparator)) {
|
||||
if (definedWorld.endsWith("*")) {
|
||||
if (world.toLowerCase().startsWith(definedWorld.substring(0, definedWorld.length()-1).toLowerCase())) return worldGroup.toString();
|
||||
} else {
|
||||
if (world.equalsIgnoreCase(definedWorld)) return worldGroup.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
return world;
|
||||
|
||||
@@ -5,6 +5,7 @@ import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
@@ -28,6 +29,11 @@ public class AlignedSuffix implements QuitEventListener, WorldChangeListener {
|
||||
this.tab = tab;
|
||||
this.playerlist = playerlist;
|
||||
loadWidthsFromFile();
|
||||
Map<Integer, Integer> widthOverrides = tab.getConfiguration().premiumconfig.getConfigurationSection("character-width-overrides");
|
||||
for (Entry<Integer, Integer> entry : widthOverrides.entrySet()) {
|
||||
widths.put((char)(int)entry.getKey(), (byte)(int)entry.getValue());
|
||||
}
|
||||
tab.debug(String.format("Loaded AlignedSuffix feature with parameters widthOverrides=%s", widthOverrides));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -47,7 +53,7 @@ public class AlignedSuffix implements QuitEventListener, WorldChangeListener {
|
||||
tab.getErrorManager().criticalError("Failed to read character widths from file", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public String formatNameAndUpdateLeader(TabPlayer player, TabPlayer viewer) {
|
||||
int playerNameWidth = getTextWidth(IChatBaseComponent.fromColoredText(player.getProperty("tabprefix").getFormat(null) + player.getProperty("customtabname").getFormat(null) + player.getProperty("tabsuffix").getFormat(null)));
|
||||
if (player == maxPlayer && playerNameWidth < maxWidth) {
|
||||
|
||||
@@ -101,7 +101,7 @@ public class HeaderFooter implements Loadable, JoinEventListener, WorldChangeLis
|
||||
}
|
||||
|
||||
private String getValue(TabPlayer p, String property) {
|
||||
String worldGroup = tab.getConfiguration().getWorldGroupOf(p.getWorldName());
|
||||
String worldGroup = tab.getConfiguration().getWorldGroupOf(tab.getConfiguration().config.getConfigurationSection("per-" + tab.getPlatform().getSeparatorType() + "-settings").keySet(), p.getWorldName());
|
||||
String[] priorities = {
|
||||
"per-" + tab.getPlatform().getSeparatorType() + "-settings." + worldGroup + ".Users." + p.getName() + "." + property,
|
||||
"per-" + tab.getPlatform().getSeparatorType() + "-settings." + worldGroup + ".Users." + p.getUniqueId().toString() + "." + property,
|
||||
|
||||
@@ -35,7 +35,7 @@ public class NameTag implements Loadable, Refreshable, LoginPacketListener, Quit
|
||||
private boolean invisibleNametags;
|
||||
protected Set<String> invisiblePlayers = new HashSet<String>();
|
||||
public Sorting sorting;
|
||||
protected Map<TabPlayer, Boolean> collision = new HashMap<TabPlayer, Boolean>();
|
||||
protected Map<String, Boolean> collision = new HashMap<String, Boolean>();
|
||||
|
||||
public NameTag(TAB tab) {
|
||||
this.tab = tab;
|
||||
@@ -58,7 +58,7 @@ public class NameTag implements Loadable, Refreshable, LoginPacketListener, Quit
|
||||
for (TabPlayer all : tab.getPlayers()) {
|
||||
((ITabPlayer) all).setTeamName(sorting.getTeamName(all));
|
||||
updateProperties(all);
|
||||
collision.put(all, true);
|
||||
collision.put(all.getName(), true);
|
||||
if (all.hasInvisibilityPotion()) invisiblePlayers.add(all.getName());
|
||||
if (isDisabledWorld(all.getWorldName())) continue;
|
||||
registerTeam(all);
|
||||
@@ -113,13 +113,13 @@ public class NameTag implements Loadable, Refreshable, LoginPacketListener, Quit
|
||||
if (p.hasTeamHandlingPaused()) return;
|
||||
if (p.getTeamName() == null) return;
|
||||
for (TabPlayer viewer : tab.getPlayers()) {
|
||||
viewer.sendCustomPacket(new PacketPlayOutScoreboardTeam(p.getTeamName()).setTeamOptions(69), TabFeature.NAMETAGS);
|
||||
viewer.sendCustomPacket(new PacketPlayOutScoreboardTeam(p.getTeamName()), TabFeature.NAMETAGS);
|
||||
}
|
||||
}
|
||||
|
||||
public void unregisterTeam(TabPlayer p, TabPlayer viewer) {
|
||||
if (p.hasTeamHandlingPaused()) return;
|
||||
viewer.sendCustomPacket(new PacketPlayOutScoreboardTeam(p.getTeamName()).setTeamOptions(69), TabFeature.NAMETAGS);
|
||||
viewer.sendCustomPacket(new PacketPlayOutScoreboardTeam(p.getTeamName()), TabFeature.NAMETAGS);
|
||||
}
|
||||
|
||||
public void registerTeam(TabPlayer p) {
|
||||
@@ -161,7 +161,7 @@ public class NameTag implements Loadable, Refreshable, LoginPacketListener, Quit
|
||||
String currentPrefix = tagprefix.getFormat(viewer);
|
||||
String currentSuffix = tagsuffix.getFormat(viewer);
|
||||
boolean visible = getTeamVisibility(p, viewer);
|
||||
viewer.sendCustomPacket(new PacketPlayOutScoreboardTeam(p.getTeamName(), currentPrefix, currentSuffix, visible?"always":"never", getCollision(p)?"always":"never", 69), TabFeature.NAMETAGS);
|
||||
viewer.sendCustomPacket(new PacketPlayOutScoreboardTeam(p.getTeamName(), currentPrefix, currentSuffix, visible?"always":"never", getCollision(p)?"always":"never", 0), TabFeature.NAMETAGS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,31 +171,32 @@ public class NameTag implements Loadable, Refreshable, LoginPacketListener, Quit
|
||||
boolean visible = getTeamVisibility(p, viewer);
|
||||
String currentPrefix = tagprefix.getFormat(viewer);
|
||||
String currentSuffix = tagsuffix.getFormat(viewer);
|
||||
viewer.sendCustomPacket(new PacketPlayOutScoreboardTeam(p.getTeamName(), currentPrefix, currentSuffix, visible?"always":"never", getCollision(p)?"always":"never", 69), TabFeature.NAMETAGS);
|
||||
viewer.sendCustomPacket(new PacketPlayOutScoreboardTeam(p.getTeamName(), currentPrefix, currentSuffix, visible?"always":"never", getCollision(p)?"always":"never", 0), TabFeature.NAMETAGS);
|
||||
}
|
||||
|
||||
private void updateCollision(TabPlayer p) {
|
||||
if (TAB.getInstance().getFeatureManager().getNameTagFeature() == null) return;
|
||||
if (TAB.getInstance().getFeatureManager().getNameTagFeature() == null || !p.isOnline()) return;
|
||||
if (p.getCollisionRule() != null) {
|
||||
if (getCollision(p) != p.getCollisionRule()) {
|
||||
collision.put(p, p.getCollisionRule());
|
||||
collision.put(p.getName(), p.getCollisionRule());
|
||||
updateTeamData(p);
|
||||
}
|
||||
} else {
|
||||
boolean collision = !p.isDisguised() && revertedCollision.contains(p.getWorldName()) ? !collisionRule : collisionRule;
|
||||
if (this.collision.get(p) == null || this.getCollision(p) != collision) {
|
||||
this.collision.put(p, collision);
|
||||
if (this.collision.get(p.getName()) == null || this.getCollision(p) != collision) {
|
||||
this.collision.put(p.getName(), collision);
|
||||
updateTeamData(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean getCollision(TabPlayer p) {
|
||||
if (!p.isOnline()) return false;
|
||||
if (p.getCollisionRule() != null) return p.getCollisionRule();
|
||||
if (!collision.containsKey(p)) {
|
||||
collision.put(p, revertedCollision.contains(p.getWorldName()) ? !collisionRule : collisionRule);
|
||||
if (!collision.containsKey(p.getName())) {
|
||||
collision.put(p.getName(), revertedCollision.contains(p.getWorldName()) ? !collisionRule : collisionRule);
|
||||
}
|
||||
return collision.get(p);
|
||||
return collision.get(p.getName());
|
||||
}
|
||||
|
||||
|
||||
@@ -227,7 +228,7 @@ public class NameTag implements Loadable, Refreshable, LoginPacketListener, Quit
|
||||
public void onJoin(TabPlayer connectedPlayer) {
|
||||
((ITabPlayer) connectedPlayer).setTeamName(sorting.getTeamName(connectedPlayer));
|
||||
updateProperties(connectedPlayer);
|
||||
collision.put(connectedPlayer, true);
|
||||
collision.put(connectedPlayer.getName(), true);
|
||||
for (TabPlayer all : tab.getPlayers()) {
|
||||
if (!all.isLoaded()) continue; //avoiding NPE when 2 players join at once
|
||||
if (all == connectedPlayer) continue; //already registered 3 lines above
|
||||
@@ -241,7 +242,7 @@ public class NameTag implements Loadable, Refreshable, LoginPacketListener, Quit
|
||||
public void onQuit(TabPlayer disconnectedPlayer) {
|
||||
if (!isDisabledWorld(disconnectedPlayer.getWorldName())) unregisterTeam(disconnectedPlayer);
|
||||
invisiblePlayers.remove(disconnectedPlayer.getName());
|
||||
collision.remove(disconnectedPlayer);
|
||||
collision.remove(disconnectedPlayer.getName());
|
||||
for (TabPlayer all : tab.getPlayers()) {
|
||||
if (all == disconnectedPlayer) continue;
|
||||
all.showNametag(disconnectedPlayer.getUniqueId()); //clearing memory from API method
|
||||
|
||||
@@ -251,10 +251,10 @@ public class PlaceholderManager implements JoinEventListener, QuitEventListener,
|
||||
public void registerPlaceholders() {
|
||||
for (PlaceholderRegistry r : registry) {
|
||||
for (Placeholder p : r.registerPlaceholders()) {
|
||||
registeredPlaceholders.put(p.getIdentifier(), p);
|
||||
registerPlaceholder(p);
|
||||
}
|
||||
}
|
||||
registeredPlaceholders.putAll(TABAPI.getAPIPlaceholders());
|
||||
TABAPI.getAPIPlaceholders().values().forEach(p -> registerPlaceholder(p));
|
||||
for (String placeholder : allUsedPlaceholderIdentifiers) {
|
||||
categorizeUsedPlaceholder(placeholder);
|
||||
}
|
||||
@@ -333,6 +333,7 @@ public class PlaceholderManager implements JoinEventListener, QuitEventListener,
|
||||
}
|
||||
|
||||
public void registerPlaceholder(Placeholder placeholder) {
|
||||
if (placeholder == null) throw new IllegalArgumentException("placeholder cannot be null");
|
||||
registeredPlaceholders.put(placeholder.getIdentifier(), placeholder);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import me.neznamy.tab.shared.TAB;
|
||||
public class UpdateChecker {
|
||||
|
||||
//separate field to prevent false flag on pre releases
|
||||
private final String currentRelease = "2.9.0";
|
||||
private final String currentRelease = "2.9.1";
|
||||
|
||||
public UpdateChecker(TAB tab) {
|
||||
new Thread(new Runnable() {
|
||||
|
||||
@@ -121,7 +121,7 @@ public class BossBar implements Loadable, JoinEventListener, WorldChangeListener
|
||||
}
|
||||
}
|
||||
showBossBars(p, defaultBars);
|
||||
showBossBars(p, perWorld.get(p.getWorldName()));
|
||||
showBossBars(p, perWorld.get(tab.getConfiguration().getWorldGroupOf(perWorld.keySet(), p.getWorldName())));
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -168,7 +168,7 @@ public class BossBar implements Loadable, JoinEventListener, WorldChangeListener
|
||||
if (isDisabledWorld(disabledWorlds, p.getWorldName()) || !p.hasBossbarVisible()) return;
|
||||
showBossBars(p, defaultBars);
|
||||
showBossBars(p, announcements);
|
||||
showBossBars(p, perWorld.get(p.getWorldName()));
|
||||
showBossBars(p, perWorld.get(tab.getConfiguration().getWorldGroupOf(perWorld.keySet(), p.getWorldName())));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -249,7 +249,7 @@ public class ScoreboardManager implements Loadable, JoinEventListener, QuitEvent
|
||||
* @return highest scoreboard player should see
|
||||
*/
|
||||
public String detectHighestScoreboard(TabPlayer p) {
|
||||
String scoreboard = perWorld.get(p.getWorldName());
|
||||
String scoreboard = perWorld.get(tab.getConfiguration().getWorldGroupOf(perWorld.keySet(), p.getWorldName()));
|
||||
if (scoreboard == null) {
|
||||
if (defaultScoreboard.equalsIgnoreCase("NONE")) {
|
||||
return "null";
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ public class CustomLine extends ScoreboardLine {
|
||||
} else {
|
||||
//only prefix/suffix changed
|
||||
refreshed.sendCustomPacket(new PacketPlayOutScoreboardTeam(teamName, refreshed.getProperty(teamName + "-prefix").get(),
|
||||
refreshed.getProperty(teamName + "-suffix").get(), "always", "always", 69), TabFeature.SCOREBOARD);
|
||||
refreshed.getProperty(teamName + "-suffix").get(), "always", "always", 0), TabFeature.SCOREBOARD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -123,6 +123,6 @@ public abstract class ScoreboardLine implements Refreshable {
|
||||
*/
|
||||
protected void removeLine(TabPlayer p, String fakeplayer, String teamName) {
|
||||
p.sendCustomPacket(new PacketPlayOutScoreboardScore(Action.REMOVE, ScoreboardManager.ObjectiveName, fakeplayer, 0), TabFeature.SCOREBOARD);
|
||||
p.sendCustomPacket(new PacketPlayOutScoreboardTeam(teamName).setTeamOptions(69), TabFeature.SCOREBOARD);
|
||||
p.sendCustomPacket(new PacketPlayOutScoreboardTeam(teamName), TabFeature.SCOREBOARD);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -44,7 +44,7 @@ public abstract class StableDynamicLine extends ScoreboardLine {
|
||||
if (!parent.players.contains(refreshed)) return; //player has different scoreboard displayed
|
||||
List<String> prefixsuffix = replaceText(refreshed, force, false);
|
||||
if (prefixsuffix == null) return;
|
||||
refreshed.sendCustomPacket(new PacketPlayOutScoreboardTeam(teamName, prefixsuffix.get(0), prefixsuffix.get(1), "always", "always", 69), TabFeature.SCOREBOARD);
|
||||
refreshed.sendCustomPacket(new PacketPlayOutScoreboardTeam(teamName, prefixsuffix.get(0), prefixsuffix.get(1), "always", "always", 0), TabFeature.SCOREBOARD);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -21,16 +21,20 @@ public interface Feature {
|
||||
*/
|
||||
public default boolean isDisabledWorld(List<String> disabledWorlds, String world) {
|
||||
if (disabledWorlds == null) return false;
|
||||
if (disabledWorlds.contains("WHITELIST")) {
|
||||
for (String enabled : disabledWorlds) {
|
||||
if (enabled != null && enabled.equalsIgnoreCase(world)) return false;
|
||||
boolean contains = contains(disabledWorlds, world);
|
||||
if (disabledWorlds.contains("WHITELIST")) contains = !contains;
|
||||
return contains;
|
||||
}
|
||||
|
||||
default boolean contains(List<String> list, String element) {
|
||||
if (element == null) return false;
|
||||
for (String s : list) {
|
||||
if (s.endsWith("*")) {
|
||||
if (element.toLowerCase().startsWith(s.substring(0, s.length()-1).toLowerCase())) return true;
|
||||
} else {
|
||||
if (element.equalsIgnoreCase(s)) return true;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
for (String disabled : disabledWorlds) {
|
||||
if (disabled != null && disabled.equalsIgnoreCase(world)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -109,16 +109,6 @@ public class PacketPlayOutScoreboardTeam extends UniversalPacketPlayOut {
|
||||
this.players = players;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets team options to given value
|
||||
* @param options - options to set to
|
||||
* @return self
|
||||
*/
|
||||
public PacketPlayOutScoreboardTeam setTeamOptions(int options) {
|
||||
this.options = options;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets team color to given value
|
||||
* @param color - color to use
|
||||
|
||||
@@ -21,7 +21,7 @@ public abstract class Placeholder {
|
||||
protected String identifier;
|
||||
|
||||
//premium replacements
|
||||
private Map<Object, String> replacements = new HashMap<Object, String>();
|
||||
protected Map<Object, String> replacements = new HashMap<Object, String>();
|
||||
|
||||
//placeholders used in outputs of replacements
|
||||
private List<String> outputPlaceholders = new ArrayList<String>();
|
||||
@@ -144,7 +144,7 @@ public abstract class Placeholder {
|
||||
* @param p - player to replace for
|
||||
* @return text with replaced placeholders in output
|
||||
*/
|
||||
private String setPlaceholders(String text, TabPlayer p) {
|
||||
protected String setPlaceholders(String text, TabPlayer p) {
|
||||
String replaced = text;
|
||||
for (String s : outputPlaceholders) {
|
||||
if (s.equals("%value%")) continue;
|
||||
|
||||
@@ -4,6 +4,7 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
|
||||
/**
|
||||
* A relational placeholder (output different for every pair of players)
|
||||
@@ -47,7 +48,12 @@ public abstract class RelationalPlaceholder extends Placeholder {
|
||||
*/
|
||||
public String getLastValue(TabPlayer viewer, TabPlayer target) {
|
||||
if (!lastValue.containsKey(viewer.getName() + "-" + target.getName())) update(viewer, target);
|
||||
return lastValue.get(viewer.getName() + "-" + target.getName());
|
||||
String value = lastValue.get(viewer.getName() + "-" + target.getName());
|
||||
String newValue = setPlaceholders(findReplacement(replacements, TAB.getInstance().getPlaceholderManager().color(value)), target);
|
||||
if (newValue.contains("%value%")) {
|
||||
newValue = newValue.replace("%value%", value);
|
||||
}
|
||||
return newValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -93,6 +93,7 @@ placeholder-output-replacements:
|
||||
"20": "&aPerfect"
|
||||
|
||||
align-tabsuffix-on-the-right: false
|
||||
character-width-overrides: {}
|
||||
|
||||
conditions:
|
||||
health:
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>me.neznamy</groupId>
|
||||
<artifactId>TAB</artifactId>
|
||||
<version>2.9.0</version>
|
||||
<version>2.9.2-pre1</version>
|
||||
</parent>
|
||||
<artifactId>velocity-1.1.0</artifactId>
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ import org.bstats.charts.SimplePie;
|
||||
import org.bstats.velocity.Metrics;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.velocitypowered.api.command.Command;
|
||||
import com.velocitypowered.api.command.CommandSource;
|
||||
import com.velocitypowered.api.command.SimpleCommand;
|
||||
import com.velocitypowered.api.event.Subscribe;
|
||||
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
|
||||
import com.velocitypowered.api.event.proxy.ProxyShutdownEvent;
|
||||
@@ -62,8 +62,9 @@ public class Main {
|
||||
ProtocolVersion.SERVER_VERSION = ProtocolVersion.values()[1];
|
||||
TAB.setInstance(new TAB(new VelocityPlatform(server), new VelocityPacketBuilder()));
|
||||
server.getEventManager().register(this, new VelocityEventListener());
|
||||
server.getCommandManager().register(server.getCommandManager().metaBuilder("btab").build(), new VelocityTABCommand());
|
||||
server.getCommandManager().register(server.getCommandManager().metaBuilder("vtab").build(), new VelocityTABCommand());
|
||||
VelocityTABCommand cmd = new VelocityTABCommand();
|
||||
server.getCommandManager().register(server.getCommandManager().metaBuilder("btab").build(), cmd);
|
||||
server.getCommandManager().register(server.getCommandManager().metaBuilder("vtab").build(), cmd);
|
||||
plm = new VelocityPluginMessageHandler(this);
|
||||
TAB.getInstance().load();
|
||||
Metrics metrics = metricsFactory.make(this, 10533);
|
||||
@@ -99,12 +100,13 @@ public class Main {
|
||||
return GsonComponentSerializer.gson().deserialize(string);
|
||||
}
|
||||
|
||||
public static class VelocityTABCommand implements Command {
|
||||
|
||||
public static class VelocityTABCommand implements SimpleCommand {
|
||||
|
||||
@Override
|
||||
public void execute(CommandSource sender, String[] args) {
|
||||
public void execute(Invocation invocation) {
|
||||
CommandSource sender = invocation.source();
|
||||
if (TAB.getInstance().isDisabled()) {
|
||||
for (String message : TAB.getInstance().disabledCommand.execute(args, sender.hasPermission("tab.reload"), sender.hasPermission("tab.admin"))) {
|
||||
for (String message : TAB.getInstance().disabledCommand.execute(invocation.arguments(), sender.hasPermission("tab.reload"), sender.hasPermission("tab.admin"))) {
|
||||
sender.sendMessage(Identity.nil(), Component.text(message.replace('&', '\u00a7')));
|
||||
}
|
||||
} else {
|
||||
@@ -113,18 +115,18 @@ public class Main {
|
||||
p = TAB.getInstance().getPlayer(((Player)sender).getUniqueId());
|
||||
if (p == null) return; //player not loaded correctly
|
||||
}
|
||||
TAB.getInstance().command.execute(p, args);
|
||||
TAB.getInstance().command.execute(p, invocation.arguments());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> suggest(CommandSource sender, String[] args) {
|
||||
public List<String> suggest(Invocation invocation) {
|
||||
TabPlayer p = null;
|
||||
if (sender instanceof Player) {
|
||||
p = TAB.getInstance().getPlayer(((Player)sender).getUniqueId());
|
||||
if (invocation.source() instanceof Player) {
|
||||
p = TAB.getInstance().getPlayer(((Player)invocation.source()).getUniqueId());
|
||||
if (p == null) return new ArrayList<String>(); //player not loaded correctly
|
||||
}
|
||||
return TAB.getInstance().command.complete(p, args);
|
||||
return TAB.getInstance().command.complete(p, invocation.arguments());
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -156,7 +156,7 @@ public class VelocityTabPlayer extends ITabPlayer {
|
||||
case ADD_PLAYER:
|
||||
player.getTabList().addEntry(TabListEntry.builder()
|
||||
.tabList(player.getTabList())
|
||||
.displayName(Main.stringToComponent(data.displayName.toString(getVersion())))
|
||||
.displayName(data.displayName == null ? null : Main.stringToComponent(data.displayName.toString(getVersion())))
|
||||
.gameMode(data.gameMode.ordinal()-1)
|
||||
.profile(new GameProfile(data.uniqueId, data.name, (List<Property>) data.skin))
|
||||
.latency(data.latency)
|
||||
@@ -167,7 +167,7 @@ public class VelocityTabPlayer extends ITabPlayer {
|
||||
break;
|
||||
case UPDATE_DISPLAY_NAME:
|
||||
for (TabListEntry entry : player.getTabList().getEntries()) {
|
||||
if (entry.getProfile().getId().equals(data.uniqueId)) entry.setDisplayName(Main.stringToComponent(data.displayName.toString(getVersion())));
|
||||
if (entry.getProfile().getId().equals(data.uniqueId)) entry.setDisplayName(data.displayName == null ? null : Main.stringToComponent(data.displayName.toString(getVersion())));
|
||||
}
|
||||
break;
|
||||
case UPDATE_LATENCY:
|
||||
|
||||
Reference in new issue
Block a user