Compare commits

..
34 Commits
Author SHA1 Message Date
NEZNAMY 341b552d0b 2.9.2-pre1 2021-06-25 08:25:25 +02:00
NEZNAMY 1586bd9768 implement correct interface 2021-06-24 21:55:06 +02:00
NEZNAMY e8dde3a756 reuse the same instance 2021-06-24 21:51:37 +02:00
NEZNAMY bb591bf56d spigot fixed the bug 2021-06-24 20:18:07 +02:00
NEZNAMY 8cf83b276a fix the feature on 1.17 2021-06-23 21:59:24 +02:00
NEZNAMY a1547a7288 cleaner implementation of #322 2021-06-23 21:56:10 +02:00
NEZNAMY 0722403a23 remove duplicated line 2021-06-22 21:27:59 +02:00
NEZNAMY cd4a91d975 return afk if at least 1 plugin says player is afk 2021-06-22 20:42:26 +02:00
NEZNAMY c7870b4e9d fix NPE in API when feature is not enabled 2021-06-21 22:52:59 +02:00
NEZNAMY 239dae5a65 change reference type to player name 2021-06-21 22:43:47 +02:00
NEZNAMY 13c89d18d7 remove unused field since 1.17 support 2021-06-21 21:47:18 +02:00
NEZNAMY c5dc42eafe cleanup 2021-06-21 14:47:56 +02:00
NEZNAMY 59b3faab1e fix team name note message in console 2021-06-21 13:41:15 +02:00
NEZNAMY b88beb5002 added null check to placeholder registration 2021-06-21 12:58:46 +02:00
NEZNAMY 9fea35c25d retry viaversion call if it returned -1 2021-06-21 12:03:33 +02:00
NEZNAMY 372013bcc6 add online status into debug message 2021-06-21 11:07:21 +02:00
NEZNAMY 20ca58b570 fix NPE 2021-06-20 21:49:48 +02:00
NEZNAMY 9c4cca20fb just an attempt 2021-06-19 11:43:40 +02:00
NEZNAMY 6b8536a86e fix possible memory leak? 2021-06-19 11:41:46 +02:00
NEZNAMY 3b41857637 fixed NPE caused by misconfiguration 2021-06-19 09:27:33 +02:00
NEZNAMY fa78ac2157 fix it again? 2021-06-18 13:39:05 +02:00
NEZNAMY 0a0bb9c83c swap order to avoid NPE when player is not loaded 2021-06-18 12:28:19 +02:00
NEZNAMY 36834a039e 2.9.1 2021-06-17 18:43:34 +02:00
NEZNAMY 4960c898bb memory leak? 2021-06-17 18:35:35 +02:00
NEZNAMY af61edbc5c added replacements support to relational placeholders 2021-06-17 15:53:24 +02:00
NEZNAMY 237bfc08a1 forward raw packets instead, no idea why was it not working 2021-06-17 15:52:39 +02:00
NEZNAMY 032e9a089d bump supported versions 2021-06-17 12:50:37 +02:00
NEZNAMY ba83779dde create and use new field getter method 2021-06-16 21:51:51 +02:00
NEZNAMY 267d72f844 spacing 2021-06-16 21:38:24 +02:00
NEZNAMY b533cdb89f send deserialized packets instead of malformed bytebufs 2021-06-16 17:26:05 +02:00
NEZNAMY 3f118ac76b add option to define custom character widths 2021-06-16 16:24:08 +02:00
NEZNAMY 08a8f0097c fix wrong constructor taken on random 1.8.8 forks 2021-06-16 16:23:26 +02:00
NEZNAMY c7a3599e46 update maven repository 2021-06-16 14:22:45 +02:00
NEZNAMY 62f80baa69 version bump 2021-06-16 14:01:31 +02:00
41 changed files with 271 additions and 224 deletions

No files matched your search

+3 -3
View File
@@ -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
View File
@@ -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) {}
});
}
/**
@@ -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();
}
}
}
@@ -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
*/
@@ -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));
}
}
@@ -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
View File
@@ -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>
@@ -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
View File
@@ -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>
+1 -1
View File
@@ -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
View File
@@ -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())));
}
/**
@@ -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";
@@ -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);
}
}
}
@@ -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);
}
}
@@ -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:
+1 -1
View File
@@ -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());
}
}
}
@@ -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: