Compare commits

...
100 Commits
Author SHA1 Message Date
NEZNAMY 09dc8cd437 version bump 2021-06-16 13:52:27 +02:00
NEZNAMY c613ba401b remove unnecessary this. 2021-06-16 13:03:52 +02:00
NEZNAMY 866df0b5cf remove duplicate content 2021-06-16 11:12:43 +02:00
NEZNAMY 8f2b56ba05 2.9.0 2021-06-16 10:09:20 +02:00
NEZNAMY 2049885f11 more accurate error message 2021-06-16 09:56:15 +02:00
NEZNAMY 4caef337d5 ANOTHER BOSSBAR API BUG IN ANOTHER PLATFORM HAHA LOL 2021-06-15 23:37:02 +02:00
NEZNAMY a644792bf6 simplify 2021-06-15 22:50:16 +02:00
NEZNAMY 54c7f8fc6a drop the rest of title packet 2021-06-15 22:49:23 +02:00
NEZNAMY 2e59b87bbe use getters instead of fields 2021-06-15 22:46:42 +02:00
NEZNAMY f89242ad8f add and use magic code Boolean getters 2021-06-15 22:40:02 +02:00
NEZNAMY 845903788c remove unused code 2021-06-15 22:39:32 +02:00
NEZNAMY 53a9047c20 fix conflict between hidden-by-default and remember-toggle-choice 2021-06-15 22:36:55 +02:00
NEZNAMY a2b74bbc30 correctly display used color codes in parse error messages 2021-06-15 22:36:31 +02:00
NEZNAMY 50ef93cc45 fix stack overflow and stretch with relational placeholders 2021-06-15 22:36:00 +02:00
NEZNAMY e2a5da9c14 deserialize other scoreboard packets as well 2021-06-15 22:35:24 +02:00
NEZNAMY bf31116d0d split method 2021-06-15 22:34:42 +02:00
NEZNAMY d79fa8c4f3 drop title packet 2021-06-15 22:34:31 +02:00
NEZNAMY 87e0a7bea3 remove unused fields 2021-06-15 22:33:33 +02:00
NEZNAMY b34cabd55c optimize check 2021-06-15 22:32:50 +02:00
NEZNAMY 704bd36c77 do not try to use rgb on <1.16 servers 2021-06-14 09:35:23 +02:00
NEZNAMY 5c2c4d0f4b improved error message 2021-06-14 08:43:36 +02:00
NEZNAMY 80cca5cb34 fix #329 2021-06-14 08:22:37 +02:00
NEZNAMY dcd603f2f5 null check to prevent errors 2021-06-13 22:10:30 +02:00
NEZNAMY 1bee3b49bf sending bossbar using bukkit api 2021-06-13 20:46:16 +02:00
NEZNAMY 11bcccb8f9 fix reload from previous commit 2021-06-13 20:24:39 +02:00
NEZNAMY 7425493706 initialization cleanup 2021-06-13 19:09:34 +02:00
NEZNAMY dca0cfd424 removed old value from config 2021-06-13 17:09:03 +02:00
NEZNAMY 21314def89 fix #328 2021-06-13 15:57:06 +02:00
NEZNAMY 90e544d279 option to take groups from backend servers 2021-06-13 11:54:03 +02:00
NEZNAMY 89e21558a1 2.8.11-pre19 2021-06-12 23:23:15 +02:00
NEZNAMY b28cc51457 spigot one dot god damn seventeen 2021-06-12 23:19:09 +02:00
NEZNAMY 2d0a203b5f increased initial delay 2021-06-12 14:28:44 +02:00
NEZNAMY 2948666c1d 2.8.11-pre18 2021-06-11 19:14:47 +02:00
NEZNAMY b2a2659546 added little comment 2021-06-11 17:14:03 +02:00
NEZNAMY e2eb7102c9 removed unnecessary 'throws' from methods 2021-06-10 21:22:15 +02:00
NEZNAMY 56301e653b splitting method into multiple 2021-06-10 21:13:40 +02:00
NEZNAMY 1d825e08d2 using correct uuid all the time 2021-06-10 19:38:46 +02:00
NEZNAMY c81a27709c 1.17 bungeecord 2021-06-10 17:22:58 +02:00
NEZNAMY 2b143172f8 spacing 2021-06-10 17:19:55 +02:00
NEZNAMY 84330ec6eb Merge branch 'master' of https://github.com/NEZNAMY/TAB 2021-06-10 17:19:25 +02:00
NEZNAMY 0bd703de7f Merge pull request #325 from Camotoy/viaversion4.0.0
Update to ViaVersion 4.0.0
2021-06-10 17:17:55 +02:00
Camotoy e6a55b7d5c Change packet ID if using 1.17 2021-06-10 11:13:45 -04:00
Camotoy b6ec7631d2 Update to ViaVersion 4.0.0
Tested on 1.17 and the bossbar showed up with no error in console.
2021-06-10 10:53:36 -04:00
NEZNAMY 5abbd00d63 fixed unloading when entering disabled world 2021-06-10 11:22:07 +02:00
NEZNAMY 515c94976e removed internal methods from TabPlayer API interface 2021-06-09 21:06:01 +02:00
NEZNAMY 912adad8f6 player 2021-06-09 20:08:36 +02:00
NEZNAMY 70fdd193a3 Merge branch 'master' of https://github.com/NEZNAMY/TAB 2021-06-09 19:43:08 +02:00
NEZNAMY 9d83e968fc Merge pull request #323 from Score2/bukkit-permission
Support to obtain bukkit permissions from bungee.
2021-06-09 19:42:35 +02:00
83669 04329da133 resolve. 2021-06-10 01:41:32 +08:00
83669 19ccfbb1a6 Merge branch 'master' of https://github.com/NEZNAMY/TAB into bukkit-permission
 Conflicts:
	velocity-1.1.0/src/main/resources/velocityconfig.yml
2021-06-10 01:29:02 +08:00
83669 c53ab09abc Support to obtain bukkit permissions from bungee. 2021-06-10 01:24:23 +08:00
NEZNAMY a4d8daac1d fixed wrong logic causing name formatting to not work 2021-06-09 16:12:33 +02:00
NEZNAMY 99d566d521 wrong action order 2021-06-09 16:05:08 +02:00
NEZNAMY aa37f73161 fixed wrong config option name 2021-06-09 15:54:12 +02:00
NEZNAMY 087518378d pom.xml cleanup 2021-06-09 15:39:57 +02:00
NEZNAMY 913d27929b shortcut and no longer requiring guava 2021-06-09 15:24:04 +02:00
NEZNAMY 530d39bec5 added property name into exception message 2021-06-09 10:47:42 +02:00
NEZNAMY cf70dc3845 fixed priorities (caused <= and >= to not work) 2021-06-08 23:17:31 +02:00
NEZNAMY d1421fee3f new colors 2021-06-08 21:58:18 +02:00
NEZNAMY 3ec490b36e only the the API now 2021-06-08 09:58:46 +02:00
NEZNAMY ee42685179 Added API to disable team handling of a player 2021-06-07 13:31:44 +02:00
NEZNAMY e02d687771 PingSpoof and SpectatorFix now properly load/unload 2021-06-06 14:55:47 +02:00
NEZNAMY dddb592253 update to default config comments 2021-06-05 20:22:20 +02:00
NEZNAMY d0ad88d317 fixed potential security issue when player is not loaded due to an error 2021-06-05 20:20:02 +02:00
NEZNAMY 3d3ce0151f added gamemode getter to TabPlayer 2021-06-05 19:56:37 +02:00
NEZNAMY f017b0e562 %canseeonline% now uses vanish detection from previous commits instead of PV API on bungeecord 2021-06-05 19:47:03 +02:00
NEZNAMY 4ba2bb669b added back 1.5 and 1.6 support 2021-06-05 16:26:32 +02:00
NEZNAMY 9fc2424736 Create FUNDING.yml 2021-06-03 16:55:26 +02:00
NEZNAMY 980c01ea70 this never happened 2021-06-01 13:25:01 +02:00
NEZNAMY 758edcaf5c fixed NPE in API usage 2021-05-30 20:48:49 +02:00
NEZNAMY 950f825e31 added unnecessary softdependency due to md5's troll console message 2021-05-30 20:47:48 +02:00
NEZNAMY 0a985f5c78 using method from component to save color codes due to limits 2021-05-28 11:43:17 +02:00
NEZNAMY 58353f4e6d wrong variable 2021-05-28 11:41:22 +02:00
NEZNAMY c3d2b5c4b0 fixed error in initialization 2021-05-28 11:19:45 +02:00
NEZNAMY c2764b4b8a removed redundant ; 2021-05-28 11:19:31 +02:00
NEZNAMY 9bc8ad0d23 typo 2021-05-28 09:47:02 +02:00
NEZNAMY 488c3540a8 using more reliable check 2021-05-27 19:58:17 +02:00
NEZNAMY 1d03950a64 removed technically useless check 2021-05-27 19:51:21 +02:00
NEZNAMY e24ea7df2e added null check, continuation of previous commit 2021-05-27 18:06:09 +02:00
NEZNAMY fe5e3d6405 better compatibility with forks that use "Unknown" server version
by using a minor version check which is more reliable
2021-05-27 16:20:08 +02:00
NEZNAMY db8584e40b correctly translating colors 2021-05-27 16:18:43 +02:00
NEZNAMY 2e4db38d1a properly compensating for the bug on all horse types 2021-05-25 14:31:44 +02:00
NEZNAMY f82470c1b1 2.8.11-pre17 2021-05-24 22:37:10 +02:00
NEZNAMY 650cc93fc0 fixed placeholders not refreshing when updating properties with API 2021-05-24 22:35:02 +02:00
NEZNAMY e61070307a fixed rare NPE 2021-05-23 23:27:56 +02:00
NEZNAMY 2fa46867e5 moved repeating task to separate method 2021-05-23 18:51:39 +02:00
NEZNAMY 636b2e760a fixed wrong check 2021-05-23 18:46:10 +02:00
NEZNAMY 8cecf46310 NPE fix 2021-05-23 00:38:16 +02:00
NEZNAMY a7bcda7eba fixed NPEs when running commands from console 2021-05-22 20:48:09 +02:00
NEZNAMY a610dd2c70 cleanup 2021-05-22 16:49:30 +02:00
NEZNAMY df98c77a48 java 8 shortcut 2021-05-22 16:48:01 +02:00
NEZNAMY 331dc33c86 removed redundant method 2021-05-22 16:46:56 +02:00
NEZNAMY 8493b37171 recoded feature to fix issues, worked 2021-05-22 16:41:56 +02:00
NEZNAMY 2449c46165 using default locale
https://support-system.xyz/redirect?link=https://cdn.discordapp.com/attachments/690574378454483034/845273706287988807/ticket-844852135032127489.html
2021-05-21 14:16:55 +02:00
NEZNAMY a642c2d344 moved code to new method to avoid duplication 2021-05-20 16:59:48 +02:00
NEZNAMY 88c7b988e7 not displaying the error message anymore 2021-05-19 20:40:07 +02:00
NEZNAMY 36651260c6 added debug messages 2021-05-19 18:10:54 +02:00
NEZNAMY 6c0072dc54 using new method (also supports essentials vanish now) 2021-05-18 21:12:54 +02:00
NEZNAMY e38f5a77c0 added support for bukkit vanish plugins into global playerlist via bridge 2021-05-18 21:11:41 +02:00
NEZNAMY 6443926a79 added a reminder since even I forgot 2021-05-18 19:55:36 +02:00
95 changed files with 1505 additions and 1705 deletions

No files matched your search

+12
View File
@@ -0,0 +1,12 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: ['https://paypal.me/neznamy1'] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
+2 -7
View File
@@ -19,13 +19,8 @@ Premium version
Bukkit bridge https://www.spigotmc.org/resources/83966/
Wiki https://github.com/NEZNAMY/TAB/wiki
Discord invite link: https://discord.gg/EaSvdk6
## Downloads
Official release: https://www.spigotmc.org/resources/57806/
Pre-releases: https://github.com/NEZNAMY/TAB/releases
## Maven Repository
```
<repositories>
+16 -43
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>me.neznamy</groupId>
<artifactId>TAB</artifactId>
<version>2.8.11-pre16</version>
<version>2.9.0</version>
</parent>
<artifactId>bukkit</artifactId>
@@ -35,6 +35,10 @@
<url>https://repo.viaversion.com/</url>
</repository>
<repository>
<id>aikar</id>
<url>https://repo.aikar.co/content/groups/aikar/</url>
</repository>
</repositories>
<dependencies>
@@ -46,18 +50,10 @@
<version>${project.version}</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
<exclusion>
<groupId>com.github.NEZNAMY</groupId>
<artifactId>YamlAssist</artifactId>
</exclusion>
<exclusion>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
</exclusion>
</exclusions>
</dependency>
@@ -65,7 +61,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>
@@ -125,40 +121,17 @@
<!-- ViaVersion -->
<dependency>
<groupId>us.myles</groupId>
<artifactId>viaversion</artifactId>
<version>3.2.0</version>
<groupId>com.viaversion</groupId>
<artifactId>viaversion-api</artifactId>
<version>4.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.mojang</groupId>
<artifactId>authlib</artifactId>
<version>1.11</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>us.myles</groupId>
<artifactId>viaversion-common</artifactId>
</exclusion>
<exclusion>
<groupId>us.myles</groupId>
<artifactId>viaversion-bukkit</artifactId>
</exclusion>
<exclusion>
<groupId>us.myles</groupId>
<artifactId>viaversion-bungee</artifactId>
</exclusion>
<exclusion>
<groupId>us.myles</groupId>
<artifactId>viaversion-fabric</artifactId>
</exclusion>
<exclusion>
<groupId>us.myles</groupId>
<artifactId>viaversion-sponge</artifactId>
</exclusion>
<exclusion>
<groupId>us.myles</groupId>
<artifactId>viaversion-velocity</artifactId>
</exclusion>
<exclusion>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-chat</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>
@@ -16,7 +16,7 @@ import org.bukkit.plugin.ServicePriority;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import me.neznamy.tab.shared.ProtocolVersion;
import me.neznamy.tab.platforms.bukkit.nms.NMSStorage;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.features.Metrics;
@@ -97,7 +97,7 @@ public class BukkitMetrics extends Metrics {
}));
addCustomChart(new SimplePie("server_version", new Callable<String>() {
public String call() {
return "1." + ProtocolVersion.SERVER_VERSION.getMinorVersion() + ".x";
return "1." + NMSStorage.getInstance().minorVersion + ".x";
}
}));
}
@@ -1,6 +1,8 @@
package me.neznamy.tab.platforms.bukkit;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -10,6 +12,11 @@ import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.EntityType;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.PropertyMap;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.gson.JsonParser;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import me.neznamy.tab.platforms.bukkit.nms.NMSStorage;
@@ -18,6 +25,7 @@ import me.neznamy.tab.shared.ProtocolVersion;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.packets.EnumChatFormat;
import me.neznamy.tab.shared.packets.IChatBaseComponent;
import me.neznamy.tab.shared.packets.IChatBaseComponent.ClickAction;
import me.neznamy.tab.shared.packets.PacketBuilder;
import me.neznamy.tab.shared.packets.PacketPlayOutBoss;
import me.neznamy.tab.shared.packets.PacketPlayOutBoss.Action;
@@ -32,18 +40,14 @@ import me.neznamy.tab.shared.packets.PacketPlayOutScoreboardObjective;
import me.neznamy.tab.shared.packets.PacketPlayOutScoreboardObjective.EnumScoreboardHealthDisplay;
import me.neznamy.tab.shared.packets.PacketPlayOutScoreboardScore;
import me.neznamy.tab.shared.packets.PacketPlayOutScoreboardTeam;
import me.neznamy.tab.shared.packets.PacketPlayOutTitle;
import me.neznamy.tab.shared.packets.IChatBaseComponent.ClickAction;
import me.neznamy.tab.shared.rgb.TextColor;
import us.myles.ViaVersion.api.type.Type;
import us.myles.viaversion.libs.gson.JsonParser;
@SuppressWarnings("unchecked")
public class BukkitPacketBuilder implements PacketBuilder {
//nms storage
private NMSStorage nms;
//entity type ids
private Map<EntityType, Integer> entityIds = new HashMap<EntityType, Integer>();
@@ -53,22 +57,22 @@ public class BukkitPacketBuilder implements PacketBuilder {
*/
public BukkitPacketBuilder(NMSStorage nms) {
this.nms = nms;
if (ProtocolVersion.SERVER_VERSION.getMinorVersion() >= 13) {
if (nms.minorVersion >= 13) {
entityIds.put(EntityType.ARMOR_STAND, 1);
entityIds.put(EntityType.WITHER, 83);
} else {
entityIds.put(EntityType.WITHER, 64);
if (ProtocolVersion.SERVER_VERSION.getMinorVersion() >= 8){
if (nms.minorVersion >= 8){
entityIds.put(EntityType.ARMOR_STAND, 30);
}
}
}
@Override
public Object build(PacketPlayOutBoss packet, ProtocolVersion clientVersion) throws Exception {
if (nms.minorVersion >= 9) {
//1.9+ server
return buildBossPacket19(packet, clientVersion);
//1.9+ server, handled using bukkit api
return packet;
}
if (clientVersion.getMinorVersion() >= 9 && Bukkit.getPluginManager().isPluginEnabled("ViaVersion")) {
//1.9+ client on 1.8 server
@@ -80,27 +84,6 @@ public class BukkitPacketBuilder implements PacketBuilder {
return buildBossPacketEntity(packet, clientVersion);
}
/**
* Build 1.9 boss packet
* @param packet - packet to build
* @param clientVersion - client version
* @return 1.9 bossbar packet
* @throws Exception - if something fails
*/
private Object buildBossPacket19(PacketPlayOutBoss packet, ProtocolVersion clientVersion) throws Exception {
Object nmsPacket = nms.newPacketPlayOutBoss.newInstance();
nms.PacketPlayOutBoss_UUID.set(nmsPacket, packet.id);
nms.PacketPlayOutBoss_ACTION.set(nmsPacket, Enum.valueOf(nms.PacketPlayOutBoss_Action, packet.operation.toString()));
nms.PacketPlayOutBoss_PROGRESS.set(nmsPacket, packet.pct);
nms.PacketPlayOutBoss_NAME.set(nmsPacket, packet.name == null ? null : toNMSComponent(IChatBaseComponent.optimizedComponent(packet.name), clientVersion));
nms.PacketPlayOutBoss_COLOR.set(nmsPacket, packet.color == null ? null : Enum.valueOf(nms.BarColor, packet.color.toString()));
nms.PacketPlayOutBoss_STYLE.set(nmsPacket, packet.overlay == null ? null : Enum.valueOf(nms.BarStyle, packet.overlay.toString()));
nms.PacketPlayOutBoss_DARKEN_SKY.set(nmsPacket, packet.darkenScreen);
nms.PacketPlayOutBoss_PLAY_MUSIC.set(nmsPacket, packet.playMusic);
nms.PacketPlayOutBoss_CREATE_FOG.set(nmsPacket, packet.createWorldFog);
return nmsPacket;
}
/**
* Builds 1.9 bossbar packet bytebuf using viaversion
* @param packet - packet to build
@@ -108,11 +91,11 @@ public class BukkitPacketBuilder implements PacketBuilder {
* @return bytebuf with 1.9 bossbar packet content
* @throws Exception - if something fails
*/
private ByteBuf buildBossPacketVia(PacketPlayOutBoss packet, ProtocolVersion clientVersion) throws Exception {
private ByteBuf buildBossPacketVia(PacketPlayOutBoss packet, ProtocolVersion clientVersion) {
if (clientVersion == ProtocolVersion.UNKNOWN) return null; //preventing disconnect if packet ID changes and users do not update
try {
ByteBuf buf = Unpooled.buffer();
Type.VAR_INT.writePrimitive(buf, clientVersion.getMinorVersion() == 15 ? 0x0D : 0x0C);
Type.VAR_INT.writePrimitive(buf, clientVersion.getMinorVersion() == 15 || clientVersion.getMinorVersion() >= 17 ? 0x0D : 0x0C);
Type.UUID.write(buf, packet.id);
Type.VAR_INT.writePrimitive(buf, packet.operation.ordinal());
switch (packet.operation) {
@@ -180,36 +163,41 @@ public class BukkitPacketBuilder implements PacketBuilder {
@Override
public Object build(PacketPlayOutChat packet, ProtocolVersion clientVersion) throws Exception {
Object nmsPacket = nms.newPacketPlayOutChat.newInstance();
nms.PacketPlayOutChat_MESSAGE.set(nmsPacket, stringToComponent(packet.message.toString(clientVersion))); //using old method for chat packets due to broken item/entity deserializer
if (nms.minorVersion >= 12) {
nms.PacketPlayOutChat_POSITION.set(nmsPacket, Enum.valueOf(nms.ChatMessageType, packet.type.toString()));
} else if (nms.minorVersion >= 8) {
nms.PacketPlayOutChat_POSITION.set(nmsPacket, (byte)packet.type.ordinal());
}
Object component = stringToComponent(packet.message.toString(clientVersion));
if (nms.minorVersion >= 16) {
nms.PacketPlayOutChat_SENDER.set(nmsPacket, UUID.randomUUID());
return nms.newPacketPlayOutChat.newInstance(component, ((Object[])nms.ChatMessageType.getMethod("values").invoke(null))[packet.type.ordinal()], UUID.randomUUID());
}
return nmsPacket;
if (nms.minorVersion >= 12) {
return nms.newPacketPlayOutChat.newInstance(component, Enum.valueOf(nms.ChatMessageType, packet.type.toString()));
}
if (nms.minorVersion >= 8) {
return nms.newPacketPlayOutChat.newInstance(component, (byte) packet.type.ordinal());
}
if (nms.minorVersion == 7) {
return nms.newPacketPlayOutChat.newInstance(component);
}
throw new IllegalStateException("Not supported on <1.7");
}
@Override
public Object build(PacketPlayOutPlayerInfo packet, ProtocolVersion clientVersion) throws Exception {
if (nms.minorVersion < 8) return null;
Object nmsPacket = nms.newPacketPlayOutPlayerInfo.newInstance();
nms.PacketPlayOutPlayerInfo_ACTION.set(nmsPacket, Enum.valueOf(nms.EnumPlayerInfoAction, packet.action.toString()));
Object nmsPacket = nms.newPacketPlayOutPlayerInfo.newInstance(((Object[])nms.EnumPlayerInfoAction.getMethod("values").invoke(null))[packet.action.ordinal()], Array.newInstance(nms.EntityPlayer, 0));
List<Object> items = new ArrayList<Object>();
for (PlayerInfoData data : packet.entries) {
Object profile = nms.newGameProfile.newInstance(data.uniqueId, data.name);
if (data.skin != null) nms.PropertyMap_putAll.invoke(nms.GameProfile_PROPERTIES.get(profile), data.skin);
GameProfile profile = new GameProfile(data.uniqueId, data.name);
if (data.skin != null) profile.getProperties().putAll((PropertyMap) data.skin);
List<Object> parameters = new ArrayList<Object>();
if (nms.newPlayerInfoData.getParameterCount() == 5) {
items.add(nms.newPlayerInfoData.newInstance(nms.newPacketPlayOutPlayerInfo.newInstance(), profile, data.latency, data.gameMode == null ? null : Enum.valueOf(nms.EnumGamemode, data.gameMode.toString()),
data.displayName == null ? null : toNMSComponent(data.displayName, clientVersion)));
} else {
//1.8.8 paper
items.add(nms.newPlayerInfoData.newInstance(profile, data.latency, data.gameMode == null ? null : Enum.valueOf(nms.EnumGamemode, data.gameMode.toString()),
data.displayName == null ? null : toNMSComponent(data.displayName, clientVersion)));
parameters.add(nmsPacket);
}
parameters.add(profile);
parameters.add(data.latency);
Object[] values = (Object[]) nms.EnumGamemode.getMethod("values").invoke(null);
parameters.add(data.gameMode == null ? null : values[values.length-EnumGamemode.values().length+data.gameMode.ordinal()]); //not_set was removed in 1.17
parameters.add(data.displayName == null ? null : toNMSComponent(data.displayName, clientVersion));
items.add(nms.newPlayerInfoData.newInstance(parameters.toArray()));
}
nms.PacketPlayOutPlayerInfo_PLAYERS.set(nmsPacket, items);
return nmsPacket;
@@ -217,6 +205,10 @@ public class BukkitPacketBuilder implements PacketBuilder {
@Override
public Object build(PacketPlayOutPlayerListHeaderFooter packet, ProtocolVersion clientVersion) throws Exception {
if (nms.PacketPlayOutPlayerListHeaderFooter == null) return null;
if (nms.minorVersion >= 17) {
return nms.newPacketPlayOutPlayerListHeaderFooter.newInstance(toNMSComponent(packet.header, clientVersion), toNMSComponent(packet.footer, clientVersion));
}
Object nmsPacket = nms.newPacketPlayOutPlayerListHeaderFooter.newInstance();
nms.PacketPlayOutPlayerListHeaderFooter_HEADER.set(nmsPacket, toNMSComponent(packet.header, clientVersion));
nms.PacketPlayOutPlayerListHeaderFooter_FOOTER.set(nmsPacket, toNMSComponent(packet.footer, clientVersion));
@@ -225,31 +217,24 @@ public class BukkitPacketBuilder implements PacketBuilder {
@Override
public Object build(PacketPlayOutScoreboardDisplayObjective packet, ProtocolVersion clientVersion) throws Exception {
Object nmsPacket = nms.newPacketPlayOutScoreboardDisplayObjective.newInstance();
nms.PacketPlayOutScoreboardDisplayObjective_POSITION.set(nmsPacket, packet.slot);
nms.PacketPlayOutScoreboardDisplayObjective_OBJECTIVENAME.set(nmsPacket, packet.objectiveName);
return nmsPacket;
return nms.newPacketPlayOutScoreboardDisplayObjective.newInstance(packet.slot, newScoreboardObjective(packet.objectiveName));
}
@Override
public Object build(PacketPlayOutScoreboardObjective packet, ProtocolVersion clientVersion) throws Exception {
String displayName = packet.displayName;
if (clientVersion.getMinorVersion() < 13) {
displayName = cutTo(displayName, 32);
String displayName = clientVersion.getMinorVersion() < 13 ? cutTo(packet.displayName, 32) : packet.displayName;
if (nms.minorVersion >= 13) {
return nms.newPacketPlayOutScoreboardObjective.newInstance(nms.newScoreboardObjective.newInstance(null, packet.objectiveName, null,
toNMSComponent(IChatBaseComponent.optimizedComponent(displayName), clientVersion),
packet.renderType == null ? null : ((Object[])nms.EnumScoreboardHealthDisplay.getMethod("values").invoke(null))[packet.renderType.ordinal()]),
packet.method);
}
Object nmsPacket = nms.newPacketPlayOutScoreboardObjective.newInstance();
nms.PacketPlayOutScoreboardObjective_OBJECTIVENAME.set(nmsPacket, packet.objectiveName);
if (nms.minorVersion >= 13) {
nms.PacketPlayOutScoreboardObjective_DISPLAYNAME.set(nmsPacket, toNMSComponent(IChatBaseComponent.optimizedComponent(displayName), clientVersion));
} else {
nms.PacketPlayOutScoreboardObjective_DISPLAYNAME.set(nmsPacket, displayName);
}
nms.PacketPlayOutScoreboardObjective_DISPLAYNAME.set(nmsPacket, displayName);
if (nms.PacketPlayOutScoreboardObjective_RENDERTYPE != null && packet.renderType != null) {
if (nms.minorVersion >= 8) {
nms.PacketPlayOutScoreboardObjective_RENDERTYPE.set(nmsPacket, Enum.valueOf(nms.EnumScoreboardHealthDisplay, packet.renderType.toString()));
} else {
nms.PacketPlayOutScoreboardObjective_RENDERTYPE.set(nmsPacket, packet.renderType.ordinal());
}
nms.PacketPlayOutScoreboardObjective_RENDERTYPE.set(nmsPacket, Enum.valueOf(nms.EnumScoreboardHealthDisplay, packet.renderType.toString()));
}
nms.PacketPlayOutScoreboardObjective_METHOD.set(nmsPacket, packet.method);
return nmsPacket;
@@ -258,21 +243,17 @@ public class BukkitPacketBuilder implements PacketBuilder {
@Override
public Object build(PacketPlayOutScoreboardScore packet, ProtocolVersion clientVersion) throws Exception {
if (nms.minorVersion >= 13) {
return nms.newPacketPlayOutScoreboardScore_1_13.newInstance(Enum.valueOf(nms.EnumScoreboardAction, packet.action.toString()), packet.objectiveName, packet.player, packet.score);
return nms.newPacketPlayOutScoreboardScore_1_13.newInstance(((Object[])nms.EnumScoreboardAction.getMethod("values").invoke(null))[packet.action.ordinal()], packet.objectiveName, packet.player, packet.score);
}
if (packet.action == PacketPlayOutScoreboardScore.Action.REMOVE) {
return nms.newPacketPlayOutScoreboardScore_String.newInstance(packet.player);
}
Object nmsPacket = nms.newPacketPlayOutScoreboardScore0.newInstance();
nms.PacketPlayOutScoreboardScore_PLAYER.set(nmsPacket, packet.player);
nms.PacketPlayOutScoreboardScore_OBJECTIVENAME.set(nmsPacket, packet.objectiveName);
nms.PacketPlayOutScoreboardScore_SCORE.set(nmsPacket, packet.score);
Object score = nms.newScoreboardScore.newInstance(nms.newScoreboard.newInstance(), newScoreboardObjective(packet.objectiveName), packet.player);
nms.ScoreboardScore_setScore.invoke(score, packet.score);
if (nms.minorVersion >= 8) {
nms.PacketPlayOutScoreboardScore_ACTION.set(nmsPacket, Enum.valueOf(nms.EnumScoreboardAction, packet.action.toString()));
} else {
nms.PacketPlayOutScoreboardScore_ACTION.set(nmsPacket, packet.action.ordinal());
return nms.newPacketPlayOutScoreboardScore.newInstance(score);
}
return nmsPacket;
return nms.newPacketPlayOutScoreboardScore.newInstance(score, 0);
}
@Override
@@ -283,44 +264,52 @@ public class BukkitPacketBuilder implements PacketBuilder {
prefix = cutTo(prefix, 16);
suffix = cutTo(suffix, 16);
}
Object nmsPacket = nms.newPacketPlayOutScoreboardTeam.newInstance();
nms.PacketPlayOutScoreboardTeam_NAME.set(nmsPacket, packet.name);
Object team = nms.newScoreboardTeam.newInstance(nms.newScoreboard.newInstance(), packet.name);
((Collection<String>)nms.ScoreboardTeam_getPlayerNameSet.invoke(team)).addAll(packet.players);
if (nms.minorVersion >= 13) {
nms.PacketPlayOutScoreboardTeam_DISPLAYNAME.set(nmsPacket, toNMSComponent(IChatBaseComponent.optimizedComponent(packet.name), clientVersion));
if (prefix != null && prefix.length() > 0) nms.PacketPlayOutScoreboardTeam_PREFIX.set(nmsPacket, toNMSComponent(IChatBaseComponent.optimizedComponent(prefix), clientVersion));
if (suffix != null && suffix.length() > 0) nms.PacketPlayOutScoreboardTeam_SUFFIX.set(nmsPacket, toNMSComponent(IChatBaseComponent.optimizedComponent(suffix), clientVersion));
if (prefix != null && prefix.length() > 0) nms.ScoreboardTeam_setPrefix.invoke(team, toNMSComponent(IChatBaseComponent.optimizedComponent(prefix), clientVersion));
if (suffix != null && suffix.length() > 0) nms.ScoreboardTeam_setSuffix.invoke(team, toNMSComponent(IChatBaseComponent.optimizedComponent(suffix), clientVersion));
EnumChatFormat format = packet.color != null ? packet.color : EnumChatFormat.lastColorsOf(prefix);
nms.PacketPlayOutScoreboardTeam_CHATFORMAT.set(nmsPacket, Enum.valueOf(nms.EnumChatFormat, format.toString()));
nms.ScoreboardTeam_setColor.invoke(team, ((Object[])nms.EnumChatFormat.getMethod("values").invoke(null))[format.ordinal()]);
} else {
nms.PacketPlayOutScoreboardTeam_DISPLAYNAME.set(nmsPacket, packet.name);
nms.PacketPlayOutScoreboardTeam_PREFIX.set(nmsPacket, prefix);
nms.PacketPlayOutScoreboardTeam_SUFFIX.set(nmsPacket, suffix);
if (prefix != null) nms.ScoreboardTeam_setPrefix.invoke(team, prefix);
if (suffix != null) nms.ScoreboardTeam_setSuffix.invoke(team, suffix);
}
if (nms.PacketPlayOutScoreboardTeam_VISIBILITY != null) nms.PacketPlayOutScoreboardTeam_VISIBILITY.set(nmsPacket, packet.nametagVisibility);
if (nms.PacketPlayOutScoreboardTeam_COLLISION != null) nms.PacketPlayOutScoreboardTeam_COLLISION.set(nmsPacket, packet.collisionRule);
nms.PacketPlayOutScoreboardTeam_PLAYERS.set(nmsPacket, packet.players);
nms.PacketPlayOutScoreboardTeam_ACTION.set(nmsPacket, packet.method);
nms.PacketPlayOutScoreboardTeam_SIGNATURE.set(nmsPacket, packet.options);
return nmsPacket;
if (nms.EnumNameTagVisibility != null && packet.nametagVisibility != null) nms.ScoreboardTeam_setNameTagVisibility.invoke(team, packet.nametagVisibility.equals("always") ? ((Object[])nms.EnumNameTagVisibility.getMethod("values").invoke(null))[0] : ((Object[])nms.EnumNameTagVisibility.getMethod("values").invoke(null))[1]);
if (nms.EnumTeamPush != null && packet.collisionRule != null) nms.ScoreboardTeam_setCollisionRule.invoke(team, packet.collisionRule.equals("always") ? ((Object[])nms.EnumTeamPush.getMethod("values").invoke(null))[0] : ((Object[])nms.EnumTeamPush.getMethod("values").invoke(null))[1]);
if (nms.minorVersion >= 17) {
switch (packet.method) {
case 0:
return nms.PacketPlayOutScoreboardTeam_ofBoolean.invoke(null, team, true);
case 1:
return nms.PacketPlayOutScoreboardTeam_of.invoke(null, team);
case 2:
return nms.PacketPlayOutScoreboardTeam_ofBoolean.invoke(null, team, false);
case 3:
return nms.PacketPlayOutScoreboardTeam_ofString.invoke(null, team, packet.players.toArray(new String[0])[0], ((Object[])nms.PacketPlayOutScoreboardTeam_a.getMethod("values").invoke(null))[0]);
case 4:
return nms.PacketPlayOutScoreboardTeam_ofString.invoke(null, team, packet.players.toArray(new String[0])[0], ((Object[])nms.PacketPlayOutScoreboardTeam_a.getMethod("values").invoke(null))[1]);
default:
throw new IllegalArgumentException("Invalid action: " + packet.method);
}
}
return nms.newPacketPlayOutScoreboardTeam.newInstance(team, packet.method);
}
@Override
public Object build(PacketPlayOutTitle packet, ProtocolVersion clientVersion) throws Exception {
if (nms.minorVersion < 8) return null;
return nms.newPacketPlayOutTitle.newInstance(Enum.valueOf(nms.EnumTitleAction, packet.action.toString()),
packet.text == null ? null : toNMSComponent(IChatBaseComponent.optimizedComponent(packet.text), clientVersion), packet.fadeIn, packet.stay, packet.fadeOut);
}
/**
* Builds entity destroy packet with given parameter
* @param ids - entity ids to destroy
* @param id - entity id to destroy
* @return destroy packet
* @throws Exception - if reflection fails
*/
public Object buildEntityDestroyPacket(int... ids) throws Exception {
return nms.newPacketPlayOutEntityDestroy.newInstance(ids);
public Object buildEntityDestroyPacket(int id) throws Exception {
if (nms.minorVersion >= 17) {
return nms.newPacketPlayOutEntityDestroy.newInstance(id);
}
return nms.newPacketPlayOutEntityDestroy.newInstance(new int[] {id});
}
/**
* Builds entity metadata packet with given parameters
* @param entityId - entity id
@@ -331,7 +320,7 @@ public class BukkitPacketBuilder implements PacketBuilder {
public Object buildEntityMetadataPacket(int entityId, DataWatcher dataWatcher) throws Exception {
return nms.newPacketPlayOutEntityMetadata.newInstance(entityId, dataWatcher.toNMS(), true);
}
/**
* Builds entity spawn packet with given parameters
* @param entityId - entity id
@@ -343,7 +332,7 @@ public class BukkitPacketBuilder implements PacketBuilder {
* @throws Exception - if reflection fails
*/
public Object buildEntitySpawnPacket(int entityId, UUID uuid, EntityType entityType, Location loc, DataWatcher dataWatcher) throws Exception {
Object nmsPacket = nms.newPacketPlayOutSpawnEntityLiving.newInstance();
Object nmsPacket = nms.newPacketPlayOutSpawnEntityLiving.newInstance(nms.getHandle.invoke(Bukkit.getOnlinePlayers().iterator().next()));
nms.PacketPlayOutSpawnEntityLiving_ENTITYID.set(nmsPacket, entityId);
nms.PacketPlayOutSpawnEntityLiving_ENTITYTYPE.set(nmsPacket, entityIds.get(entityType));
nms.PacketPlayOutSpawnEntityLiving_YAW.set(nmsPacket, (byte)(loc.getYaw() * 256.0f / 360.0f));
@@ -351,7 +340,7 @@ public class BukkitPacketBuilder implements PacketBuilder {
if (nms.PacketPlayOutSpawnEntityLiving_DATAWATCHER != null) {
nms.PacketPlayOutSpawnEntityLiving_DATAWATCHER.set(nmsPacket, dataWatcher.toNMS());
}
if (ProtocolVersion.SERVER_VERSION.getMinorVersion() >= 9) {
if (nms.minorVersion >= 9) {
nms.PacketPlayOutSpawnEntityLiving_UUID.set(nmsPacket, uuid);
nms.PacketPlayOutSpawnEntityLiving_X.set(nmsPacket, loc.getX());
nms.PacketPlayOutSpawnEntityLiving_Y.set(nmsPacket, loc.getY());
@@ -363,7 +352,7 @@ public class BukkitPacketBuilder implements PacketBuilder {
}
return nmsPacket;
}
/**
* Builds entity teleport packet with given parameters
* @param entityId - entity id
@@ -372,9 +361,9 @@ public class BukkitPacketBuilder implements PacketBuilder {
* @throws Exception - if reflection fails
*/
public Object buildEntityTeleportPacket(int entityId, Location location) throws Exception {
Object nmsPacket = nms.newPacketPlayOutEntityTeleport.newInstance();
Object nmsPacket = nms.newPacketPlayOutEntityTeleport.newInstance(nms.getHandle.invoke(Bukkit.getOnlinePlayers().iterator().next()));
nms.PacketPlayOutEntityTeleport_ENTITYID.set(nmsPacket, entityId);
if (ProtocolVersion.SERVER_VERSION.getMinorVersion() >= 9) {
if (nms.minorVersion >= 9) {
nms.PacketPlayOutEntityTeleport_X.set(nmsPacket, location.getX());
nms.PacketPlayOutEntityTeleport_Y.set(nmsPacket, location.getY());
nms.PacketPlayOutEntityTeleport_Z.set(nmsPacket, location.getZ());
@@ -394,12 +383,12 @@ public class BukkitPacketBuilder implements PacketBuilder {
EnumPlayerInfoAction action = EnumPlayerInfoAction.valueOf(nms.PacketPlayOutPlayerInfo_ACTION.get(nmsPacket).toString());
List<PlayerInfoData> listData = new ArrayList<PlayerInfoData>();
for (Object nmsData : (List<?>) nms.PacketPlayOutPlayerInfo_PLAYERS.get(nmsPacket)) {
Object nmsGamemode = nms.PlayerInfoData_GAMEMODE.get(nmsData);
EnumGamemode gamemode = nmsGamemode == null ? null : EnumGamemode.valueOf(nmsGamemode.toString());
Object profile = nms.PlayerInfoData_PROFILE.get(nmsData);
Object nmsComponent = nms.PlayerInfoData_LISTNAME.get(nmsData);
IChatBaseComponent listName = fromNMSComponent(nmsComponent);
listData.add(new PlayerInfoData((String) nms.GameProfile_NAME.get(profile), (UUID) nms.GameProfile_ID.get(profile), nms.GameProfile_PROPERTIES.get(profile), nms.PlayerInfoData_PING.getInt(nmsData), gamemode, listName));
Object nmsGamemode = nms.PlayerInfoData_getGamemode.invoke(nmsData);
EnumGamemode gamemode = (nmsGamemode == null) ? null : EnumGamemode.valueOf(nmsGamemode.toString());
GameProfile profile = (GameProfile) nms.PlayerInfoData_getProfile.invoke(nmsData);
Object nmsComponent = nms.PlayerInfoData_getDisplayName.invoke(nmsData);
IChatBaseComponent listName = nmsComponent == null ? null : fromNMSComponent(nmsComponent);
listData.add(new PlayerInfoData(profile.getName(), profile.getId(), profile.getProperties(), (int)nms.PlayerInfoData_getLatency.invoke(nmsData), gamemode, listName));
}
return new PacketPlayOutPlayerInfo(action, listData);
}
@@ -419,11 +408,7 @@ public class BukkitPacketBuilder implements PacketBuilder {
if (nms.PacketPlayOutScoreboardObjective_RENDERTYPE != null) {
Object nmsRender = nms.PacketPlayOutScoreboardObjective_RENDERTYPE.get(nmsPacket);
if (nmsRender != null) {
if (nms.minorVersion >= 8) {
renderType = EnumScoreboardHealthDisplay.valueOf(nmsRender.toString());
} else {
renderType = EnumScoreboardHealthDisplay.values()[(int)nmsRender];
}
renderType = EnumScoreboardHealthDisplay.valueOf(nmsRender.toString());
}
}
int method = nms.PacketPlayOutScoreboardObjective_METHOD.getInt(nmsPacket);
@@ -437,7 +422,7 @@ public class BukkitPacketBuilder implements PacketBuilder {
(String) nms.PacketPlayOutScoreboardDisplayObjective_OBJECTIVENAME.get(nmsPacket)
);
}
/**
* A method yoinked from minecraft code used to convert double to int
* @param paramDouble double value
@@ -447,7 +432,7 @@ public class BukkitPacketBuilder implements PacketBuilder {
int i = (int)paramDouble;
return paramDouble < i ? i - 1 : i;
}
/**
* Converts json string into a component
* @param json json as string
@@ -458,7 +443,7 @@ public class BukkitPacketBuilder implements PacketBuilder {
if (json == null) return null;
return nms.ChatSerializer_DESERIALIZE.invoke(null, json);
}
/**
* Converts minecraft IChatBaseComponent into TAB's component class. Currently does not support hover event.
* @param component - component to convert
@@ -471,7 +456,7 @@ public class BukkitPacketBuilder implements PacketBuilder {
TAB.getInstance().getCPUManager().addMethodTime("fromNMSComponent", System.nanoTime()-time);
return obj;
}
//separate method to prevent extras counting cpu again due to recursion and finally showing higher usage than real
@SuppressWarnings("rawtypes")
public IChatBaseComponent fromNMSComponent0(Object component) throws Exception {
@@ -503,7 +488,7 @@ public class BukkitPacketBuilder implements PacketBuilder {
if (clickEvent != null) {
chat.onClick(ClickAction.valueOf(nms.ChatClickable_action.get(clickEvent).toString().toUpperCase()), (String) nms.ChatClickable_value.get(clickEvent));
}
/* Object hoverEvent = nms.ChatModifier_hoverEvent.get(modifier);
/* Object hoverEvent = nms.ChatModifier_hoverEvent.get(modifier);
if (hoverEvent != null) {
chat.onHover(HoverAction.fromString(nms.ChatHoverable_action.get(hoverEvent).toString()), fromNMSComponent(nms.ChatHoverable_value.get(hoverEvent)));
}*/
@@ -513,7 +498,7 @@ public class BukkitPacketBuilder implements PacketBuilder {
}
return chat;
}
/**
* Converts TAB's IChatBaseComponent into minecraft's component. Currently does not support hover event.
* @param component - component to convert
@@ -527,7 +512,7 @@ public class BukkitPacketBuilder implements PacketBuilder {
TAB.getInstance().getCPUManager().addMethodTime("toNMSComponent", System.nanoTime()-time);
return obj;
}
//separate method to prevent extras counting cpu again due to recursion and finally showing higher usage than real
private Object toNMSComponent0(IChatBaseComponent component, ProtocolVersion clientVersion) throws Exception {
if (component == null) return null;
@@ -543,16 +528,16 @@ public class BukkitPacketBuilder implements PacketBuilder {
}
}
modifier = nms.newChatModifier.newInstance(
color,
component.isBold() ? true : null,
component.isItalic() ? true : null,
component.isUnderlined() ? true : null,
component.isStrikethrough() ? true : null,
component.isObfuscated() ? true : null,
component.getClickAction() == null ? null : nms.newChatClickable.newInstance(nms.EnumClickAction_a.invoke(null, component.getClickAction().toString().toLowerCase()), component.getClickValue().toString()),
null, //component.getHoverAction() == null ? null : nms.newChatHoverable.newInstance(nms.EnumHoverAction_a.invoke(null, component.getHoverAction().toString().toLowerCase()), stringToComponent(component.getHoverValue().toString())),
null, null
);
color,
component.getBold(),
component.getItalic(),
component.getUnderlined(),
component.getStrikethrough(),
component.getObfuscated(),
component.getClickAction() == null ? null : nms.newChatClickable.newInstance(nms.EnumClickAction_a.invoke(null, component.getClickAction().toString().toLowerCase()), component.getClickValue().toString()),
null, //component.getHoverAction() == null ? null : nms.newChatHoverable.newInstance(nms.EnumHoverAction_a.invoke(null, component.getHoverAction().toString().toLowerCase()), stringToComponent(component.getHoverValue().toString())),
null, null
);
} else {
modifier = nms.newChatModifier.newInstance();
if (component.getClickAction() != null){
@@ -574,4 +559,11 @@ public class BukkitPacketBuilder implements PacketBuilder {
}
return chat;
}
private Object newScoreboardObjective(String objectiveName) throws Exception {
if (nms.minorVersion >= 13) {
return nms.newScoreboardObjective.newInstance(null, objectiveName, null, stringToComponent("{\"text\":\"\"}"), null);
}
return nms.newScoreboardObjective.newInstance(null, objectiveName, nms.getFields(nms.IScoreboardCriteria, nms.IScoreboardCriteria).get(0).get(null));
}
}
@@ -64,24 +64,25 @@ public class BukkitPipelineInjector extends PipelineInjector {
@SuppressWarnings("unchecked")
private void modifyPlayers(Object packetPlayOutScoreboardTeam) throws Exception {
long time = System.nanoTime();
if (nms.PacketPlayOutScoreboardTeam_SIGNATURE.getInt(packetPlayOutScoreboardTeam) != 69) {
Collection<String> players = (Collection<String>) nms.PacketPlayOutScoreboardTeam_PLAYERS.get(packetPlayOutScoreboardTeam);
//creating a new list to prevent NoSuchFieldException in minecraft packet encoder when a player is removed
Collection<String> newList = new ArrayList<String>();
for (String entry : players) {
TabPlayer p = tab.getPlayer(entry);
if (p == null) {
newList.add(entry);
continue;
}
if (tab.getFeatureManager().getNameTagFeature().isDisabledWorld(p.getWorldName())) {
newList.add(entry);
} else {
logTeamOverride((String) nms.PacketPlayOutScoreboardTeam_NAME.get(packetPlayOutScoreboardTeam), entry);
}
Collection<String> players = (Collection<String>) nms.PacketPlayOutScoreboardTeam_PLAYERS.get(packetPlayOutScoreboardTeam);
String teamName = (String) nms.PacketPlayOutScoreboardTeam_NAME.get(packetPlayOutScoreboardTeam);
if (players == null) return;
//creating a new list to prevent NoSuchFieldException in minecraft packet encoder when a player is removed
Collection<String> newList = new ArrayList<String>();
for (String entry : players) {
TabPlayer p = tab.getPlayer(entry);
if (p == null) {
newList.add(entry);
continue;
}
if (!tab.getFeatureManager().getNameTagFeature().isDisabledWorld(p.getWorldName()) && !p.hasTeamHandlingPaused() &&
!p.getTeamName().equals(teamName)) {
logTeamOverride(teamName, entry);
} else {
newList.add(entry);
}
nms.PacketPlayOutScoreboardTeam_PLAYERS.set(packetPlayOutScoreboardTeam, newList);
}
nms.PacketPlayOutScoreboardTeam_PLAYERS.set(packetPlayOutScoreboardTeam, newList);
tab.getCPUManager().addTime(TabFeature.NAMETAGS, UsageType.ANTI_OVERRIDE, System.nanoTime()-time);
}
@@ -17,6 +17,7 @@ import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.java.JavaPlugin;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.platforms.bukkit.nms.NMSStorage;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.features.PlaceholderManager;
import me.neznamy.tab.shared.placeholders.Placeholder;
@@ -93,11 +94,13 @@ public class BukkitPlaceholderRegistry implements PlaceholderRegistry {
return String.valueOf(((Player) p.getPlayer()).getStatistic(Statistic.DEATHS));
}
});
placeholders.add(new PlayerPlaceholder("%health%", 100) {
public String get(TabPlayer p) {
return String.valueOf((int) Math.ceil(((Player) p.getPlayer()).getHealth()));
}
});
if (NMSStorage.getInstance().minorVersion >= 6) {
placeholders.add(new PlayerPlaceholder("%health%", 100) {
public String get(TabPlayer p) {
return String.valueOf((int) Math.ceil(((Player) p.getPlayer()).getHealth()));
}
});
}
placeholders.add(new ServerPlaceholder("%tps%", 1000) {
public String get() {
try {
@@ -257,6 +260,7 @@ public class BukkitPlaceholderRegistry implements PlaceholderRegistry {
if (Bukkit.getPluginManager().isPluginEnabled("Essentials")) {
placeholders.add(new PlayerPlaceholder("%essentialsnick%", 1000) {
public String get(TabPlayer p) {
if (getNickname == null) return "<Internal plugin error>";
String name = null;
try {
name = (String) getNickname.invoke(getUser.invoke(Bukkit.getPluginManager().getPlugin("Essentials"), p.getPlayer()));
@@ -21,10 +21,14 @@ import me.neznamy.tab.platforms.bukkit.features.unlimitedtags.NameTagX;
import me.neznamy.tab.platforms.bukkit.nms.NMSStorage;
import me.neznamy.tab.platforms.bukkit.permission.Vault;
import me.neznamy.tab.shared.Platform;
import me.neznamy.tab.shared.ProtocolVersion;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.features.BelowName;
import me.neznamy.tab.shared.features.NameTag;
import me.neznamy.tab.shared.features.PingSpoof;
import me.neznamy.tab.shared.features.PlaceholderManager;
import me.neznamy.tab.shared.features.SpectatorFix;
import me.neznamy.tab.shared.features.TabObjective;
import me.neznamy.tab.shared.features.scoreboard.ScoreboardManager;
import me.neznamy.tab.shared.permission.LuckPerms;
import me.neznamy.tab.shared.permission.None;
import me.neznamy.tab.shared.permission.PermissionPlugin;
@@ -55,6 +59,7 @@ public class BukkitPlatform implements Platform {
public boolean viaversion;
public boolean idisguise;
public boolean libsdisguises;
public boolean essentials;
/**
* Constructs new instance with given parameters
@@ -85,19 +90,24 @@ public class BukkitPlatform implements Platform {
viaversion = Bukkit.getPluginManager().isPluginEnabled("ViaVersion");
idisguise = Bukkit.getPluginManager().isPluginEnabled("iDisguise");
libsdisguises = Bukkit.getPluginManager().isPluginEnabled("LibsDisguises");
int version = ProtocolVersion.SERVER_VERSION.getMinorVersion();
essentials = Bukkit.getPluginManager().isPluginEnabled("Essentials");
TAB tab = TAB.getInstance();
usedExpansions = new HashSet<String>();
tab.getPlaceholderManager().addRegistry(new BukkitPlaceholderRegistry(plugin));
tab.getPlaceholderManager().addRegistry(new UniversalPlaceholderRegistry());
tab.getPlaceholderManager().registerPlaceholders();
if (version >= 8 && tab.getConfiguration().pipelineInjection) {
if (nms.minorVersion >= 8 && tab.getConfiguration().pipelineInjection) {
tab.getFeatureManager().registerFeature("injection", new BukkitPipelineInjector(tab, nms));
}
loadNametagFeature(tab);
loadUniversalFeatures();
if (tab.getConfiguration().bossbar.getBoolean("bossbar-enabled", false) && version < 9) tab.getFeatureManager().registerFeature("bossbar1.8", new BossBar_legacy(tab, plugin));
if (version >= 9 && tab.getConfiguration().config.getBoolean("fix-pet-names", false)) tab.getFeatureManager().registerFeature("petfix", new PetFix(nms));
if (tab.getConfiguration().config.getBoolean("ping-spoof.enabled", false)) tab.getFeatureManager().registerFeature("pingspoof", new PingSpoof());
if (tab.getConfiguration().config.getString("yellow-number-in-tablist", "%ping%").length() > 0) tab.getFeatureManager().registerFeature("tabobjective", new TabObjective(tab));
if (tab.getConfiguration().config.getBoolean("do-not-move-spectators", false)) tab.getFeatureManager().registerFeature("spectatorfix", new SpectatorFix());
if (tab.getConfiguration().config.getBoolean("classic-vanilla-belowname.enabled", true)) tab.getFeatureManager().registerFeature("belowname", new BelowName(tab));
if (tab.getConfiguration().premiumconfig != null && tab.getConfiguration().premiumconfig.getBoolean("scoreboard.enabled", false)) tab.getFeatureManager().registerFeature("scoreboard", new ScoreboardManager(tab));
if (tab.getConfiguration().bossbar.getBoolean("bossbar-enabled", false) && nms.minorVersion < 9) tab.getFeatureManager().registerFeature("bossbar1.8", new BossBar_legacy(tab, plugin));
if (nms.minorVersion >= 9 && tab.getConfiguration().config.getBoolean("fix-pet-names", false)) tab.getFeatureManager().registerFeature("petfix", new PetFix(nms));
if (tab.getConfiguration().config.getBoolean("per-world-playerlist.enabled", false)) tab.getFeatureManager().registerFeature("pwp", new PerWorldPlayerlist(plugin, tab));
if (placeholderAPI) {
new TabExpansion(plugin);
@@ -115,7 +125,7 @@ public class BukkitPlatform implements Platform {
*/
private void loadNametagFeature(TAB tab) {
if (tab.getConfiguration().config.getBoolean("change-nametag-prefix-suffix", true)) {
if (tab.getConfiguration().config.getBoolean("unlimited-nametag-prefix-suffix-mode.enabled", false) && ProtocolVersion.SERVER_VERSION.getMinorVersion() >= 8) {
if (tab.getConfiguration().config.getBoolean("unlimited-nametag-prefix-suffix-mode.enabled", false) && nms.minorVersion >= 8) {
tab.getFeatureManager().registerFeature("nametagx", new NameTagX(plugin, nms, tab));
} else {
tab.getFeatureManager().registerFeature("nametag16", new NameTag(tab));
@@ -281,4 +291,9 @@ public class BukkitPlatform implements Platform {
public int getMaxPlayers() {
return Bukkit.getMaxPlayers();
}
@Override
public String getConfigName() {
return "bukkitconfig.yml";
}
}
@@ -1,8 +1,18 @@
package me.neznamy.tab.platforms.bukkit;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import com.viaversion.viaversion.api.Via;
import org.bukkit.Bukkit;
import org.bukkit.boss.BarColor;
import org.bukkit.boss.BarFlag;
import org.bukkit.boss.BarStyle;
import org.bukkit.boss.BossBar;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.plugin.RegisteredServiceProvider;
@@ -14,7 +24,8 @@ import me.neznamy.tab.platforms.bukkit.nms.NMSStorage;
import me.neznamy.tab.shared.ITabPlayer;
import me.neznamy.tab.shared.ProtocolVersion;
import me.neznamy.tab.shared.TAB;
import us.myles.ViaVersion.api.Via;
import me.neznamy.tab.shared.packets.PacketPlayOutBoss;
import me.neznamy.tab.shared.rgb.RGBUtils;
/**
* TabPlayer for Bukkit
@@ -23,12 +34,15 @@ public class BukkitTabPlayer extends ITabPlayer {
//bukkit player
private Player player;
//nms handle
private Object handle;
//nms player connection
private Object playerConnection;
//player's visible boss bars
private Map<UUID, BossBar> bossbars = new HashMap<UUID, BossBar>();
/**
* Constructs new instance with given parameter
@@ -96,7 +110,7 @@ public class BukkitTabPlayer extends ITabPlayer {
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", 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);
}
}
@@ -129,11 +143,71 @@ public class BukkitTabPlayer extends ITabPlayer {
}
return;
}
if (nmsPacket instanceof PacketPlayOutBoss) {
handle((PacketPlayOutBoss) nmsPacket);
return;
}
NMSStorage.getInstance().sendPacket.invoke(playerConnection, nmsPacket);
} catch (Throwable e) {
TAB.getInstance().getErrorManager().printError("An error occurred when sending " + nmsPacket.getClass().getSimpleName(), e);
}
}
private void handle(PacketPlayOutBoss packet) {
Set<BarFlag> flags = new HashSet<BarFlag>();
BossBar bar;
switch (packet.operation) {
case ADD:
if (packet.createWorldFog) flags.add(BarFlag.CREATE_FOG);
if (packet.darkenScreen) flags.add(BarFlag.DARKEN_SKY);
if (packet.playMusic) flags.add(BarFlag.PLAY_BOSS_MUSIC);
bar = Bukkit.createBossBar(RGBUtils.getInstance().convertToBukkitFormat(packet.name, getVersion().getMinorVersion() >= 16 && NMSStorage.getInstance().minorVersion >= 16),
BarColor.valueOf(packet.color.name()),
BarStyle.valueOf(packet.overlay.name().replace("PROGRESS", "SOLID").replace("NOTCHED", "SEGMENTED")),
flags.toArray(new BarFlag[0]));
bossbars.put(packet.id, bar);
bar.addPlayer(player);
break;
case REMOVE:
bossbars.get(packet.id).removePlayer(player);
bossbars.remove(packet.id);
break;
case UPDATE_PCT:
bossbars.get(packet.id).setProgress(packet.pct);
break;
case UPDATE_NAME:
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);
break;
case UPDATE_PROPERTIES:
bar = bossbars.get(packet.id);
processFlag(bar, packet.createWorldFog, BarFlag.CREATE_FOG);
processFlag(bar, packet.darkenScreen, BarFlag.DARKEN_SKY);
processFlag(bar, packet.playMusic, BarFlag.PLAY_BOSS_MUSIC);
break;
default:
break;
}
}
private void processFlag(BossBar bar, boolean targetValue, BarFlag flag) {
if (targetValue) {
if (!bar.hasFlag(flag)) {
bar.addFlag(flag);
}
} else {
if (bar.hasFlag(flag)) {
bar.removeFlag(flag);
}
}
}
@Override
public boolean hasInvisibilityPotion() {
@@ -193,4 +267,28 @@ public class BukkitTabPlayer extends ITabPlayer {
public boolean isOnline() {
return player.isOnline();
}
@Override
public boolean isVanished() {
try {
if (((BukkitPlatform)TAB.getInstance().getPlatform()).essentials) {
Object essentials = Bukkit.getPluginManager().getPlugin("Essentials");
Object user = essentials.getClass().getMethod("getUser", Player.class).invoke(essentials, player);
boolean vanished = (boolean) user.getClass().getMethod("isVanished").invoke(user);
if (vanished) return true;
}
if (player.hasMetadata("vanished") && !player.getMetadata("vanished").isEmpty()) {
return player.getMetadata("vanished").get(0).asBoolean();
}
} catch (Exception e) {
TAB.getInstance().getErrorManager().printError("Failed to check vanish status of " + player.getName(), e);
}
return false;
}
@SuppressWarnings("deprecation")
@Override
public int getGamemode() {
return player.getGameMode().getValue();
}
}
@@ -1,5 +1,6 @@
package me.neznamy.tab.platforms.bukkit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -7,6 +8,7 @@ import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.platforms.bukkit.nms.NMSStorage;
import me.neznamy.tab.shared.ProtocolVersion;
import me.neznamy.tab.shared.TAB;
@@ -35,11 +37,23 @@ public class Main extends JavaPlugin {
sender.sendMessage(message.replace('&', '\u00a7'));
}
} else {
TAB.getInstance().command.execute(sender instanceof Player ? TAB.getInstance().getPlayer(((Player)sender).getUniqueId()) : null, args);
TabPlayer p = null;
if (sender instanceof Player) {
p = TAB.getInstance().getPlayer(((Player)sender).getUniqueId());
if (p == null) return false; //player not loaded correctly
}
TAB.getInstance().command.execute(p, args);
}
return false;
});
Bukkit.getPluginCommand("tab").setTabCompleter((sender, c, cmd, args) -> TAB.getInstance().command.complete(sender instanceof Player ? TAB.getInstance().getPlayer(((Player)sender).getUniqueId()) : null, args));
Bukkit.getPluginCommand("tab").setTabCompleter((sender, c, cmd, args) -> {
TabPlayer p = null;
if (sender instanceof Player) {
p = TAB.getInstance().getPlayer(((Player)sender).getUniqueId());
if (p == null) return new ArrayList<String>(); //player not loaded correctly
}
return TAB.getInstance().command.complete(p, args);
});
TAB.getInstance().load();
new BukkitMetrics(this);
}
@@ -56,9 +70,10 @@ public class Main extends JavaPlugin {
*/
private boolean isVersionSupported(){
List<String> SUPPORTED_VERSIONS = Arrays.asList(
"v1_5_R1", "v1_5_R2", "v1_5_R3", "v1_6_R1", "v1_6_R2", "v1_6_R3",
"v1_7_R1", "v1_7_R2", "v1_7_R3", "v1_7_R4", "v1_8_R1", "v1_8_R2", "v1_8_R3",
"v1_9_R1", "v1_9_R2", "v1_10_R1", "v1_11_R1", "v1_12_R1", "v1_13_R1", "v1_13_R2",
"v1_14_R1", "v1_15_R1", "v1_16_R1", "v1_16_R2", "v1_16_R3");
"v1_14_R1", "v1_15_R1", "v1_16_R1", "v1_16_R2", "v1_16_R3", "v1_17_R1");
String serverPackage = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
try {
NMSStorage.setInstance(new NMSStorage());
@@ -36,24 +36,18 @@ public class BossBar_legacy implements Listener, Loadable {
this.mainFeature = (BossBar) tab.getFeatureManager().getFeature("bossbar");
Bukkit.getPluginManager().registerEvents(this, plugin);
//bar disappears in client after ~1 second of not seeing boss entity
tab.getCPUManager().startRepeatingMeasuredTask(900, "refreshing bossbar", TabFeature.BOSSBAR, UsageType.TELEPORTING_ENTITY, new Runnable() {
public void run() {
for (TabPlayer all : tab.getPlayers()) {
if (all.getVersion().getMinorVersion() > 8) continue; //sending VV packets to those
for (me.neznamy.tab.api.bossbar.BossBar l : all.getActiveBossBars()) {
try {
all.sendPacket(((BukkitPacketBuilder)tab.getPacketBuilder()).buildEntityTeleportPacket(Math.abs(l.getUniqueId().hashCode()), getWitherLocation(all)), TabFeature.BOSSBAR);
} catch (Exception e) {
tab.getErrorManager().printError("Failed to create PacketPlayOutEntityTeleport", e);
}
}
}
}
});
tab.getCPUManager().startRepeatingMeasuredTask(900, "refreshing bossbar", TabFeature.BOSSBAR, UsageType.TELEPORTING_ENTITY, () -> teleport());
}
@Override
public void load() {
teleport();
}
/**
* Updates wither location for all players
*/
private void teleport() {
for (TabPlayer all : TAB.getInstance().getPlayers()) {
if (all.getVersion().getMinorVersion() > 8) continue; //sending VV packets to those
for (me.neznamy.tab.api.bossbar.BossBar l : all.getActiveBossBars()) {
@@ -76,7 +70,7 @@ public class BossBar_legacy implements Listener, Loadable {
*/
@EventHandler
public void onRespawn(PlayerRespawnEvent e) {
TAB.getInstance().getCPUManager().runMeasuredTask("processing PlayerRespawnEvent", getFeatureType(), UsageType.PLAYER_RESPAWN_EVENT, () -> mainFeature.detectBossBarsAndSend(TAB.getInstance().getPlayer(e.getPlayer().getUniqueId())));
TAB.getInstance().getCPUManager().runMeasuredTask("processing PlayerRespawnEvent", TabFeature.BOSSBAR, UsageType.PLAYER_RESPAWN_EVENT, () -> mainFeature.detectBossBarsAndSend(TAB.getInstance().getPlayer(e.getPlayer().getUniqueId())));
}
/**
@@ -90,9 +84,4 @@ public class BossBar_legacy implements Listener, Loadable {
if (loc.getY() < 1) loc.setY(1);
return loc;
}
@Override
public TabFeature getFeatureType() {
return TabFeature.BOSSBAR;
}
}
@@ -46,8 +46,8 @@ public class ExpansionDownloader {
@Override
public void run() {
try {
//initial delay to give PlaceholderAPI time to load
Thread.sleep(5000);
//initial delay to give PlaceholderAPI & plugins with expansions time to load
Thread.sleep(10000);
TAB.getInstance().debug("Used expansions: " + expansions.toString());
TAB.getInstance().debug("Registered expansions in PlaceholderAPI: " + PlaceholderAPI.getRegisteredIdentifiers());
expansions.removeAll(PlaceholderAPI.getRegisteredIdentifiers());
@@ -1,45 +1,35 @@
package me.neznamy.tab.platforms.bukkit.features;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerChangedWorldEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.plugin.java.JavaPlugin;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.cpu.TabFeature;
import me.neznamy.tab.shared.cpu.UsageType;
import me.neznamy.tab.shared.features.types.Loadable;
import me.neznamy.tab.shared.features.types.event.JoinEventListener;
import me.neznamy.tab.shared.features.types.event.WorldChangeListener;
import me.neznamy.tab.shared.features.types.packet.PlayerInfoPacketListener;
import me.neznamy.tab.shared.packets.PacketPlayOutPlayerInfo;
import me.neznamy.tab.shared.packets.PacketPlayOutPlayerInfo.EnumPlayerInfoAction;
import me.neznamy.tab.shared.packets.PacketPlayOutPlayerInfo.PlayerInfoData;
/**
* Per-world-playerlist feature. Currently bukkit API based, however that causes various (compatibility) issues.
* Will be reworked to use packets in the future
* Per-world-playerlist feature handler
*/
@SuppressWarnings("deprecation")
public class PerWorldPlayerlist implements Loadable, JoinEventListener, WorldChangeListener, PlayerInfoPacketListener {
//tab instance
private TAB tab;
public class PerWorldPlayerlist implements Loadable, Listener {
//plugin instance
private JavaPlugin plugin;
//if bypass permission is allowed or not
//config options
private boolean allowBypass;
//list of ignored worlds
private List<String> ignoredWorlds;
//map of worlds that share playerlist
private Map<String, List<String>> sharedWorlds;
/**
@@ -49,7 +39,6 @@ public class PerWorldPlayerlist implements Loadable, JoinEventListener, WorldCha
*/
public PerWorldPlayerlist(JavaPlugin plugin, TAB tab) {
this.plugin = plugin;
this.tab = tab;
allowBypass = tab.getConfiguration().config.getBoolean("per-world-playerlist.allow-bypass-permission", false);
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");
@@ -60,120 +49,59 @@ public class PerWorldPlayerlist implements Loadable, JoinEventListener, WorldCha
}
}
tab.debug(String.format("Loaded PerWorldPlayerlist feature with parameters allowBypass=%s, ignoredWorlds=%s, sharedWorlds=%s", allowBypass, ignoredWorlds, sharedWorlds));
Bukkit.getPluginManager().registerEvents(this, plugin);
}
@Override
public void load(){
for (TabPlayer p : tab.getPlayers()){
hidePlayer(p);
showInSameWorldGroup(p);
}
Bukkit.getScheduler().runTask(plugin, () -> Bukkit.getOnlinePlayers().forEach(p -> checkPlayer(p)));
}
@Override
public void unload(){
for (TabPlayer p : tab.getPlayers()) {
for (TabPlayer pl : tab.getPlayers()) {
((Player) p.getPlayer()).showPlayer((Player) pl.getPlayer());
for (Player p : Bukkit.getOnlinePlayers()) {
for (Player pl : Bukkit.getOnlinePlayers()) {
p.showPlayer(pl);
}
}
HandlerList.unregisterAll(this);
}
@EventHandler
public void onJoin(PlayerJoinEvent e) {
long time = System.nanoTime();
checkPlayer(e.getPlayer());
TAB.getInstance().getCPUManager().addTime(TabFeature.PER_WORLD_PLAYERLIST, UsageType.PLAYER_JOIN_EVENT, System.nanoTime()-time);
}
@EventHandler
public void onWorldChange(PlayerChangedWorldEvent e) {
long time = System.nanoTime();
checkPlayer(e.getPlayer());
TAB.getInstance().getCPUManager().addTime(TabFeature.PER_WORLD_PLAYERLIST, UsageType.WORLD_SWITCH_EVENT, System.nanoTime()-time);
}
private void checkPlayer(Player p) {
for (Player all : Bukkit.getOnlinePlayers()){
if (all == p) continue;
if (!shouldSee(p, all) && p.canSee(all)) p.hidePlayer(all);
if (shouldSee(p, all) && !p.canSee(all)) p.showPlayer(all);
if (!shouldSee(all, p) && all.canSee(p)) all.hidePlayer(p);
if (shouldSee(all, p) && !all.canSee(p)) all.showPlayer(p);
}
}
@Override
public void onJoin(TabPlayer connectedPlayer) {
hidePlayer(connectedPlayer);
showInSameWorldGroup(connectedPlayer);
}
@Override
public void onWorldChange(TabPlayer p, String from, String to) {
hidePlayer(p);
showInSameWorldGroup(p);
}
/**
* Shows all players that player should see
* @param shown - player to process mutual visibility for
*/
private void showInSameWorldGroup(TabPlayer shown){
Bukkit.getScheduler().runTask(plugin, new Runnable() {
@Override
public void run() {
try {
for (TabPlayer everyone : tab.getPlayers()){
if (everyone == shown) continue;
if (shouldSee(shown, everyone)) ((Player) shown.getPlayer()).showPlayer((Player) everyone.getPlayer());
if (shouldSee(everyone, shown)) ((Player) everyone.getPlayer()).showPlayer((Player) shown.getPlayer());
}
} catch (Throwable t) {
tab.getErrorManager().printError("Failed to show players", t);
}
}
});
}
/**
* Returns true if specified viewer should see player, false if not
* @param viewer - tablist viewer
* @param displayed - player to check if should be visible
* @return true if should, false if not
*/
private boolean shouldSee(TabPlayer viewer, TabPlayer displayed) {
if (displayed == viewer) return true;
if ((allowBypass && viewer.hasPermission("tab.bypass")) || ignoredWorlds.contains(((Player)viewer.getPlayer()).getWorld().getName())) return true;
String viewerWorldGroup = ((Player)viewer.getPlayer()).getWorld().getName() + "-default"; //preventing unwanted behavior when some group is called exactly like a world
String targetWorldGroup = ((Player)displayed.getPlayer()).getWorld().getName() + "-default";
private boolean shouldSee(Player viewer, Player target) {
if (target == viewer) return true;
if ((allowBypass && viewer.hasPermission("tab.bypass")) || ignoredWorlds.contains(viewer.getWorld().getName())) return true;
String viewerWorldGroup = viewer.getWorld().getName() + "-default"; //preventing unwanted behavior when some group is called exactly like a world
String targetWorldGroup = target.getWorld().getName() + "-default";
for (String group : sharedWorlds.keySet()) {
if (sharedWorlds.get(group) != null) {
if (sharedWorlds.get(group).contains(((Player)viewer.getPlayer()).getWorld().getName())) viewerWorldGroup = group;
if (sharedWorlds.get(group).contains(((Player)displayed.getPlayer()).getWorld().getName())) targetWorldGroup = group;
if (sharedWorlds.get(group).contains(viewer.getWorld().getName())) viewerWorldGroup = group;
if (sharedWorlds.get(group).contains(target.getWorld().getName())) targetWorldGroup = group;
}
}
return viewerWorldGroup.equals(targetWorldGroup);
}
/**
* Hides the player from everyone and everyone to the player
* @param hidden - player to hide
*/
private void hidePlayer(TabPlayer hidden){
Bukkit.getScheduler().runTask(plugin, new Runnable() {
@Override
public void run() {
try {
for (TabPlayer everyone : tab.getPlayers()){
if (everyone == hidden) continue;
((Player) hidden.getPlayer()).hidePlayer((Player) everyone.getPlayer());
((Player) everyone.getPlayer()).hidePlayer((Player) hidden.getPlayer());
}
} catch (Throwable t) {
tab.getErrorManager().printError("Failed to hide players", t);
}
}
});
}
//fixing bukkit api bug making players not hide when hidePlayer is called too early
@Override
public void onPacketSend(TabPlayer receiver, PacketPlayOutPlayerInfo info) {
if (info.action != EnumPlayerInfoAction.ADD_PLAYER) return;
List<PlayerInfoData> toRemove = new ArrayList<PlayerInfoData>();
for (PlayerInfoData data : info.entries) {
TabPlayer added = tab.getPlayerByTablistUUID(data.uniqueId);
if (added != null && !shouldSee(receiver, added)) {
toRemove.add(data);
}
}
List<PlayerInfoData> newList = new ArrayList<PlayerInfoData>();
info.entries.forEach(d -> newList.add(d));
newList.removeAll(toRemove);
info.entries = newList;
}
@Override
public TabFeature getFeatureType() {
return TabFeature.PER_WORLD_PLAYERLIST;
}
}
@@ -9,7 +9,6 @@ import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.platforms.bukkit.nms.NMSStorage;
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcher;
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcherItem;
import me.neznamy.tab.shared.ProtocolVersion;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.cpu.TabFeature;
import me.neznamy.tab.shared.features.types.event.QuitEventListener;
@@ -23,7 +22,7 @@ import me.neznamy.tab.shared.features.types.packet.RawPacketListener;
public class PetFix implements RawPacketListener, QuitEventListener {
//datawatcher position of pet owner field
private int PET_OWNER_POSITION = getPetOwnerPosition();
private int PET_OWNER_POSITION;
//logger of last interacts to prevent feature not working on 1.16
private Map<String, Long> lastInteractFix = new HashMap<String, Long>();
@@ -37,6 +36,7 @@ public class PetFix implements RawPacketListener, QuitEventListener {
*/
public PetFix(NMSStorage nms) {
this.nms = nms;
PET_OWNER_POSITION = getPetOwnerPosition();
TAB.getInstance().debug("Loaded PetFix feature");
}
@@ -45,13 +45,16 @@ public class PetFix implements RawPacketListener, QuitEventListener {
* @return position of pet owner field based on server version
*/
private int getPetOwnerPosition() {
if (ProtocolVersion.SERVER_VERSION.getMinorVersion() >= 15) {
if (nms.minorVersion >= 17) {
//1.17.x
return 18;
} else if (nms.minorVersion >= 15) {
//1.15.x, 1.16.x
return 17;
} else if (ProtocolVersion.SERVER_VERSION.getMinorVersion() >= 14) {
} else if (nms.minorVersion >= 14) {
//1.14.x
return 16;
} else if (ProtocolVersion.SERVER_VERSION.getMinorVersion() >= 10) {
} else if (nms.minorVersion >= 10) {
//1.10.x - 1.13.x
return 14;
} else {
@@ -91,7 +94,7 @@ public class PetFix implements RawPacketListener, QuitEventListener {
for (Object item : items) {
if (nms.DataWatcherObject_SLOT.getInt(nms.DataWatcherItem_TYPE.get(item)) == PET_OWNER_POSITION) {
Object value = nms.DataWatcherItem_VALUE.get(item);
if (value instanceof java.util.Optional || value instanceof com.google.common.base.Optional) continue;
if (value.getClass().getSimpleName().equals("Optional")) continue;
}
newList.add(item);
}
@@ -101,7 +104,7 @@ public class PetFix implements RawPacketListener, QuitEventListener {
if (nms.PacketPlayOutSpawnEntityLiving.isInstance(packet) && nms.PacketPlayOutSpawnEntityLiving_DATAWATCHER != null) {
DataWatcher watcher = DataWatcher.fromNMS(nms.PacketPlayOutSpawnEntityLiving_DATAWATCHER.get(packet));
DataWatcherItem petOwner = watcher.getItem(PET_OWNER_POSITION);
if (petOwner != null && (petOwner.value instanceof java.util.Optional || petOwner.value instanceof com.google.common.base.Optional)) {
if (petOwner != null && petOwner.value.getClass().getSimpleName().equals("Optional")) {
watcher.removeValue(PET_OWNER_POSITION);
nms.PacketPlayOutSpawnEntityLiving_DATAWATCHER.set(packet, watcher.toNMS());
}
@@ -305,19 +305,19 @@ public class BukkitArmorStand implements ArmorStand {
* @return correct player's Y
*/
private double getY() {
//1.14+ bukkit api bug
//1.14+ server sided bug
Entity vehicle = player.getVehicle();
if (vehicle != null) {
if (vehicle.getType() == EntityType.HORSE) {
if (vehicle.getType().toString().contains("HORSE")) { //covering all 3 horse types
return vehicle.getLocation().getY() + 0.85;
}
if (vehicle.getType().toString().equals("DONKEY")) {
if (vehicle.getType() == EntityType.DONKEY) {
return vehicle.getLocation().getY() + 0.525;
}
if (vehicle.getType() == EntityType.PIG) {
return vehicle.getLocation().getY() + 0.325;
}
if (vehicle.getType().toString().equals("STRIDER")) { //preventing errors on <1.16
if (vehicle.getType().toString().equals("STRIDER")) { //added in 1.16
return vehicle.getLocation().getY() + 1.15;
}
}
@@ -3,6 +3,7 @@ package me.neznamy.tab.platforms.bukkit.features.unlimitedtags;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -148,6 +149,7 @@ public class NameTagX extends NameTag {
if (!playerLocations.containsKey(p) || !playerLocations.get(p).equals(((Player)p.getPlayer()).getLocation())) {
playerLocations.put(p, ((Player)p.getPlayer()).getLocation());
processPassengers((Entity) p.getPlayer());
//also updating position if player is previewing since we're here as the code would be same if we want to avoid listening to move event
if (p.isPreviewingNametag() && p.getArmorStandManager() != null) {
p.getArmorStandManager().teleport(p);
}
@@ -271,18 +273,11 @@ public class NameTagX extends NameTag {
if (((Player) viewer.getPlayer()).getWorld() != ((Player) owner.getPlayer()).getWorld()) return; //different world
if (isDisabledWorld(owner.getWorldName()) || isDisabledWorld(disabledUnlimitedWorlds, owner.getWorldName())) return;
if (getDistance(viewer, owner) <= 48) {
if (((Player)viewer.getPlayer()).canSee((Player)owner.getPlayer()) && !isVanished((Player) owner.getPlayer())) owner.getArmorStandManager().spawn(viewer);
if (((Player)viewer.getPlayer()).canSee((Player)owner.getPlayer()) && !owner.isVanished()) owner.getArmorStandManager().spawn(viewer);
if (sendMutually && viewer.getArmorStandManager() != null && ((Player)owner.getPlayer()).canSee((Player)viewer.getPlayer())
&& !isVanished((Player) viewer.getPlayer())) viewer.getArmorStandManager().spawn(owner);
&& !viewer.isVanished()) viewer.getArmorStandManager().spawn(owner);
}
}
private boolean isVanished(Player player) {
if (player.hasMetadata("vanished") && !player.getMetadata("vanished").isEmpty()) {
return player.getMetadata("vanished").get(0).asBoolean();
}
return false;
}
/**
* Restarts and loads armor stands from config
@@ -383,13 +378,18 @@ public class NameTagX extends NameTag {
@Override
public void refreshUsedPlaceholders() {
usedPlaceholders = tab.getConfiguration().config.getUsedPlaceholderIdentifiersRecursive("tagprefix", "customtagname", "tagsuffix");
usedPlaceholders = new HashSet<>(tab.getConfiguration().config.getUsedPlaceholderIdentifiersRecursive("tagprefix", "customtagname", "tagsuffix"));
for (String line : dynamicLines) {
usedPlaceholders.addAll(tab.getConfiguration().config.getUsedPlaceholderIdentifiersRecursive(line));
}
for (String line : staticLines.keySet()) {
usedPlaceholders.addAll(tab.getConfiguration().config.getUsedPlaceholderIdentifiersRecursive(line));
}
for (TabPlayer p : tab.getPlayers()) {
usedPlaceholders.addAll(tab.getPlaceholderManager().getUsedPlaceholderIdentifiersRecursive(p.getProperty("tagprefix").getCurrentRawValue(),
p.getProperty("customtagname").getCurrentRawValue(), p.getProperty("tagsuffix").getCurrentRawValue(),
p.getProperty("abovename").getCurrentRawValue(), p.getProperty("belowname").getCurrentRawValue()));
}
}
@Override
@@ -74,7 +74,13 @@ public class PacketListener implements RawPacketListener {
onEntitySpawn(receiver, nms.PacketPlayOutNamedEntitySpawn_ENTITYID.getInt(packet));
}
if (nms.PacketPlayOutEntityDestroy.isInstance(packet)) {
onEntityDestroy(receiver, (int[]) nms.PacketPlayOutEntityDestroy_ENTITIES.get(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);
}
}
}
}
@@ -107,12 +113,10 @@ public class PacketListener implements RawPacketListener {
}
}
public void onEntityDestroy(TabPlayer receiver, int[] entities) {
for (int id : entities) {
TabPlayer despawnedPlayer = nameTagX.entityIdMap.get(id);
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 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));
}
@Override
@@ -1,13 +1,13 @@
package me.neznamy.tab.platforms.bukkit.nms;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.bukkit.Bukkit;
@@ -21,19 +21,22 @@ public class NMSStorage {
//instance of this class
private static NMSStorage instance;
//field mapping changes in thermos
private Map<String, String> thermosFieldMappings = new HashMap<String, String>();
//data watcher registry
public DataWatcherRegistry dataWatcherRegistry;
//server package, such as "v1_16_R3"
private String serverPackage;
//server minor version such as "16"
public int minorVersion;
public Class<?> Entity;
public Class<?> EntityLiving;
private Class<?> Packet;
private Class<?> PlayerConnection;
private Class<?> NetworkManager;
public Class<?> EntityPlayer;
public Field PING;
public Field PLAYER_CONNECTION;
public Field NETWORK_MANAGER;
@@ -44,16 +47,16 @@ public class NMSStorage {
//chat
public Class<Enum> EnumChatFormat;
public Class<?> IChatBaseComponent;
public Class<?> ChatBaseComponent;
public Class<?> ChatSerializer;
public Class<?> EnumClickAction;
public Class<?> EnumHoverAction;
public Class<?> ChatModifier;
private Class<?> IChatBaseComponent;
private Class<?> ChatBaseComponent;
private Class<?> ChatSerializer;
private Class<?> EnumClickAction;
private Class<?> EnumHoverAction;
private Class<?> ChatModifier;
public Class<?> ChatComponentText;
public Class<?> ChatClickable;
public Class<?> ChatHoverable;
public Class<?> ChatHexColor;
private Class<?> ChatClickable;
private Class<?> ChatHoverable;
private Class<?> ChatHexColor;
public Constructor<?> newChatComponentText;
public Constructor<?> newChatClickable;
public Constructor<?> newChatHoverable;
@@ -82,29 +85,10 @@ public class NMSStorage {
public Method ChatHexColor_ofString;
public Method ChatComponentText_addSibling;
//PacketPlayOutBoss
public Class<?> PacketPlayOutBoss;
public Class<Enum> BarColor;
public Class<Enum> BarStyle;
public Class<Enum> PacketPlayOutBoss_Action;
public Constructor<?> newPacketPlayOutBoss;
public Field PacketPlayOutBoss_UUID;
public Field PacketPlayOutBoss_ACTION;
public Field PacketPlayOutBoss_NAME;
public Field PacketPlayOutBoss_PROGRESS;
public Field PacketPlayOutBoss_COLOR;
public Field PacketPlayOutBoss_STYLE;
public Field PacketPlayOutBoss_DARKEN_SKY;
public Field PacketPlayOutBoss_PLAY_MUSIC;
public Field PacketPlayOutBoss_CREATE_FOG;
//PacketPlayOutChat
public Class<?> PacketPlayOutChat;
private Class<?> PacketPlayOutChat;
public Class<Enum> ChatMessageType;
public Constructor<?> newPacketPlayOutChat;
public Field PacketPlayOutChat_MESSAGE;
public Field PacketPlayOutChat_POSITION;
public Field PacketPlayOutChat_SENDER;
//PacketPlayOutPlayerListHeaderFooter
public Class<?> PacketPlayOutPlayerListHeaderFooter;
@@ -120,78 +104,76 @@ public class NMSStorage {
//PacketPlayOutScoreboardObjective
public Class<?> PacketPlayOutScoreboardObjective;
public Class<?> IScoreboardCriteria;
private Class<?> ScoreboardObjective;
public Class<Enum> EnumScoreboardHealthDisplay;
public Constructor<?> newPacketPlayOutScoreboardObjective;
public Constructor<?> newScoreboardObjective;
public Field PacketPlayOutScoreboardObjective_OBJECTIVENAME;
public Field PacketPlayOutScoreboardObjective_DISPLAYNAME;
public Field PacketPlayOutScoreboardObjective_RENDERTYPE;
public Field PacketPlayOutScoreboardObjective_METHOD;
//PacketPlayOutScoreboardScore
public Class<?> PacketPlayOutScoreboardScore;
private Class<?> PacketPlayOutScoreboardScore;
private Class<?> ScoreboardScore;
public Class<Enum> EnumScoreboardAction;
public Constructor<?> newPacketPlayOutScoreboardScore0;
public Constructor<?> newPacketPlayOutScoreboardScore;
public Constructor<?> newPacketPlayOutScoreboardScore_String;
public Constructor<?> newPacketPlayOutScoreboardScore_1_13;
public Field PacketPlayOutScoreboardScore_PLAYER;
public Field PacketPlayOutScoreboardScore_OBJECTIVENAME;
public Field PacketPlayOutScoreboardScore_SCORE;
public Field PacketPlayOutScoreboardScore_ACTION;
public Constructor<?> newScoreboardScore;
public Method ScoreboardScore_setScore;
//PacketPlayOutScoreboardTeam
public Class<?> PacketPlayOutScoreboardTeam;
public Class<?> EnumNameTagVisibility;
public Class<?> EnumTeamPush;
public Constructor<?> newPacketPlayOutScoreboardTeam;
public Field PacketPlayOutScoreboardTeam_NAME;
public Field PacketPlayOutScoreboardTeam_DISPLAYNAME;
public Field PacketPlayOutScoreboardTeam_PREFIX;
public Field PacketPlayOutScoreboardTeam_SUFFIX;
public Field PacketPlayOutScoreboardTeam_VISIBILITY; //1.8+
public Field PacketPlayOutScoreboardTeam_CHATFORMAT; //1.13+
public Field PacketPlayOutScoreboardTeam_COLLISION; //1.9+
public Field PacketPlayOutScoreboardTeam_PLAYERS;
public Field PacketPlayOutScoreboardTeam_ACTION;
public Field PacketPlayOutScoreboardTeam_SIGNATURE;
private Class<?> Scoreboard;
private Class<?> ScoreboardTeam;
public Constructor<?> newScoreboard;
public Constructor<?> newScoreboardTeam;
public Method ScoreboardTeam_setPrefix;
public Method ScoreboardTeam_setSuffix;
public Method ScoreboardTeam_setNameTagVisibility;
public Method ScoreboardTeam_setCollisionRule;
public Method ScoreboardTeam_setColor;
public Method ScoreboardTeam_getPlayerNameSet;
//1.17
public Class<?> PacketPlayOutScoreboardTeam_a;
public Method PacketPlayOutScoreboardTeam_of;
public Method PacketPlayOutScoreboardTeam_ofBoolean;
public Method PacketPlayOutScoreboardTeam_ofString;
//PacketPlayOutPlayerInfo
public Class<?> PacketPlayOutPlayerInfo;
public Class<Enum> EnumGamemode;
public Class<Enum> EnumPlayerInfoAction;
public Class<?> PlayerInfoData;
private Class<?> PlayerInfoData;
public Constructor<?> newPacketPlayOutPlayerInfo;
public Constructor<?> newPlayerInfoData;
public Class<?> GameProfile;
public Constructor<?> newGameProfile;
public Field GameProfile_ID;
public Field GameProfile_NAME;
public Field GameProfile_PROPERTIES;
public Class<?> PropertyMap;
public Method PropertyMap_putAll;
public Field PacketPlayOutPlayerInfo_ACTION;
public Field PacketPlayOutPlayerInfo_PLAYERS;
public Field PlayerInfoData_PING;
public Field PlayerInfoData_GAMEMODE;
public Field PlayerInfoData_PROFILE;
public Field PlayerInfoData_LISTNAME;
//PacketPlayOutTitle
public Class<?> PacketPlayOutTitle;
public Constructor<?> newPacketPlayOutTitle;
public Class<Enum> EnumTitleAction;
public Method PlayerInfoData_getProfile;
public Method PlayerInfoData_getLatency;
public Method PlayerInfoData_getGamemode;
public Method PlayerInfoData_getDisplayName;
public Class<?> PacketPlayOutEntityDestroy;
public Constructor<?> newPacketPlayOutEntityDestroy;
public Field PacketPlayOutEntityDestroy_ENTITIES;
public Class<?> PacketPlayInUseEntity;
private Class<?> EnumEntityUseAction;
public Field PacketPlayInUseEntity_ENTITY;
public Field PacketPlayInUseEntity_ACTION;
public Class<?> PacketPlayOutNamedEntitySpawn;
public Field PacketPlayOutNamedEntitySpawn_ENTITYID;
public Class<?> PacketPlayOutEntity;
public Class<?> PacketPlayOutEntityLook;
public Field PacketPlayOutEntity_ENTITYID;
@@ -222,21 +204,21 @@ public class NMSStorage {
public Field PacketPlayOutSpawnEntityLiving_DATAWATCHER;
//DataWatcher
public Class<?> DataWatcher;
private Class<?> DataWatcher;
public Constructor<?> newDataWatcher;
public Method DataWatcher_REGISTER;
public Class<?> DataWatcherItem;
public Constructor<?> newDataWatcherItem;
private Class<?> DataWatcherItem;
public Field DataWatcherItem_TYPE;
public Field DataWatcherItem_VALUE;
public Class<?> DataWatcherObject;
private Class<?> DataWatcherObject;
public Constructor<?> newDataWatcherObject;
public Field DataWatcherObject_SLOT;
public Field DataWatcherObject_SERIALIZER;
public Class<?> DataWatcherRegistry;
private Class<?> DataWatcherRegistry;
private Class<?> DataWatcherSerializer;
/**
* Creates new instance, initializes required NMS classes and fields
@@ -245,14 +227,13 @@ public class NMSStorage {
public NMSStorage() throws Exception {
serverPackage = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
minorVersion = Integer.parseInt(serverPackage.split("_")[1]);
loadThermosMappings();
initializeClasses();
initializeConstructors();
initializeFields();
initializeMethods();
dataWatcherRegistry = new DataWatcherRegistry(DataWatcherRegistry);
dataWatcherRegistry = new DataWatcherRegistry(this, DataWatcherRegistry);
}
/**
* Sets new instance
* @param instance - new instance
@@ -260,7 +241,7 @@ public class NMSStorage {
public static void setInstance(NMSStorage instance) {
NMSStorage.instance = instance;
}
/**
* Returns instance
* @return instance
@@ -269,81 +250,77 @@ public class NMSStorage {
return instance;
}
/**
* Puts thermos mapping changes into map
*/
private void loadThermosMappings() {
thermosFieldMappings.put("ping", "field_71138_i");
thermosFieldMappings.put("playerConnection", "field_71135_a");
thermosFieldMappings.put("networkManager", "field_147371_a");
}
/**
* Initializes required NMS classes
* @throws Exception - if something fails
*/
public void initializeClasses() throws Exception {
ChatModifier = getNMSClass("ChatModifier");
ChatBaseComponent = getNMSClass("ChatBaseComponent");
ChatComponentText = getNMSClass("ChatComponentText");
ChatClickable = getNMSClass("ChatClickable");
ChatHoverable = getNMSClass("ChatHoverable");
DataWatcher = getNMSClass("DataWatcher");
//1.9+; v1_8_R2 & v1_8_R3; 1.7 - v1_8_R1
DataWatcherItem = getNMSClass("DataWatcher$Item", "DataWatcher$WatchableObject", "WatchableObject");
EnumChatFormat = (Class<Enum>) getNMSClass("EnumChatFormat");
IChatBaseComponent = getNMSClass("IChatBaseComponent");
PacketPlayInUseEntity = getNMSClass("PacketPlayInUseEntity");
PacketPlayOutChat = getNMSClass("PacketPlayOutChat");
PacketPlayOutEntity = getNMSClass("PacketPlayOutEntity");
//v1_8_R2+; v1_7_R1 - v1_8_R1
PacketPlayOutEntityLook = getNMSClass("PacketPlayOutEntity$PacketPlayOutEntityLook", "PacketPlayOutEntityLook");
PacketPlayOutEntityDestroy = getNMSClass("PacketPlayOutEntityDestroy");
PacketPlayOutEntityMetadata = getNMSClass("PacketPlayOutEntityMetadata");
PacketPlayOutEntityTeleport = getNMSClass("PacketPlayOutEntityTeleport");
PacketPlayOutNamedEntitySpawn = getNMSClass("PacketPlayOutNamedEntitySpawn");
PacketPlayOutScoreboardDisplayObjective = getNMSClass("PacketPlayOutScoreboardDisplayObjective");
PacketPlayOutScoreboardObjective = getNMSClass("PacketPlayOutScoreboardObjective");
PacketPlayOutScoreboardScore = getNMSClass("PacketPlayOutScoreboardScore");
PacketPlayOutScoreboardTeam = getNMSClass("PacketPlayOutScoreboardTeam");
PacketPlayOutSpawnEntityLiving = getNMSClass("PacketPlayOutSpawnEntityLiving");
//v1_8_R2+; //v1.8.R1-
ChatSerializer = getNMSClass("IChatBaseComponent$ChatSerializer", "ChatSerializer");
EnumClickAction = getNMSClass("ChatClickable$EnumClickAction", "EnumClickAction");
EnumHoverAction = getNMSClass("ChatHoverable$EnumHoverAction", "EnumHoverAction");
private void initializeClasses() throws Exception {
DataWatcher = getNMSClass("net.minecraft.network.syncher.DataWatcher", "DataWatcher");
DataWatcherItem = getNMSClass("net.minecraft.network.syncher.DataWatcher$Item", "DataWatcher$Item", "DataWatcher$WatchableObject", "WatchableObject");
EntityPlayer = getNMSClass("net.minecraft.server.level.EntityPlayer", "EntityPlayer");
EnumChatFormat = (Class<Enum>) getNMSClass("net.minecraft.EnumChatFormat", "EnumChatFormat");
Entity = getNMSClass("net.minecraft.world.entity.Entity", "Entity");
EntityLiving = getNMSClass("net.minecraft.world.entity.EntityLiving", "EntityLiving");
Packet = getNMSClass("net.minecraft.network.protocol.Packet", "Packet");
PacketPlayInUseEntity = getNMSClass("net.minecraft.network.protocol.game.PacketPlayInUseEntity", "PacketPlayInUseEntity", "Packet7UseEntity");
PacketPlayOutChat = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutChat", "PacketPlayOutChat", "Packet3Chat");
PacketPlayOutEntity = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutEntity", "PacketPlayOutEntity", "Packet30Entity");
PacketPlayOutEntityDestroy = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutEntityDestroy", "PacketPlayOutEntityDestroy", "Packet29DestroyEntity");
PacketPlayOutEntityLook = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutEntity$PacketPlayOutEntityLook", "PacketPlayOutEntity$PacketPlayOutEntityLook", "PacketPlayOutEntityLook", "Packet32EntityLook");
PacketPlayOutEntityMetadata = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutEntityMetadata", "PacketPlayOutEntityMetadata", "Packet40EntityMetadata");
PacketPlayOutEntityTeleport = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutEntityTeleport", "PacketPlayOutEntityTeleport", "Packet34EntityTeleport");
PacketPlayOutNamedEntitySpawn = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutNamedEntitySpawn", "PacketPlayOutNamedEntitySpawn", "Packet20NamedEntitySpawn");
PacketPlayOutScoreboardDisplayObjective = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutScoreboardDisplayObjective", "PacketPlayOutScoreboardDisplayObjective", "Packet208SetScoreboardDisplayObjective");
PacketPlayOutScoreboardObjective = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutScoreboardObjective", "PacketPlayOutScoreboardObjective", "Packet206SetScoreboardObjective");
PacketPlayOutScoreboardScore = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutScoreboardScore", "PacketPlayOutScoreboardScore", "Packet207SetScoreboardScore");
PacketPlayOutScoreboardTeam = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutScoreboardTeam", "PacketPlayOutScoreboardTeam", "Packet209SetScoreboardTeam");
PacketPlayOutSpawnEntityLiving = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutSpawnEntityLiving", "PacketPlayOutSpawnEntityLiving", "Packet24MobSpawn");
PlayerConnection = getNMSClass("net.minecraft.server.network.PlayerConnection", "PlayerConnection");
NetworkManager = getNMSClass("net.minecraft.network.NetworkManager", "NetworkManager");
Scoreboard = getNMSClass("net.minecraft.world.scores.Scoreboard", "Scoreboard");
ScoreboardObjective = getNMSClass("net.minecraft.world.scores.ScoreboardObjective", "ScoreboardObjective");
ScoreboardTeam = getNMSClass("net.minecraft.world.scores.ScoreboardTeam", "ScoreboardTeam");
ScoreboardScore = getNMSClass("net.minecraft.world.scores.ScoreboardScore", "ScoreboardScore");
IScoreboardCriteria = getNMSClass("net.minecraft.world.scores.criteria.IScoreboardCriteria", "IScoreboardCriteria");
if (minorVersion >= 7) {
ChatBaseComponent = getNMSClass("net.minecraft.network.chat.ChatBaseComponent", "ChatBaseComponent");
ChatClickable = getNMSClass("net.minecraft.network.chat.ChatClickable", "ChatClickable");
ChatComponentText = getNMSClass("net.minecraft.network.chat.ChatComponentText", "ChatComponentText");
ChatHoverable = getNMSClass("net.minecraft.network.chat.ChatHoverable", "ChatHoverable");
ChatModifier = getNMSClass("net.minecraft.network.chat.ChatModifier", "ChatModifier");
ChatSerializer = getNMSClass("net.minecraft.network.chat.IChatBaseComponent$ChatSerializer", "IChatBaseComponent$ChatSerializer", "ChatSerializer");
EnumClickAction = getNMSClass("net.minecraft.network.chat.ChatClickable$EnumClickAction", "ChatClickable$EnumClickAction", "EnumClickAction");
EnumHoverAction = getNMSClass("net.minecraft.network.chat.ChatHoverable$EnumHoverAction", "ChatHoverable$EnumHoverAction", "EnumHoverAction");
IChatBaseComponent = getNMSClass("net.minecraft.network.chat.IChatBaseComponent", "IChatBaseComponent");
EnumEntityUseAction = getNMSClass("net.minecraft.network.protocol.game.PacketPlayInUseEntity$EnumEntityUseAction", "PacketPlayInUseEntity$EnumEntityUseAction", "EnumEntityUseAction");
}
if (minorVersion >= 8) {
GameProfile = Class.forName("com.mojang.authlib.GameProfile");
PropertyMap = Class.forName("com.mojang.authlib.properties.PropertyMap");
PacketPlayOutPlayerInfo = getNMSClass("PacketPlayOutPlayerInfo");
PacketPlayOutPlayerListHeaderFooter = getNMSClass("PacketPlayOutPlayerListHeaderFooter");
PacketPlayOutTitle = getNMSClass("PacketPlayOutTitle");
//v1_8_R2+; v1_8_R1
EnumPlayerInfoAction = (Class<Enum>) getNMSClass("PacketPlayOutPlayerInfo$EnumPlayerInfoAction", "EnumPlayerInfoAction");
PlayerInfoData = getNMSClass("PacketPlayOutPlayerInfo$PlayerInfoData", "PlayerInfoData");
EnumScoreboardHealthDisplay = (Class<Enum>) getNMSClass("IScoreboardCriteria$EnumScoreboardHealthDisplay", "EnumScoreboardHealthDisplay");
EnumTitleAction = (Class<Enum>) getNMSClass("PacketPlayOutTitle$EnumTitleAction", "EnumTitleAction");
//everything; v1_8_R2 - v1_9_R2
EnumGamemode = (Class<Enum>) getNMSClass("EnumGamemode", "WorldSettings$EnumGamemode");
//1.13+; 1_8_R2 - 1.12; 1_8_R1
EnumScoreboardAction = (Class<Enum>) getNMSClass("ScoreboardServer$Action", "PacketPlayOutScoreboardScore$EnumScoreboardAction", "EnumScoreboardAction");
PacketPlayOutPlayerInfo = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo", "PacketPlayOutPlayerInfo");
PacketPlayOutPlayerListHeaderFooter = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutPlayerListHeaderFooter", "PacketPlayOutPlayerListHeaderFooter");
EnumPlayerInfoAction = (Class<Enum>) getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo$EnumPlayerInfoAction", "PacketPlayOutPlayerInfo$EnumPlayerInfoAction", "EnumPlayerInfoAction");
PlayerInfoData = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo$PlayerInfoData", "PacketPlayOutPlayerInfo$PlayerInfoData", "PlayerInfoData");
EnumScoreboardHealthDisplay = (Class<Enum>) getNMSClass("net.minecraft.world.scores.criteria.IScoreboardCriteria$EnumScoreboardHealthDisplay", "IScoreboardCriteria$EnumScoreboardHealthDisplay", "EnumScoreboardHealthDisplay");
EnumGamemode = (Class<Enum>) getNMSClass("net.minecraft.world.level.EnumGamemode", "EnumGamemode", "WorldSettings$EnumGamemode");
EnumScoreboardAction = (Class<Enum>) getNMSClass("net.minecraft.server.ScoreboardServer$Action", "ScoreboardServer$Action", "PacketPlayOutScoreboardScore$EnumScoreboardAction", "EnumScoreboardAction");
EnumNameTagVisibility = getNMSClass("net.minecraft.world.scores.ScoreboardTeamBase$EnumNameTagVisibility", "ScoreboardTeamBase$EnumNameTagVisibility", "EnumNameTagVisibility");
}
if (minorVersion >= 9) {
DataWatcherObject = getNMSClass("DataWatcherObject");
DataWatcherRegistry = getNMSClass("DataWatcherRegistry");
PacketPlayOutBoss = getNMSClass("PacketPlayOutBoss");
BarColor = (Class<Enum>) getNMSClass("BossBattle$BarColor");
BarStyle = (Class<Enum>) getNMSClass("BossBattle$BarStyle");
PacketPlayOutBoss_Action = (Class<Enum>) getNMSClass("PacketPlayOutBoss$Action");
DataWatcherObject = getNMSClass("net.minecraft.network.syncher.DataWatcherObject", "DataWatcherObject");
DataWatcherRegistry = getNMSClass("net.minecraft.network.syncher.DataWatcherRegistry", "DataWatcherRegistry");
DataWatcherSerializer = getNMSClass("net.minecraft.network.syncher.DataWatcherSerializer", "DataWatcherSerializer");
EnumTeamPush = getNMSClass("net.minecraft.world.scores.ScoreboardTeamBase$EnumTeamPush", "ScoreboardTeamBase$EnumTeamPush");
}
if (minorVersion >= 12) {
ChatMessageType = (Class<Enum>) getNMSClass("ChatMessageType");
ChatMessageType = (Class<Enum>) getNMSClass("net.minecraft.network.chat.ChatMessageType", "ChatMessageType");
}
if (minorVersion >= 16) {
ChatHexColor = getNMSClass("ChatHexColor");
ChatHexColor = getNMSClass("net.minecraft.network.chat.ChatHexColor", "ChatHexColor");
}
if (minorVersion >= 17) {
PacketPlayOutScoreboardTeam_a = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutScoreboardTeam$a");
}
}
@@ -351,47 +328,57 @@ public class NMSStorage {
* Initializes required NMS constructors
* @throws Exception - if something fails
*/
public void initializeConstructors() throws Exception {
newChatComponentText = ChatComponentText.getConstructor(String.class);
newChatClickable = ChatClickable.getConstructor(EnumClickAction, String.class);
newDataWatcher = DataWatcher.getConstructor(getNMSClass("Entity"));
newDataWatcherItem = DataWatcherItem.getConstructors()[0];
newPacketPlayOutChat = PacketPlayOutChat.getConstructor();
newPacketPlayOutScoreboardDisplayObjective = PacketPlayOutScoreboardDisplayObjective.getConstructor();
newPacketPlayOutScoreboardObjective = PacketPlayOutScoreboardObjective.getConstructor();
newPacketPlayOutScoreboardTeam = PacketPlayOutScoreboardTeam.getConstructor();
newPacketPlayOutEntityDestroy = PacketPlayOutEntityDestroy.getConstructor(int[].class);
private void initializeConstructors() throws Exception {
newDataWatcher = DataWatcher.getConstructors()[0];
newPacketPlayOutEntityMetadata = PacketPlayOutEntityMetadata.getConstructor(int.class, DataWatcher, boolean.class);
newPacketPlayOutEntityTeleport = PacketPlayOutEntityTeleport.getConstructor();
newPacketPlayOutSpawnEntityLiving = PacketPlayOutSpawnEntityLiving.getConstructor();
newScoreboardObjective = ScoreboardObjective.getConstructors()[0];
newScoreboard = Scoreboard.getConstructor();
newScoreboardTeam = ScoreboardTeam.getConstructor(Scoreboard, String.class);
newScoreboardScore = ScoreboardScore.getConstructor(Scoreboard, ScoreboardObjective, String.class);
newPacketPlayOutEntityDestroy = getConstructor(PacketPlayOutEntityDestroy, 1);
newPacketPlayOutEntityTeleport = PacketPlayOutEntityTeleport.getConstructor(Entity);
newPacketPlayOutSpawnEntityLiving = PacketPlayOutSpawnEntityLiving.getConstructor(EntityLiving);
newPacketPlayOutScoreboardDisplayObjective = PacketPlayOutScoreboardDisplayObjective.getConstructor(int.class, ScoreboardObjective);
if (minorVersion >= 7) {
newChatComponentText = ChatComponentText.getConstructor(String.class);
newChatClickable = ChatClickable.getConstructor(EnumClickAction, String.class);
newChatHoverable = ChatHoverable.getConstructors()[0];
}
if (minorVersion >= 8) {
newGameProfile = GameProfile.getConstructor(UUID.class, String.class);
newPacketPlayOutPlayerListHeaderFooter = PacketPlayOutPlayerListHeaderFooter.getConstructor();
newPacketPlayOutTitle = PacketPlayOutTitle.getConstructor(EnumTitleAction, IChatBaseComponent, int.class, int.class, int.class);
newPacketPlayOutPlayerInfo = PacketPlayOutPlayerInfo.getConstructor();
try {
newPlayerInfoData = PlayerInfoData.getConstructor(PacketPlayOutPlayerInfo, GameProfile, int.class, EnumGamemode, IChatBaseComponent);
} catch (Exception e) {
//1.8.8 paper
newPlayerInfoData = PlayerInfoData.getConstructor(GameProfile, int.class, EnumGamemode, IChatBaseComponent);
}
newPacketPlayOutPlayerListHeaderFooter = PacketPlayOutPlayerListHeaderFooter.getConstructors()[0];
newPacketPlayOutPlayerInfo = PacketPlayOutPlayerInfo.getConstructor(EnumPlayerInfoAction, Array.newInstance(EntityPlayer, 0).getClass());
newPlayerInfoData = PlayerInfoData.getConstructors()[0];
}
if (minorVersion >= 9) {
newDataWatcherObject = DataWatcherObject.getConstructors()[0];
newPacketPlayOutBoss = PacketPlayOutBoss.getConstructor();
}
if (minorVersion >= 13) {
newPacketPlayOutScoreboardObjective = PacketPlayOutScoreboardObjective.getConstructor(ScoreboardObjective, int.class);
newPacketPlayOutScoreboardScore_1_13 = PacketPlayOutScoreboardScore.getConstructor(EnumScoreboardAction, String.class, String.class, int.class);
} else {
newPacketPlayOutScoreboardScore0 = PacketPlayOutScoreboardScore.getConstructor();
newPacketPlayOutScoreboardObjective = PacketPlayOutScoreboardObjective.getConstructor();
newPacketPlayOutScoreboardScore_String = PacketPlayOutScoreboardScore.getConstructor(String.class);
if (minorVersion >= 8) {
newPacketPlayOutScoreboardScore = PacketPlayOutScoreboardScore.getConstructor(ScoreboardScore);
} else {
newPacketPlayOutScoreboardScore = PacketPlayOutScoreboardScore.getConstructor(ScoreboardScore, int.class);
}
}
if (minorVersion >= 16) {
newChatHoverable = ChatHoverable.getConstructor(EnumHoverAction, Object.class);
newChatModifier = getConstructor(ChatModifier, 10);
} else {
newChatHoverable = ChatHoverable.getConstructor(EnumHoverAction, IChatBaseComponent);
newPacketPlayOutChat = PacketPlayOutChat.getConstructor(IChatBaseComponent, ChatMessageType, UUID.class);
} else if (minorVersion >= 7) {
newChatModifier = ChatModifier.getConstructor();
if (minorVersion >= 12) {
newPacketPlayOutChat = PacketPlayOutChat.getConstructor(IChatBaseComponent, ChatMessageType);
} else if (minorVersion >= 8) {
newPacketPlayOutChat = PacketPlayOutChat.getConstructor(IChatBaseComponent, byte.class);
} else {
newPacketPlayOutChat = PacketPlayOutChat.getConstructor(IChatBaseComponent);
}
}
if (minorVersion < 17) {
newPacketPlayOutScoreboardTeam = PacketPlayOutScoreboardTeam.getConstructor(ScoreboardTeam, int.class);
}
}
@@ -399,174 +386,117 @@ public class NMSStorage {
* Initializes required NMS fields
* @throws Exception - if something fails
*/
public void initializeFields() throws Exception {
ChatBaseComponent_modifier = getFields(ChatBaseComponent, ChatModifier).get(0);
ChatComponentText_text = getFields(ChatComponentText, String.class).get(0);
ChatClickable_action = getField(ChatClickable, "a");
ChatClickable_value = getField(ChatClickable, "b");
try {
//1.14.4+
ChatBaseComponent_extra = getField(ChatBaseComponent, "siblings");
ChatModifier_color = getField(ChatModifier, "color");
ChatModifier_bold = getField(ChatModifier, "bold");
ChatModifier_italic = getField(ChatModifier, "italic");
ChatModifier_underlined = getField(ChatModifier, "underlined");
ChatModifier_strikethrough = getField(ChatModifier, "strikethrough");
ChatModifier_obfuscated = getField(ChatModifier, "obfuscated");
ChatModifier_clickEvent = getField(ChatModifier, "clickEvent");
ChatModifier_hoverEvent = getField(ChatModifier, "hoverEvent");
} catch (NoSuchFieldException e) {
//1.14.3-
ChatBaseComponent_extra = getField(ChatBaseComponent, "a");
ChatModifier_color = getField(ChatModifier, "b");
ChatModifier_bold = getField(ChatModifier, "c");
ChatModifier_italic = getField(ChatModifier, "d");
ChatModifier_underlined = getField(ChatModifier, "e");
ChatModifier_strikethrough = getField(ChatModifier, "f");
ChatModifier_obfuscated = getField(ChatModifier, "g");
ChatModifier_clickEvent = getField(ChatModifier, "h");
ChatModifier_hoverEvent = getField(ChatModifier, "i");
private void initializeFields() throws Exception {
PLAYER_CONNECTION = getFields(EntityPlayer, PlayerConnection).get(0);
PacketPlayOutScoreboardDisplayObjective_POSITION = getFields(PacketPlayOutScoreboardDisplayObjective, int.class).get(0);
PacketPlayOutScoreboardDisplayObjective_OBJECTIVENAME = getFields(PacketPlayOutScoreboardDisplayObjective, String.class).get(0);
PacketPlayOutScoreboardObjective_OBJECTIVENAME = getFields(PacketPlayOutScoreboardObjective, String.class).get(0);
List<Field> fields = getFields(PacketPlayOutScoreboardObjective, int.class);
PacketPlayOutScoreboardObjective_METHOD = fields.get(fields.size()-1);
PacketPlayOutScoreboardTeam_NAME = getFields(PacketPlayOutScoreboardTeam, String.class).get(0);
PacketPlayOutScoreboardTeam_PLAYERS = getFields(PacketPlayOutScoreboardTeam, Collection.class).get(0);
PacketPlayOutEntityTeleport_ENTITYID = getFields(PacketPlayOutEntityTeleport, int.class).get(0);
PacketPlayOutEntityTeleport_YAW = getFields(PacketPlayOutEntityTeleport, byte.class).get(0);
PacketPlayOutEntityTeleport_PITCH = getFields(PacketPlayOutEntityTeleport, byte.class).get(1);
PacketPlayOutEntity_ENTITYID = getFields(PacketPlayOutEntity, int.class).get(0);
PacketPlayOutEntityMetadata_LIST = getFields(PacketPlayOutEntityMetadata, List.class).get(0);
PacketPlayOutSpawnEntityLiving_ENTITYID = getFields(PacketPlayOutSpawnEntityLiving, int.class).get(0);
PacketPlayOutSpawnEntityLiving_ENTITYTYPE = getFields(PacketPlayOutSpawnEntityLiving, int.class).get(1);
PacketPlayOutSpawnEntityLiving_YAW = getFields(PacketPlayOutSpawnEntityLiving, byte.class).get(0);
PacketPlayOutSpawnEntityLiving_PITCH = getFields(PacketPlayOutSpawnEntityLiving, byte.class).get(0);
(PacketPlayOutEntityDestroy_ENTITIES = PacketPlayOutEntityDestroy.getDeclaredFields()[0]).setAccessible(true);
PacketPlayOutNamedEntitySpawn_ENTITYID = getFields(PacketPlayOutNamedEntitySpawn, int.class).get(0);
if (minorVersion >= 7) {
NETWORK_MANAGER = getFields(PlayerConnection, NetworkManager).get(0);
ChatBaseComponent_extra = getFields(ChatBaseComponent, List.class).get(0);
ChatBaseComponent_modifier = getFields(ChatBaseComponent, ChatModifier).get(0);
ChatComponentText_text = getFields(ChatComponentText, String.class).get(0);
ChatClickable_action = getFields(ChatClickable, EnumClickAction).get(0);
ChatClickable_value = getFields(ChatClickable, String.class).get(0);
ChatHoverable_action = getFields(ChatHoverable, EnumHoverAction).get(0);
List<Field> booleans = getFields(ChatModifier, Boolean.class);
ChatModifier_bold = booleans.get(0);
ChatModifier_italic = booleans.get(1);
ChatModifier_underlined = booleans.get(2);
ChatModifier_strikethrough = booleans.get(3);
ChatModifier_obfuscated = booleans.get(4);
ChatModifier_clickEvent = getFields(ChatModifier, ChatClickable).get(0);
ChatModifier_hoverEvent = getFields(ChatModifier, ChatHoverable).get(0);
PacketPlayInUseEntity_ENTITY = getFields(PacketPlayInUseEntity, int.class).get(0);
PacketPlayInUseEntity_ACTION = getFields(PacketPlayInUseEntity, EnumEntityUseAction).get(0);
}
PING = getField(getNMSClass("EntityPlayer"), "ping");
PLAYER_CONNECTION = getField(getNMSClass("EntityPlayer"), "playerConnection");
NETWORK_MANAGER = getField(PLAYER_CONNECTION.getType(), "networkManager");
PacketPlayOutChat_MESSAGE = getField(PacketPlayOutChat, "a");
PacketPlayOutScoreboardDisplayObjective_POSITION = getField(PacketPlayOutScoreboardDisplayObjective, "a");
PacketPlayOutScoreboardDisplayObjective_OBJECTIVENAME = getField(PacketPlayOutScoreboardDisplayObjective, "b");
PacketPlayOutScoreboardObjective_OBJECTIVENAME = getField(PacketPlayOutScoreboardObjective, "a");
PacketPlayOutScoreboardObjective_DISPLAYNAME = getField(PacketPlayOutScoreboardObjective, "b");
PacketPlayOutScoreboardScore_PLAYER = getField(PacketPlayOutScoreboardScore, "a");
PacketPlayOutScoreboardScore_OBJECTIVENAME = getField(PacketPlayOutScoreboardScore, "b");
PacketPlayOutScoreboardScore_SCORE = getField(PacketPlayOutScoreboardScore, "c");
PacketPlayOutScoreboardScore_ACTION = getField(PacketPlayOutScoreboardScore, "d");
PacketPlayOutScoreboardTeam_NAME = getField(PacketPlayOutScoreboardTeam, "a");
PacketPlayOutScoreboardTeam_DISPLAYNAME = getField(PacketPlayOutScoreboardTeam, "b");
PacketPlayOutScoreboardTeam_PREFIX = getField(PacketPlayOutScoreboardTeam, "c");
PacketPlayOutScoreboardTeam_SUFFIX = getField(PacketPlayOutScoreboardTeam, "d");
PacketPlayOutEntityTeleport_ENTITYID = getField(PacketPlayOutEntityTeleport, "a");
PacketPlayOutEntityTeleport_X = getField(PacketPlayOutEntityTeleport, "b");
PacketPlayOutEntityTeleport_Y = getField(PacketPlayOutEntityTeleport, "c");
PacketPlayOutEntityTeleport_Z = getField(PacketPlayOutEntityTeleport, "d");
PacketPlayOutEntityTeleport_YAW = getField(PacketPlayOutEntityTeleport, "e");
PacketPlayOutEntityTeleport_PITCH = getField(PacketPlayOutEntityTeleport, "f");
PacketPlayOutEntity_ENTITYID = getField(PacketPlayOutEntity, "a");
PacketPlayOutEntityMetadata_LIST = getField(PacketPlayOutEntityMetadata, "b");
PacketPlayOutSpawnEntityLiving_ENTITYID = getField(PacketPlayOutSpawnEntityLiving, "a");
PacketPlayInUseEntity_ENTITY = getField(PacketPlayInUseEntity, "a");
PacketPlayOutEntityDestroy_ENTITIES = getField(PacketPlayOutEntityDestroy, "a");
PacketPlayOutNamedEntitySpawn_ENTITYID = getField(PacketPlayOutNamedEntitySpawn, "a");
if (minorVersion >= 8) {
//1.8+
CHANNEL = getFields(getNMSClass("NetworkManager"), Channel.class).get(0);
PacketPlayOutChat_POSITION = getField(PacketPlayOutChat, "b");
PacketPlayOutScoreboardObjective_RENDERTYPE = getField(PacketPlayOutScoreboardObjective, "c");
PacketPlayOutScoreboardObjective_METHOD = getField(PacketPlayOutScoreboardObjective, "d");
GameProfile_ID = getField(GameProfile, "id");
GameProfile_NAME = getField(GameProfile, "name");
GameProfile_PROPERTIES = getField(GameProfile, "properties");
PacketPlayOutPlayerInfo_ACTION = getField(PacketPlayOutPlayerInfo, "a");
PacketPlayOutPlayerInfo_PLAYERS = getField(PacketPlayOutPlayerInfo, "b");
PlayerInfoData_PING = getField(PlayerInfoData, "b");
PlayerInfoData_GAMEMODE = getField(PlayerInfoData, "c");
PlayerInfoData_PROFILE = getField(PlayerInfoData, "d");
PlayerInfoData_LISTNAME = getField(PlayerInfoData, "e");
List<Field> fields = getFields(PacketPlayOutPlayerListHeaderFooter, IChatBaseComponent);
PacketPlayOutPlayerListHeaderFooter_HEADER = fields.get(0);
PacketPlayOutPlayerListHeaderFooter_FOOTER = fields.get(1);
} else {
//1.7-
PacketPlayOutScoreboardObjective_METHOD = getField(PacketPlayOutScoreboardObjective, "c");
CHANNEL = getFields(NetworkManager, Channel.class).get(0);
PacketPlayOutPlayerInfo_ACTION = getFields(PacketPlayOutPlayerInfo, EnumPlayerInfoAction).get(0);
PacketPlayOutPlayerInfo_PLAYERS = getFields(PacketPlayOutPlayerInfo, List.class).get(0);
PacketPlayOutPlayerListHeaderFooter_HEADER = getFields(PacketPlayOutPlayerListHeaderFooter, IChatBaseComponent).get(0);
PacketPlayOutPlayerListHeaderFooter_FOOTER = getFields(PacketPlayOutPlayerListHeaderFooter, IChatBaseComponent).get(1);
PacketPlayOutScoreboardObjective_RENDERTYPE = getFields(PacketPlayOutScoreboardObjective, EnumScoreboardHealthDisplay).get(0);
}
if (minorVersion >= 9) {
//1.9+
DataWatcherItem_TYPE = getField(DataWatcherItem, "a");
DataWatcherItem_VALUE = getField(DataWatcherItem, "b");
DataWatcherObject_SLOT = getField(DataWatcherObject, "a");
DataWatcherObject_SERIALIZER = getField(DataWatcherObject, "b");
PacketPlayOutBoss_UUID = getField(PacketPlayOutBoss, "a");
PacketPlayOutBoss_ACTION = getField(PacketPlayOutBoss, "b");
PacketPlayOutBoss_NAME = getField(PacketPlayOutBoss, "c");
PacketPlayOutBoss_PROGRESS = getField(PacketPlayOutBoss, "d");
PacketPlayOutBoss_COLOR = getField(PacketPlayOutBoss, "e");
PacketPlayOutBoss_STYLE = getField(PacketPlayOutBoss, "f");
PacketPlayOutBoss_DARKEN_SKY = getField(PacketPlayOutBoss, "g");
PacketPlayOutBoss_PLAY_MUSIC = getField(PacketPlayOutBoss, "h");
PacketPlayOutBoss_CREATE_FOG = getField(PacketPlayOutBoss, "i");
PacketPlayOutScoreboardTeam_VISIBILITY = getField(PacketPlayOutScoreboardTeam, "e");
PacketPlayOutScoreboardTeam_COLLISION = getField(PacketPlayOutScoreboardTeam, "f");
PacketPlayOutScoreboardTeam_PLAYERS = getField(PacketPlayOutScoreboardTeam, "h");
PacketPlayOutScoreboardTeam_ACTION = getField(PacketPlayOutScoreboardTeam, "i");
PacketPlayOutScoreboardTeam_SIGNATURE = getField(PacketPlayOutScoreboardTeam, "j");
PacketPlayOutSpawnEntityLiving_UUID = getField(PacketPlayOutSpawnEntityLiving, "b");
PacketPlayOutSpawnEntityLiving_ENTITYTYPE = getField(PacketPlayOutSpawnEntityLiving, "c");
PacketPlayOutSpawnEntityLiving_X = getField(PacketPlayOutSpawnEntityLiving, "d");
PacketPlayOutSpawnEntityLiving_Y = getField(PacketPlayOutSpawnEntityLiving, "e");
PacketPlayOutSpawnEntityLiving_Z = getField(PacketPlayOutSpawnEntityLiving, "f");
PacketPlayOutSpawnEntityLiving_YAW = getField(PacketPlayOutSpawnEntityLiving, "j");
PacketPlayOutSpawnEntityLiving_PITCH = getField(PacketPlayOutSpawnEntityLiving, "k");
PacketPlayInUseEntity_ACTION = getField(PacketPlayInUseEntity, "action");
DataWatcherItem_TYPE = getFields(DataWatcherItem, DataWatcherObject).get(0);
DataWatcherItem_VALUE = getFields(DataWatcherItem, Object.class).get(0);
DataWatcherObject_SLOT = getFields(DataWatcherObject, int.class).get(0);
DataWatcherObject_SERIALIZER = getFields(DataWatcherObject, DataWatcherSerializer).get(0);
PacketPlayOutEntityTeleport_X = getFields(PacketPlayOutEntityTeleport, double.class).get(0);
PacketPlayOutEntityTeleport_Y = getFields(PacketPlayOutEntityTeleport, double.class).get(1);
PacketPlayOutEntityTeleport_Z = getFields(PacketPlayOutEntityTeleport, double.class).get(2);
PacketPlayOutSpawnEntityLiving_UUID = getFields(PacketPlayOutSpawnEntityLiving, UUID.class).get(0);
PacketPlayOutSpawnEntityLiving_X = getFields(PacketPlayOutSpawnEntityLiving, double.class).get(0);
PacketPlayOutSpawnEntityLiving_Y = getFields(PacketPlayOutSpawnEntityLiving, double.class).get(1);
PacketPlayOutSpawnEntityLiving_Z = getFields(PacketPlayOutSpawnEntityLiving, double.class).get(2);
} else {
//1.8-
DataWatcherItem_TYPE = getField(DataWatcherItem, "b");
DataWatcherItem_VALUE = getField(DataWatcherItem, "c");
PacketPlayOutSpawnEntityLiving_ENTITYTYPE = getField(PacketPlayOutSpawnEntityLiving, "b");
PacketPlayOutSpawnEntityLiving_X = getField(PacketPlayOutSpawnEntityLiving, "c");
PacketPlayOutSpawnEntityLiving_Y = getField(PacketPlayOutSpawnEntityLiving, "d");
PacketPlayOutSpawnEntityLiving_Z = getField(PacketPlayOutSpawnEntityLiving, "e");
PacketPlayOutSpawnEntityLiving_YAW = getField(PacketPlayOutSpawnEntityLiving, "i");
PacketPlayOutSpawnEntityLiving_PITCH = getField(PacketPlayOutSpawnEntityLiving, "j");
if (minorVersion == 8) {
//1.8.x
PacketPlayOutScoreboardTeam_VISIBILITY = getField(PacketPlayOutScoreboardTeam, "e");
PacketPlayOutScoreboardTeam_PLAYERS = getField(PacketPlayOutScoreboardTeam, "g");
PacketPlayOutScoreboardTeam_ACTION = getField(PacketPlayOutScoreboardTeam, "h");
PacketPlayOutScoreboardTeam_SIGNATURE = getField(PacketPlayOutScoreboardTeam, "i");
} else {
//1.7.x
PacketPlayOutScoreboardTeam_PLAYERS = getField(PacketPlayOutScoreboardTeam, "e");
PacketPlayOutScoreboardTeam_ACTION = getField(PacketPlayOutScoreboardTeam, "f");
PacketPlayOutScoreboardTeam_SIGNATURE = getField(PacketPlayOutScoreboardTeam, "g");
}
DataWatcherItem_TYPE = getFields(DataWatcherItem, int.class).get(1);
DataWatcherItem_VALUE = getFields(DataWatcherItem, Object.class).get(0);
PacketPlayOutEntityTeleport_X = getFields(PacketPlayOutEntityTeleport, int.class).get(1);
PacketPlayOutEntityTeleport_Y = getFields(PacketPlayOutEntityTeleport, int.class).get(2);
PacketPlayOutEntityTeleport_Z = getFields(PacketPlayOutEntityTeleport, int.class).get(3);
PacketPlayOutSpawnEntityLiving_X = getFields(PacketPlayOutSpawnEntityLiving, int.class).get(2);
PacketPlayOutSpawnEntityLiving_Y = getFields(PacketPlayOutSpawnEntityLiving, int.class).get(3);
PacketPlayOutSpawnEntityLiving_Z = getFields(PacketPlayOutSpawnEntityLiving, int.class).get(4);
}
if (minorVersion >= 13) {
//1.13+
PacketPlayOutScoreboardTeam_CHATFORMAT = getField(PacketPlayOutScoreboardTeam, "g");
PacketPlayOutScoreboardObjective_DISPLAYNAME = getFields(PacketPlayOutScoreboardObjective, IChatBaseComponent).get(0);
} else {
PacketPlayOutScoreboardObjective_DISPLAYNAME = getFields(PacketPlayOutScoreboardObjective, String.class).get(1);
}
if (minorVersion <= 14) {
PacketPlayOutSpawnEntityLiving_DATAWATCHER = getFields(PacketPlayOutSpawnEntityLiving, DataWatcher).get(0);
}
if (minorVersion >= 16) {
//1.16+
ChatHexColor_name = getField(ChatHexColor, "name");
ChatHexColor_rgb = getField(ChatHexColor, "rgb");
ChatHoverable_action = getField(ChatHoverable, "b");
ChatHoverable_value = getField(ChatHoverable, "c");
PacketPlayOutChat_SENDER = getField(PacketPlayOutChat, "c");
fields = getFields(ChatHexColor, String.class);
ChatHexColor_name = fields.get(fields.size()-1);
ChatHexColor_rgb = getFields(ChatHexColor, int.class).get(0);
ChatHoverable_value = getFields(ChatHoverable, Object.class).get(0);
ChatModifier_color = getFields(ChatModifier, ChatHexColor).get(0);
} else if (minorVersion >= 7) {
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 {
ChatHoverable_action = getField(ChatHoverable, "a");
ChatHoverable_value = getField(ChatHoverable, "b");
PING = getField(EntityPlayer, "ping");
}
}
@@ -574,33 +504,50 @@ public class NMSStorage {
* Initializes required NMS methods
* @throws Exception - if something fails
*/
public void initializeMethods() throws Exception {
ChatComponentText_addSibling = getMethod(ChatComponentText, new String[]{"addSibling", "a", "func_150257_a"}, IChatBaseComponent); //v1.7.R4+, v1.7.R3-
ChatSerializer_DESERIALIZE = getMethod(ChatSerializer, new String[]{"a", "func_150699_a"}, String.class);
EnumClickAction_a = getMethod(EnumClickAction, new String[]{"a", "func_150672_a"}, String.class);
EnumHoverAction_a = getMethod(EnumHoverAction, new String[]{"a", "func_150684_a"}, String.class);
private void initializeMethods() throws Exception {
getHandle = Class.forName("org.bukkit.craftbukkit." + serverPackage + ".entity.CraftPlayer").getMethod("getHandle");
sendPacket = getMethod(getNMSClass("PlayerConnection"), new String[]{"sendPacket", "func_147359_a"}, getNMSClass("Packet"));
sendPacket = getMethod(PlayerConnection, new String[]{"sendPacket", "func_147359_a"}, Packet);
ScoreboardTeam_getPlayerNameSet = getMethod(ScoreboardTeam, new String[]{"getPlayerNameSet", "func_96670_d"});
ScoreboardScore_setScore = getMethod(ScoreboardScore, new String[]{"setScore", "func_96647_c"}, int.class);
if (minorVersion >= 7) {
ChatComponentText_addSibling = getMethod(ChatComponentText, new String[]{"addSibling", "a", "func_150257_a"}, IChatBaseComponent); //v1.7.R4+, v1.7.R3-
ChatSerializer_DESERIALIZE = getMethod(ChatSerializer, new String[]{"a", "func_150699_a"}, String.class);
EnumClickAction_a = getMethod(EnumClickAction, new String[]{"a", "func_150672_a"}, String.class);
EnumHoverAction_a = getMethod(EnumHoverAction, new String[]{"a", "func_150684_a"}, String.class);
}
if (minorVersion >= 8) {
getProfile = getNMSClass("EntityHuman").getMethod("getProfile");
for (Method m : PropertyMap.getMethods()) {
if (m.getName().equals("putAll") && m.getParameterCount() == 1) PropertyMap_putAll = m;
}
if (PropertyMap_putAll == null) throw new IllegalStateException("putAll method not found");
PlayerInfoData_getProfile = PlayerInfoData.getMethod("a");
PlayerInfoData_getLatency = PlayerInfoData.getMethod("b");
PlayerInfoData_getGamemode = PlayerInfoData.getMethod("c");
PlayerInfoData_getDisplayName = PlayerInfoData.getMethod("d");
ScoreboardTeam_setNameTagVisibility = getMethod(ScoreboardTeam, new String[]{"setNameTagVisibility", "a"}, EnumNameTagVisibility);
getProfile = EntityPlayer.getMethod("getProfile");
}
if (minorVersion >= 9) {
//1.9+
ScoreboardTeam_setCollisionRule = ScoreboardTeam.getMethod("setCollisionRule", EnumTeamPush);
DataWatcher_REGISTER = DataWatcher.getMethod("register", DataWatcherObject, Object.class);
} else {
//1.7.x - 1.8.x
DataWatcher_REGISTER = getMethod(DataWatcher, new String[]{"a", "func_75682_a"}, int.class, Object.class);
}
if (minorVersion >= 13) {
ScoreboardTeam_setPrefix = ScoreboardTeam.getMethod("setPrefix", IChatBaseComponent);
ScoreboardTeam_setSuffix = ScoreboardTeam.getMethod("setSuffix", IChatBaseComponent);
ScoreboardTeam_setColor = ScoreboardTeam.getMethod("setColor", EnumChatFormat);
} else {
ScoreboardTeam_setPrefix = getMethod(ScoreboardTeam, new String[]{"setPrefix", "func_96666_b"}, String.class);
ScoreboardTeam_setSuffix = getMethod(ScoreboardTeam, new String[]{"setSuffix", "func_96662_c"}, String.class);
}
if (minorVersion >= 16) {
ChatHexColor_ofInt = ChatHexColor.getMethod("a", int.class);
ChatHexColor_ofString = ChatHexColor.getMethod("a", String.class);
}
if (minorVersion >= 17) {
PacketPlayOutScoreboardTeam_of = PacketPlayOutScoreboardTeam.getMethod("a", ScoreboardTeam);
PacketPlayOutScoreboardTeam_ofBoolean = PacketPlayOutScoreboardTeam.getMethod("a", ScoreboardTeam, boolean.class);
PacketPlayOutScoreboardTeam_ofString = PacketPlayOutScoreboardTeam.getMethod("a", ScoreboardTeam, String.class, PacketPlayOutScoreboardTeam_a);
}
}
/**
* A helper method that prints all methods of class into console, including their return type, name and parameters
* Useful for modded servers which code I can not access
@@ -626,27 +573,31 @@ public class NMSStorage {
} catch (ClassNotFoundException e) {
}
}
throw new ClassNotFoundException("No class found with possible names " + names);
throw new ClassNotFoundException("No class found with possible names " + Arrays.toString(names));
}
/**
* Returns class from given name
* @param name - class name
* @return class from given name
* @throws ClassNotFoundException if class was not found
*/
public Class<?> getNMSClass(String name) throws ClassNotFoundException {
try {
return Class.forName("net.minecraft.server." + serverPackage + "." + name);
} catch (ClassNotFoundException e) {
//modded server?
return Main.class.getClassLoader().loadClass("net.minecraft.server." + serverPackage + "." + name);
} catch (NullPointerException e) {
//nested class in modded server
throw new ClassNotFoundException(name);
private Class<?> getNMSClass(String name) throws ClassNotFoundException {
if (minorVersion >= 17) {
return Class.forName(name);
} else {
try {
return Class.forName("net.minecraft.server." + serverPackage + "." + name);
} catch (ClassNotFoundException e) {
//modded server?
return Main.class.getClassLoader().loadClass("net.minecraft.server." + serverPackage + "." + name);
} catch (NullPointerException e) {
//nested class in modded server
throw new ClassNotFoundException(name);
}
}
}
/**
* Returns method with specified possible names and parameters. Throws exception if no such method was found
* @param clazz - class to get method from
@@ -655,7 +606,7 @@ public class NMSStorage {
* @return method with specified name and parameters
* @throws NoSuchMethodException if no such method exists
*/
public Method getMethod(Class<?> clazz, String[] names, Class<?>... parameterTypes) throws NoSuchMethodException {
private Method getMethod(Class<?> clazz, String[] names, Class<?>... parameterTypes) throws NoSuchMethodException {
for (String name : names) {
try {
return clazz.getMethod(name, parameterTypes);
@@ -671,16 +622,16 @@ public class NMSStorage {
* @param type - field type to check for
* @return list of all fields with specified class type
*/
private List<Field> getFields(Class<?> clazz, Class<?> type){
public List<Field> getFields(Class<?> clazz, Class<?> type){
if (clazz == null) throw new IllegalArgumentException("Source class cannot be null");
List<Field> list = new ArrayList<Field>();
if (clazz == null) return list;
for (Field field : clazz.getDeclaredFields()) {
field.setAccessible(true);
if (field.getType() == type) list.add(field);
}
return list;
}
/**
* Returns field with specified name and makes it accessible
* @param clazz - class to get field from
@@ -695,12 +646,12 @@ public class NMSStorage {
return f;
}
}
if (thermosFieldMappings.containsKey(name)) {
return getField(clazz, thermosFieldMappings.get(name));
if (name.equals("ping")){
return getField(clazz, "field_71138_i"); //thermos
}
throw new NoSuchFieldException("Field \"" + name + "\" was not found in class " + clazz.getName());
}
private Constructor<?> getConstructor(Class<?> clazz, int parameterCount) throws NoSuchMethodException {
for (Constructor<?> c : clazz.getDeclaredConstructors()) {
if (c.getParameterCount() == parameterCount) {
@@ -5,7 +5,6 @@ import java.util.List;
import java.util.Map;
import me.neznamy.tab.platforms.bukkit.nms.NMSStorage;
import me.neznamy.tab.shared.ProtocolVersion;
/**
* A class representing the n.m.s.DataWatcher class to make work with it much easier
@@ -59,10 +58,15 @@ public class DataWatcher {
*/
public Object toNMS() throws Exception {
NMSStorage nms = NMSStorage.getInstance();
Object nmsWatcher = nms.newDataWatcher.newInstance(new Object[] {null});
Object nmsWatcher;
if (nms.newDataWatcher.getParameterCount() == 1) {
nmsWatcher = nms.newDataWatcher.newInstance(new Object[] {null});
} else {
nmsWatcher = nms.newDataWatcher.newInstance();
}
for (DataWatcherItem item : dataValues.values()) {
Object position;
if (ProtocolVersion.SERVER_VERSION.getMinorVersion() >= 9) {
if (nms.minorVersion >= 9) {
position = nms.newDataWatcherObject.newInstance(item.type.position, item.type.classType);
} else {
position = item.type.position;
@@ -36,13 +36,16 @@ public class DataWatcherHelper {
* @return armor stand flags position based on server version
*/
private int getArmorStandFlagsPosition() {
if (ProtocolVersion.SERVER_VERSION.getMinorVersion() >= 15) {
if (NMSStorage.getInstance().minorVersion >= 17) {
//1.17.x
return 15;
} else if (NMSStorage.getInstance().minorVersion >= 15) {
//1.15.x, 1.16.x
return 14;
} else if (ProtocolVersion.SERVER_VERSION.getMinorVersion() >= 14) {
} else if (NMSStorage.getInstance().minorVersion >= 14) {
//1.14.x
return 13;
} else if (ProtocolVersion.SERVER_VERSION.getMinorVersion() >= 10) {
} else if (NMSStorage.getInstance().minorVersion >= 10) {
//1.10.x - 1.13.x
return 11;
} else {
@@ -65,17 +68,22 @@ public class DataWatcherHelper {
* @param clientVersion - client version
*/
public void setCustomName(String customName, ProtocolVersion clientVersion) {
if (ProtocolVersion.SERVER_VERSION.getMinorVersion() >= 13) {
if (NMSStorage.getInstance().minorVersion >= 13) {
try {
data.setValue(new DataWatcherObject(2, registry.Optional_IChatBaseComponent), Optional.ofNullable(((BukkitPacketBuilder)TAB.getInstance().getPacketBuilder()).toNMSComponent(IChatBaseComponent.optimizedComponent(customName), clientVersion)));
} catch (Exception e) {
TAB.getInstance().getErrorManager().printError("Failed to create component", e);
}
} else if (ProtocolVersion.SERVER_VERSION.getMinorVersion() >= 8){
} else if (NMSStorage.getInstance().minorVersion >= 8){
data.setValue(new DataWatcherObject(2, registry.String), customName);
} else {
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 {
data.setValue(new DataWatcherObject(5, registry.String), cutName);
}
}
}
@@ -85,7 +93,7 @@ public class DataWatcherHelper {
* @param visible - if visible or not
*/
public void setCustomNameVisible(boolean visible) {
if (ProtocolVersion.SERVER_VERSION.getMinorVersion() >= 9) {
if (NMSStorage.getInstance().minorVersion >= 9) {
data.setValue(new DataWatcherObject(3, registry.Boolean), visible);
} else {
data.setValue(new DataWatcherObject(3, registry.Byte), (byte)(visible?1:0));
@@ -97,7 +105,11 @@ public class DataWatcherHelper {
* @param health - health of entity
*/
public void setHealth(float health) {
data.setValue(new DataWatcherObject(6, registry.Float), health);
if (NMSStorage.getInstance().minorVersion >= 6) {
data.setValue(new DataWatcherObject(6, registry.Float), health);
} else {
data.setValue(new DataWatcherObject(16, registry.Integer), (int)health);
}
}
/**
@@ -1,7 +1,6 @@
package me.neznamy.tab.platforms.bukkit.nms.datawatcher;
import me.neznamy.tab.platforms.bukkit.nms.NMSStorage;
import me.neznamy.tab.shared.ProtocolVersion;
public class DataWatcherItem {
@@ -29,7 +28,7 @@ public class DataWatcherItem {
*/
public static DataWatcherItem fromNMS(Object nmsItem) throws Exception {
NMSStorage nms = NMSStorage.getInstance();
if (ProtocolVersion.SERVER_VERSION.getMinorVersion() >= 9) {
if (NMSStorage.getInstance().minorVersion >= 9) {
Object nmsObject = nms.DataWatcherItem_TYPE.get(nmsItem);
return new DataWatcherItem(new DataWatcherObject(nms.DataWatcherObject_SLOT.getInt(nmsObject), nms.DataWatcherObject_SERIALIZER.get(nmsObject)), nms.DataWatcherItem_VALUE.get(nmsItem));
} else {
@@ -5,7 +5,7 @@ import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
import me.neznamy.tab.shared.ProtocolVersion;
import me.neznamy.tab.platforms.bukkit.nms.NMSStorage;
/**
* A class representing the n.m.s.DataWatcherRegistry class to make work with it much easier
@@ -23,24 +23,19 @@ public class DataWatcherRegistry {
/**
* Initializes required NMS classes and fields
*/
public DataWatcherRegistry(Class<?> registry) {
if (ProtocolVersion.SERVER_VERSION.getMinorVersion() >= 9) {
public DataWatcherRegistry(NMSStorage nms, Class<?> registry) {
if (nms.minorVersion >= 9) {
Map<String, Object> fields = getStaticFields(registry);
Byte = fields.get("a");
Integer = fields.get("b");
Float = fields.get("c");
String = fields.get("d");
if (ProtocolVersion.SERVER_VERSION.getMinorVersion() >= 13) {
if (nms.minorVersion >= 13) {
Optional_IChatBaseComponent = fields.get("f");
Boolean = fields.get("i");
} else {
Boolean = fields.get("h");
}
} else {
Byte = 0;
Integer = 2;
Float = 3;
String = 4;
}
}
+1 -4
View File
@@ -27,7 +27,6 @@ footer:
#supports any numeric placeholder, set to "" to disable the feature
yellow-number-in-tablist: "%ping%"
#literally what it says
group-sorting-priority-list:
- owner
- admin
@@ -97,8 +96,7 @@ do-not-move-spectators: false
#allows players with tab.spectatorbypass permission to see spectators moved despite the option above enabled
allow-spectator-bypass-permission: false
#using armor stands for nametags, bypassing all limits
#THEY ARE CLIENT SIDED AND DO NOT EXIST ON SERVER SO STOP SAYING YOUR SERVER IS LAGGING FROM THIS
#using armor stands for nametags, bypassing all limits (they are not on server sided & asynchronous - no TPS loss)
unlimited-nametag-prefix-suffix-mode:
#enabling the feature
@@ -218,7 +216,6 @@ per-world-playerlist:
sort-players-by-permissions: false
#making tamed animals no longer copy nametag properties from their owner (prefix/suffix/visibility)
#do not enable this if you're on paper, you'll feed the trolls even more
fix-pet-names: false
#taking primary group from permission plugin
+1 -1
View File
@@ -3,7 +3,7 @@ version: ${project.parent.version}
author: NEZNAMY
main: me.neznamy.tab.platforms.bukkit.Main
api-version: 1.13
softdepend: [PlaceholderAPI, Vault, UltraPermissions, LuckPerms, Essentials, LibsDisguises]
softdepend: [PlaceholderAPI, Vault, UltraPermissions, LuckPerms, Essentials, LibsDisguises, ProtocolSupport]
website: "https://www.spigotmc.org/resources/57806/"
description: ${project.parent.description}
commands:
+4 -32
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>me.neznamy</groupId>
<artifactId>TAB</artifactId>
<version>2.8.11-pre16</version>
<version>2.9.0</version>
</parent>
<artifactId>bungeecord</artifactId>
@@ -34,37 +34,13 @@
<version>${project.version}</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>com.google.j2objc</groupId>
<artifactId>j2objc-annotations</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
</exclusion>
<exclusion>
<groupId>com.github.NEZNAMY</groupId>
<artifactId>YamlAssist</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.errorprone</groupId>
<artifactId>error_prone_annotations</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>listenablefuture</artifactId>
</exclusion>
<exclusion>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>failureaccess</artifactId>
</exclusion>
<exclusion>
<groupId>org.checkerframework</groupId>
<artifactId>checker-qual</artifactId>
<groupId>com.github.NEZNAMY</groupId>
<artifactId>YamlAssist</artifactId>
</exclusion>
</exclusions>
</dependency>
@@ -73,7 +49,7 @@
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-proxy</artifactId>
<version>1.16-R0.5-SNAPSHOT</version>
<version>1.17-R0.1-SNAPSHOT</version>
<scope>provided</scope>
<exclusions>
<exclusion>
@@ -136,10 +112,6 @@
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.maven</groupId>
<artifactId>maven-resolver-provider</artifactId>
@@ -19,18 +19,16 @@ import me.neznamy.tab.shared.packets.PacketPlayOutScoreboardObjective;
import me.neznamy.tab.shared.packets.PacketPlayOutScoreboardObjective.EnumScoreboardHealthDisplay;
import me.neznamy.tab.shared.packets.PacketPlayOutScoreboardScore;
import me.neznamy.tab.shared.packets.PacketPlayOutScoreboardTeam;
import me.neznamy.tab.shared.packets.PacketPlayOutTitle;
import net.md_5.bungee.protocol.packet.BossBar;
import net.md_5.bungee.protocol.packet.Chat;
import net.md_5.bungee.protocol.packet.PlayerListHeaderFooter;
import net.md_5.bungee.protocol.packet.PlayerListItem;
import net.md_5.bungee.protocol.packet.PlayerListItem.Item;
import net.md_5.bungee.protocol.packet.ScoreboardDisplay;
import net.md_5.bungee.protocol.packet.ScoreboardObjective;
import net.md_5.bungee.protocol.packet.ScoreboardObjective.HealthDisplay;
import net.md_5.bungee.protocol.packet.ScoreboardScore;
import net.md_5.bungee.protocol.packet.Team;
import net.md_5.bungee.protocol.packet.Title;
import net.md_5.bungee.protocol.packet.PlayerListItem.Item;
/**
* Packet builder for BungeeCord platform
@@ -116,18 +114,7 @@ public class BungeePacketBuilder implements PacketBuilder {
}
@Override
public Object build(PacketPlayOutTitle packet, ProtocolVersion clientVersion) throws Exception {
Title bungeePacket = new Title();
bungeePacket.setAction(Title.Action.valueOf(packet.action.toString()));
if (packet.text != null) bungeePacket.setText(IChatBaseComponent.optimizedComponent(packet.text).toString(clientVersion));
bungeePacket.setFadeIn(packet.fadeIn);
bungeePacket.setStay(packet.stay);
bungeePacket.setFadeOut(packet.fadeOut);
return bungeePacket;
}
@Override
public PacketPlayOutPlayerInfo readPlayerInfo(Object bungeePacket, ProtocolVersion clientVersion){
public PacketPlayOutPlayerInfo readPlayerInfo(Object bungeePacket, ProtocolVersion clientVersion) {
PlayerListItem item = (PlayerListItem) bungeePacket;
List<PlayerInfoData> listData = new ArrayList<PlayerInfoData>();
for (Item i : item.getItems()) {
@@ -137,7 +124,7 @@ public class BungeePacketBuilder implements PacketBuilder {
}
@Override
public PacketPlayOutScoreboardObjective readObjective(Object bungeePacket, ProtocolVersion clientVersion) throws Exception {
public PacketPlayOutScoreboardObjective readObjective(Object bungeePacket, ProtocolVersion clientVersion) {
ScoreboardObjective packet = (ScoreboardObjective) bungeePacket;
String title;
if (clientVersion.getMinorVersion() >= 13) {
@@ -150,7 +137,7 @@ public class BungeePacketBuilder implements PacketBuilder {
}
@Override
public PacketPlayOutScoreboardDisplayObjective readDisplayObjective(Object bungeePacket, ProtocolVersion clientVersion) throws Exception {
public PacketPlayOutScoreboardDisplayObjective readDisplayObjective(Object bungeePacket, ProtocolVersion clientVersion){
return new PacketPlayOutScoreboardDisplayObjective(((ScoreboardDisplay) bungeePacket).getPosition(), ((ScoreboardDisplay) bungeePacket).getName());
}
}
@@ -58,16 +58,15 @@ public class BungeePipelineInjector extends PipelineInjector {
private void modifyPlayers(Team packet){
long time = System.nanoTime();
if (packet.getPlayers() == null) return;
if (packet.getFriendlyFire() != 69) {
Collection<String> col = Lists.newArrayList(packet.getPlayers());
for (TabPlayer p : tab.getPlayers()) {
if (col.contains(p.getName()) && !tab.getFeatureManager().getNameTagFeature().isDisabledWorld(p.getWorldName())) {
logTeamOverride(packet.getName(), p.getName());
col.remove(p.getName());
}
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())) {
logTeamOverride(packet.getName(), p.getName());
col.remove(p.getName());
}
packet.setPlayers(col.toArray(new String[0]));
}
packet.setPlayers(col.toArray(new String[0]));
tab.getCPUManager().addTime(TabFeature.NAMETAGS, UsageType.ANTI_OVERRIDE, System.nanoTime()-time);
}
@@ -94,47 +93,45 @@ public class BungeePipelineInjector extends PipelineInjector {
super.write(context, tab.getFeatureManager().onPacketPlayOutPlayerInfo(player, packet), 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) {
if (packet instanceof Team) {
//team packet coming from a bungeecord plugin
modifyPlayers((Team) packet);
super.write(context, packet, channelPromise);
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;
}
if (packet instanceof ByteBuf) {
long time = System.nanoTime();
ByteBuf buf = ((ByteBuf) packet);
//for now protocolsupport will break the plugin
/* if (modifiedPacket instanceof ByteBuf) {
ByteBuf buf = ((ByteBuf) modifiedPacket);
int marker = buf.readerIndex();
int packetId = buf.readByte();
if (packetId == ((BungeeTabPlayer)player).getPacketId(Team.class)) {
//team packet sent by backend server, proxy does not deserialize those for whatever reason
Team team = new Team();
team.read(buf, null, ((ProxiedPlayer)player.getPlayer()).getPendingConnection().getVersion());
if (packetId + 128 == ((BungeeTabPlayer)player).getPacketId(Team.class)){
//compressed team packet when using protocolsupport, proper decompression will be needed
buf.release();
tab.getCPUManager().addTime(TabFeature.NAMETAGS, UsageType.ANTI_OVERRIDE, System.nanoTime()-time);
modifyPlayers(team);
super.write(context, team, channelPromise);
return;
} else if (packetId + 128 == ((BungeeTabPlayer)player).getPacketId(Team.class)){
//compressed team packet when using protocolsupport, just kill it as it does not come from tab anyway
buf.release();
return;
}
buf.readerIndex(marker);
}
}*/
tab.getCPUManager().addTime(TabFeature.NAMETAGS, UsageType.ANTI_OVERRIDE, System.nanoTime()-time);
}
if (packet instanceof ScoreboardDisplay && antiOverrideObjectives && tab.getFeatureManager().onDisplayObjective(player, packet)) {
//TODO add support for serialized packets as above with teams
if (modifiedPacket instanceof ScoreboardDisplay && antiOverrideObjectives && tab.getFeatureManager().onDisplayObjective(player, modifiedPacket)) {
return;
}
if (packet instanceof ScoreboardObjective && antiOverrideObjectives) {
//TODO add support for serialized packets as above with teams
tab.getFeatureManager().onObjective(player, packet);
if (modifiedPacket instanceof ScoreboardObjective && antiOverrideObjectives) {
tab.getFeatureManager().onObjective(player, modifiedPacket);
}
//client reset packet
if (packet instanceof Login) {
if (modifiedPacket instanceof Login) {
//making sure to not send own packets before login packet is actually sent
super.write(context, packet, channelPromise);
super.write(context, modifiedPacket, channelPromise);
tab.getFeatureManager().onLoginPacket(player);
return;
}
@@ -143,5 +140,36 @@ public class BungeePipelineInjector extends PipelineInjector {
}
super.write(context, packet, channelPromise);
}
/**
* Deserializes bytebuf in case it is one of the tracked packets coming from backend server and returns it.
* If the packet is not one of them, returns input
* @param buf - bytebuf to deserialize
* @return deserialized packet or input bytebuf if packet is not tracked
*/
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;
}
buf.readerIndex(marker);
return buf;
}
}
}
@@ -4,7 +4,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
import de.myzelyam.api.vanish.BungeeVanishAPI;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.placeholders.Placeholder;
@@ -23,22 +22,24 @@ public class BungeePlaceholderRegistry implements PlaceholderRegistry {
@Override
public List<Placeholder> registerPlaceholders() {
List<Placeholder> placeholders = new ArrayList<Placeholder>();
if (ProxyServer.getInstance().getPluginManager().getPlugin("PremiumVanish") != null) {
placeholders.add(new ServerPlaceholder("%canseeonline%", 1000) {
public String get() {
return String.valueOf(TAB.getInstance().getPlayers().size() - BungeeVanishAPI.getInvisiblePlayers().size());
placeholders.add(new PlayerPlaceholder("%canseeonline%", 2000) {
public String get(TabPlayer p) {
int var = 0;
for (TabPlayer all : TAB.getInstance().getPlayers()){
if (!all.isVanished() || p.hasPermission("tab.seevanished")) var++;
}
});
placeholders.add(new ServerPlaceholder("%canseestaffonline%", 1000) {
public String get() {
int count = 0;
for (TabPlayer all : TAB.getInstance().getPlayers()) {
if (!((BungeeTabPlayer)all).isVanished() && all.isStaff()) count++;
}
return String.valueOf(count);
return String.valueOf(var);
}
});
placeholders.add(new PlayerPlaceholder("%canseestaffonline%", 2000) {
public String get(TabPlayer p) {
int var = 0;
for (TabPlayer all : TAB.getInstance().getPlayers()){
if (all.isStaff() && (!all.isVanished() || p.hasPermission("tab.seevanished"))) var++;
}
});
}
return String.valueOf(var);
}
});
placeholders.add(new PlayerPlaceholder("%displayname%", 500) {
public String get(TabPlayer p) {
return ((ProxiedPlayer) p.getPlayer()).getDisplayName();
@@ -6,9 +6,14 @@ import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.api.event.BungeeTABLoadEvent;
import me.neznamy.tab.shared.Platform;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.features.BelowName;
import me.neznamy.tab.shared.features.GlobalPlayerlist;
import me.neznamy.tab.shared.features.NameTag;
import me.neznamy.tab.shared.features.PingSpoof;
import me.neznamy.tab.shared.features.PlaceholderManager;
import me.neznamy.tab.shared.features.SpectatorFix;
import me.neznamy.tab.shared.features.TabObjective;
import me.neznamy.tab.shared.features.scoreboard.ScoreboardManager;
import me.neznamy.tab.shared.permission.LuckPerms;
import me.neznamy.tab.shared.permission.PermissionPlugin;
import me.neznamy.tab.shared.permission.UltraPermissions;
@@ -37,7 +42,9 @@ public class BungeePlatform implements Platform {
@Override
public PermissionPlugin detectPermissionPlugin() {
if (ProxyServer.getInstance().getPluginManager().getPlugin("LuckPerms") != null) {
if (TAB.getInstance().getConfiguration().bukkitPermissions) {
return new VaultBridge(Main.plm);
} else if (ProxyServer.getInstance().getPluginManager().getPlugin("LuckPerms") != null) {
return new LuckPerms(ProxyServer.getInstance().getPluginManager().getPlugin("LuckPerms").getDescription().getVersion());
} else if (ProxyServer.getInstance().getPluginManager().getPlugin("UltraPermissions") != null) {
return new UltraPermissions(ProxyServer.getInstance().getPluginManager().getPlugin("UltraPermissions").getDescription().getVersion());
@@ -55,6 +62,11 @@ public class BungeePlatform implements Platform {
if (tab.getConfiguration().pipelineInjection) tab.getFeatureManager().registerFeature("injection", new BungeePipelineInjector(tab));
if (tab.getConfiguration().config.getBoolean("change-nametag-prefix-suffix", true)) tab.getFeatureManager().registerFeature("nametag16", new NameTag(tab));
loadUniversalFeatures();
if (tab.getConfiguration().config.getBoolean("ping-spoof.enabled", false)) tab.getFeatureManager().registerFeature("pingspoof", new PingSpoof());
if (tab.getConfiguration().config.getString("yellow-number-in-tablist", "%ping%").length() > 0) tab.getFeatureManager().registerFeature("tabobjective", new TabObjective(tab));
if (tab.getConfiguration().config.getBoolean("do-not-move-spectators", false)) tab.getFeatureManager().registerFeature("spectatorfix", new SpectatorFix());
if (tab.getConfiguration().config.getBoolean("classic-vanilla-belowname.enabled", true)) tab.getFeatureManager().registerFeature("belowname", new BelowName(tab));
if (tab.getConfiguration().premiumconfig != null && tab.getConfiguration().premiumconfig.getBoolean("scoreboard.enabled", false)) tab.getFeatureManager().registerFeature("scoreboard", new ScoreboardManager(tab));
if (tab.getConfiguration().config.getBoolean("global-playerlist.enabled", false)) tab.getFeatureManager().registerFeature("globalplayerlist", new GlobalPlayerlist(tab));
for (ProxiedPlayer p : ProxyServer.getInstance().getPlayers()) {
tab.addPlayer(new BungeeTabPlayer(p));
@@ -112,4 +124,9 @@ public class BungeePlatform implements Platform {
public int getMaxPlayers() {
return ProxyServer.getInstance().getConfigurationAdapter().getListeners().iterator().next().getMaxPlayers();
}
@Override
public String getConfigName() {
return "bungeeconfig.yml";
}
}
@@ -7,6 +7,7 @@ import de.myzelyam.api.vanish.BungeeVanishAPI;
import me.neznamy.tab.shared.ITabPlayer;
import me.neznamy.tab.shared.ProtocolVersion;
import me.neznamy.tab.shared.TAB;
import net.md_5.bungee.UserConnection;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.connection.InitialHandler;
@@ -64,6 +65,12 @@ public class BungeeTabPlayer extends ITabPlayer {
@Override
public boolean hasPermission(String permission) {
if (TAB.getInstance().getConfiguration().bukkitPermissions) {
String merge = "hasPermission:" + permission;
Main.plm.requestAttribute(this, merge);
if (!attributes.containsKey(merge)) return false;
return Boolean.parseBoolean(attributes.get(merge));
}
return player.hasPermission(permission);
}
@@ -97,7 +104,7 @@ public class BungeeTabPlayer extends ITabPlayer {
}
/**
* Returns packet ID for this packet of provided packet class
* Returns packet ID for this player of provided packet class
* @param clazz - packet class
* @return - packet ID
*/
@@ -117,7 +124,10 @@ public class BungeeTabPlayer extends ITabPlayer {
@Override
public boolean isVanished() {
return ProxyServer.getInstance().getPluginManager().getPlugin("PremiumVanish") != null && BungeeVanishAPI.isInvisible(player);
if (ProxyServer.getInstance().getPluginManager().getPlugin("PremiumVanish") != null && BungeeVanishAPI.isInvisible(player)) return true;
Main.plm.requestAttribute(this, "vanished");
if (!attributes.containsKey("vanished")) return false;
return Boolean.parseBoolean(attributes.get("vanished"));
}
@Override
@@ -138,4 +148,9 @@ public class BungeeTabPlayer extends ITabPlayer {
public boolean isOnline() {
return player.isConnected();
}
@Override
public int getGamemode() {
return ((UserConnection)player).getGamemode();
}
}
@@ -5,6 +5,7 @@ import java.util.ArrayList;
import org.bstats.bungeecord.Metrics;
import org.bstats.charts.SimplePie;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.ProtocolVersion;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.features.PluginMessageHandler;
@@ -81,14 +82,23 @@ public class Main extends Plugin {
sender.sendMessage(message.replace('&', '\u00a7'));
}
} else {
TAB.getInstance().command.execute(sender instanceof ProxiedPlayer ? TAB.getInstance().getPlayer(((ProxiedPlayer)sender).getUniqueId()) : null, args);
TabPlayer p = null;
if (sender instanceof ProxiedPlayer) {
p = TAB.getInstance().getPlayer(((ProxiedPlayer)sender).getUniqueId());
if (p == null) return; //player not loaded correctly
}
TAB.getInstance().command.execute(p, args);
}
}
@Override
public Iterable<String> onTabComplete(CommandSender sender, String[] args) {
if (TAB.getInstance().isDisabled()) return new ArrayList<String>();
return TAB.getInstance().command.complete(sender instanceof ProxiedPlayer ? TAB.getInstance().getPlayer(((ProxiedPlayer)sender).getUniqueId()) : null, args);
TabPlayer p = null;
if (sender instanceof ProxiedPlayer) {
p = TAB.getInstance().getPlayer(((ProxiedPlayer)sender).getUniqueId());
if (p == null) return new ArrayList<String>(); //player not loaded correctly
}
return TAB.getInstance().command.complete(p, args);
}
}
}
@@ -28,7 +28,7 @@ public class PremiumVanishListener implements Listener {
if (list == null) return;
TabPlayer vanished = TAB.getInstance().getPlayer(e.getPlayer().getUniqueId());
for (TabPlayer all : TAB.getInstance().getPlayers()) {
boolean perm = all.hasPermission(list.PREMIUMVANISH_SEE_VANISHED_PERMISSION);
boolean perm = all.hasPermission("tab.seevanished");
if (all == vanished || perm) {
if (perm && list.vanishedAsSpectators) {
all.sendCustomPacket(new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.UPDATE_GAME_MODE, new PlayerInfoData(vanished.getUniqueId(), EnumGamemode.SPECTATOR)), TabFeature.GLOBAL_PLAYERLIST);
@@ -1,5 +1,8 @@
# Detailed explanation of all options available at https://github.com/NEZNAMY/TAB/wiki/config.yml
#taking permission nodes and groups from backend servers
use-bukkit-permissions-manager: false
#changing nametags, affecting sorting, collision rule
change-nametag-prefix-suffix: true
@@ -43,7 +46,6 @@ footer:
#supports any numeric placeholder, set to "" to disable the feature
yellow-number-in-tablist: "%ping%"
#literally what it says
group-sorting-priority-list:
- owner
- admin
@@ -97,9 +99,9 @@ classic-vanilla-belowname:
#controlling the collision rule
enable-collision: true
#using the opposite of the setting above for worlds
revert-collision-rule-in-worlds:
- revertedworld
#using the opposite of the setting above for servers
revert-collision-rule-in-servers:
- revertedserver
#preventing players with spectator gamemode from being moved to the bottom of tablist with transparent name
do-not-move-spectators: false
+1 -5
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>me.neznamy</groupId>
<artifactId>TAB</artifactId>
<version>2.8.11-pre16</version>
<version>2.9.0</version>
</parent>
<artifactId>jar</artifactId>
<build>
@@ -85,10 +85,6 @@
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</exclusion>
<exclusion>
<groupId>com.github.NEZNAMY</groupId>
<artifactId>VelocityInternals</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
+1 -1
View File
@@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>me.neznamy</groupId>
<artifactId>TAB</artifactId>
<version>2.8.11-pre16</version>
<version>2.9.0</version>
<packaging>pom</packaging>
<description>An all-in-one solution that works</description>
<modules>
+9 -124
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>me.neznamy</groupId>
<artifactId>TAB</artifactId>
<version>2.8.11-pre16</version>
<version>2.9.0</version>
</parent>
<artifactId>shared</artifactId>
@@ -31,39 +31,6 @@
</repositories>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>30.1.1-jre</version>
<exclusions>
<exclusion>
<groupId>com.google.j2objc</groupId>
<artifactId>j2objc-annotations</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.errorprone</groupId>
<artifactId>error_prone_annotations</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>listenablefuture</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>failureaccess</artifactId>
</exclusion>
<exclusion>
<groupId>org.checkerframework</groupId>
<artifactId>checker-qual</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
@@ -80,10 +47,6 @@
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
<exclusion>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-chat</artifactId>
@@ -97,97 +60,19 @@
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-proxy</artifactId>
<version>1.16-R0.5-SNAPSHOT</version>
<artifactId>bungeecord-api</artifactId>
<version>1.17-R0.1-SNAPSHOT</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>netty-codec-haproxy</artifactId>
</exclusion>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>netty-codec-http</artifactId>
</exclusion>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>netty-handler</artifactId>
</exclusion>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-epoll</artifactId>
</exclusion>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-unix-common</artifactId>
</exclusion>
<exclusion>
<groupId>net.md-5</groupId>
<artifactId>brigadier</artifactId>
</exclusion>
<exclusion>
<groupId>jline</groupId>
<artifactId>jline</artifactId>
</exclusion>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>netty-transport</artifactId>
</exclusion>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>netty-codec</artifactId>
</exclusion>
<exclusion>
<groupId>net.sf.trove4j</groupId>
<artifactId>core</artifactId>
</exclusion>
<exclusion>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-query</artifactId>
</exclusion>
<exclusion>
<groupId>se.llbit</groupId>
<artifactId>jo-nbt</artifactId>
</exclusion>
<exclusion>
<groupId>net.sf.jopt-simple</groupId>
<artifactId>jopt-simple</artifactId>
</exclusion>
<exclusion>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>
maven-resolver-connector-basic
</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.maven</groupId>
<artifactId>maven-resolver-provider</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>
maven-resolver-transport-http
</artifactId>
</exclusion>
<exclusion>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-config</artifactId>
</exclusion>
<exclusion>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-chat</artifactId>
<groupId>io.netty</groupId>
<artifactId>
netty-transport-native-unix-common
</artifactId>
</exclusion>
<exclusion>
<groupId>net.md-5</groupId>
@@ -195,11 +80,11 @@
</exclusion>
<exclusion>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-native</artifactId>
<artifactId>bungeecord-event</artifactId>
</exclusion>
<exclusion>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-log</artifactId>
<artifactId>bungeecord-chat</artifactId>
</exclusion>
</exclusions>
</dependency>
@@ -56,7 +56,6 @@ public class TABAPI {
/**
* Enables unlimited nametag mode permanently in config
* @throws IllegalStateException if called from a proxy
* @see isUnlimitedNameTagModeEnabled
*/
public static void enableUnlimitedNameTagModePermanently() {
@@ -78,6 +77,7 @@ public class TABAPI {
PlaceholderManager pl = TAB.getInstance().getPlaceholderManager();
pl.registerPlaceholder(placeholder);
pl.allUsedPlaceholderIdentifiers.add(placeholder.getIdentifier());
pl.refreshPlaceholderUsage();
}
/**
@@ -91,6 +91,7 @@ public class TABAPI {
PlaceholderManager pl = TAB.getInstance().getPlaceholderManager();
pl.registerPlaceholder(placeholder);
pl.allUsedPlaceholderIdentifiers.add(placeholder.getIdentifier());
pl.refreshPlaceholderUsage();
}
/**
@@ -102,6 +103,7 @@ public class TABAPI {
PlaceholderManager pl = TAB.getInstance().getPlaceholderManager();
pl.registerPlaceholder(placeholder);
pl.allUsedPlaceholderIdentifiers.add(placeholder.getIdentifier());
pl.refreshPlaceholderUsage();
}
/**
@@ -147,7 +147,7 @@ public interface TabPlayer {
/**
* Returns player's uuid used in tablist. This may only be different than real uuid if
* TAB is installed on velocity with some specific velocity setup
* @return
* @return player's uuid in tablist
*/
public UUID getTablistUUID();
@@ -232,7 +232,6 @@ public interface TabPlayer {
/**
* Toggles armor stands preview mode for the player
* @throws IllegalStateException - if unlimited nametag mode is not enabled
*/
public void toggleNametagPreview();
@@ -272,11 +271,6 @@ public interface TabPlayer {
*/
public boolean isLoaded();
/**
* Marks the player as loaded and makes isLoaded() return true
*/
public void markAsLoaded();
/**
* Returns true if player has bossbar visible, false if player hid bossbar(s) using bossbar
* toggle command
@@ -427,30 +421,6 @@ public interface TabPlayer {
* @param armorStandManager - new instance
*/
public void setArmorStandManager(ArmorStandManager armorStandManager);
/**
* Internal method to set world name
* @param name - name of new world
*/
public void setWorldName(String name);
/**
* Internal method to set team name
* @param name - name of team
*/
public void setTeamName(String name);
/**
* Internal method to set team name note
* @param note - team name note
*/
public void setTeamNameNote(String note);
/**
* Internal method to track currently active scoreboard
* @param board - new active scoreboard
*/
public void setActiveScoreboard(Scoreboard board);
/**
* Internal method that returns player's active scoreboard
@@ -458,26 +428,6 @@ public interface TabPlayer {
*/
public Scoreboard getActiveScoreboard();
/**
* Internal method that sets player's group
* @param group - new group
* @param refreshIfChanged - whether to refresh properties if value changed or not
*/
public void setGroup(String group, boolean refreshIfChanged);
/**
* Internal method to track scoreboards from other plugins
* @param objectiveName - objective name of scoreboard from other plugins
*/
public void setOtherPluginScoreboard(String objectiveName);
/**
* Internal method that returns scoreboard objective name of scoreboard from other plugin or null
* if not scoreboard from other plugin is set
* @return name of scoreboard objective from other plugin
*/
public String getOtherPluginScoreboard();
/**
* Forces new team name for the player until this method is called again with null argument and
* performs all actions to change player's team name
@@ -490,4 +440,28 @@ public interface TabPlayer {
* @return forced team name or null if not forced
*/
public String getForcedTeamName();
/**
* Returns gamemode of the player (0 for survival, 1 creative, 2 adventure, 3 spectator)
* @return gamemode of the player
*/
public int getGamemode();
/**
* Unregisters player's team and no longer handles it, as well as disables anti-override for teams.
* This can be resumed using resumeTeamHandling(). If team handling was paused already, nothing happens.
*/
public void pauseTeamHandling();
/**
* Resumes team handling if it was before paused using pauseTeamHandling(), if not, nothing happens
*/
public void resumeTeamHandling();
/**
* Returns true if team handling is paused for this player using pauseTeamHandling(), false if not or
* it was resumed already using resumeTeamHandling
* @return true if paused, false if not
*/
public boolean hasTeamHandlingPaused();
}
@@ -10,6 +10,7 @@ import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import me.neznamy.tab.api.bossbar.BarColor;
@@ -107,12 +108,12 @@ public class ErrorManager {
if (file.length() > 1000000) return; //not going over 1 MB
BufferedWriter buf = new BufferedWriter(new FileWriter(file, true));
if (message != null) {
write(buf, "&c[TAB v" + tab.getPluginVersion() + (tab.isPremium() ? " Premium": "") + "] " + message, intoConsoleToo);
write(buf, "&c[TAB v" + tab.getPluginVersion() + (tab.isPremium() ? " Premium": "") + "] ", message.replace('\u00a7', '&'), intoConsoleToo);
}
if (error != null) {
write(buf, "&c" + error.getClass().getName() + ": " + error.getMessage(), intoConsoleToo);
write(buf, "&c", error.getClass().getName() + ": " + error.getMessage(), intoConsoleToo);
for (StackTraceElement ste : error.getStackTrace()) {
write(buf, "&c at " + ste.toString(), intoConsoleToo);
write(buf, "&c at ", ste.toString(), intoConsoleToo);
}
}
buf.close();
@@ -148,9 +149,9 @@ public class ErrorManager {
* @param forceConsole - send into console even without debug mode
* @throws IOException - if IO writer operation fails
*/
private void write(BufferedWriter buf, String message, boolean forceConsole) throws IOException {
buf.write(getCurrentTime() + removeColors(message) + System.getProperty("line.separator"));
if (tab.debugMode || forceConsole) tab.getPlatform().sendConsoleMessage(message, true);
private void write(BufferedWriter buf, String prefix, String message, boolean forceConsole) throws IOException {
buf.write(getCurrentTime() + removeColors(prefix) + message + System.getProperty("line.separator"));
if (tab.debugMode || forceConsole) tab.getPlatform().sendConsoleMessage(prefix.replace('&', '\u00a7') + message, false);
}
/**
@@ -410,7 +411,7 @@ public class ErrorManager {
*/
public SimpleDateFormat createDateFormat(String value, String defaultValue) {
try {
return new SimpleDateFormat(value);
return new SimpleDateFormat(value, Locale.ENGLISH);
} catch (Exception e) {
startupWarn("Format \"" + value + "\" is not a valid date/time format. Did you try to use color codes?");
return new SimpleDateFormat(defaultValue);
@@ -209,7 +209,7 @@ public class FeatureManager {
((JoinEventListener)f).onJoin(connectedPlayer);
tab.getCPUManager().addTime(f.getFeatureType(), UsageType.PLAYER_JOIN_EVENT, System.nanoTime()-time);
}
connectedPlayer.markAsLoaded();
((ITabPlayer)connectedPlayer).markAsLoaded();
tab.debug("Player join of " + connectedPlayer.getName() + " processed in " + (System.currentTimeMillis()-millis) + "ms");
}
@@ -227,7 +227,7 @@ public class FeatureManager {
return;
}
String from = changed.getWorldName();
changed.setWorldName(to);
((ITabPlayer)changed).setWorldName(to);
for (Feature f : getAllFeatures()) {
if (!(f instanceof WorldChangeListener)) continue;
long time = System.nanoTime();
@@ -1,5 +1,6 @@
package me.neznamy.tab.shared;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@@ -52,6 +53,7 @@ public abstract class ITabPlayer implements TabPlayer {
private boolean scoreboardVisible;
private Scoreboard forcedScoreboard;
private String otherPluginScoreboard;
private boolean teamHandlingPaused;
protected Map<String, String> attributes = new HashMap<String, String>();
@@ -103,19 +105,20 @@ public abstract class ITabPlayer implements TabPlayer {
@Override
public void setValueTemporarily(EnumProperty type, String value) {
TAB.getInstance().getPlaceholderManager().checkForRegistration(value);
TAB.getInstance().debug("Received API request to set property " + type + " of " + getName() + " temporarily to " + value + " by " + Thread.currentThread().getStackTrace()[2].toString());
Property pr = getProperty(type.toString());
if (pr == null) throw new IllegalStateException("Feature handling this property is not enabled");
if (pr == null) throw new IllegalStateException("Feature handling this property (" + type + ") is not enabled");
pr.setTemporaryValue(value);
if (TAB.getInstance().getFeatureManager().isFeatureEnabled("nametagx") && type.toString().contains("tag")) {
setProperty("nametag",getProperty("tagprefix").getCurrentRawValue() + getProperty("customtagname").getCurrentRawValue() + getProperty("tagsuffix").getCurrentRawValue(), null);
}
TAB.getInstance().getPlaceholderManager().checkForRegistration(value);
forceRefresh();
}
@Override
public void setValuePermanently(EnumProperty type, String value) {
TAB.getInstance().getPlaceholderManager().checkForRegistration(value);
TAB.getInstance().debug("Received API request to set property " + type + " of " + getName() + " permanently to " + value + " by " + Thread.currentThread().getStackTrace()[2].toString());
((PlayerCommand)TAB.getInstance().command.subcommands.get("player")).savePlayer(null, getName(), type.toString(), value);
if (TAB.getInstance().getFeatureManager().isFeatureEnabled("nametagx") && type.toString().contains("tag")) {
setProperty("nametag", getProperty("tagprefix").getCurrentRawValue() + getProperty("customtagname").getCurrentRawValue() + getProperty("tagsuffix").getCurrentRawValue(), null);
@@ -123,6 +126,7 @@ public abstract class ITabPlayer implements TabPlayer {
Property pr = getProperty(type.toString());
if (pr == null) return;
pr.changeRawValue(value);
TAB.getInstance().getPlaceholderManager().checkForRegistration(value);
forceRefresh();
}
@@ -214,7 +218,6 @@ public abstract class ITabPlayer implements TabPlayer {
return world;
}
@Override
public void setWorldName(String name) {
world = name;
}
@@ -276,7 +279,6 @@ public abstract class ITabPlayer implements TabPlayer {
return onJoinFinished;
}
@Override
public void markAsLoaded() {
onJoinFinished = true;
}
@@ -376,7 +378,6 @@ public abstract class ITabPlayer implements TabPlayer {
this.armorStandManager = armorStandManager;
}
@Override
public void setTeamName(String name) {
teamName = name;
}
@@ -387,7 +388,6 @@ public abstract class ITabPlayer implements TabPlayer {
return teamName;
}
@Override
public void setTeamNameNote(String note) {
teamNameNote = note;
}
@@ -419,9 +419,13 @@ public abstract class ITabPlayer implements TabPlayer {
sendMessage(scoreboardManager.scoreboard_on, true);
}
if (scoreboardManager.remember_toggle_choice) {
scoreboardManager.sb_off_players.remove(getName());
if (scoreboardManager.hiddenByDefault) {
scoreboardManager.sb_off_players.add(getName());
} else {
scoreboardManager.sb_off_players.remove(getName());
}
synchronized (scoreboardManager.sb_off_players){
TAB.getInstance().getConfiguration().playerdata.set("scoreboard-off", scoreboardManager.sb_off_players);
TAB.getInstance().getConfiguration().playerdata.set("scoreboard-off", new ArrayList<>(scoreboardManager.sb_off_players));
}
}
} else {
@@ -430,9 +434,13 @@ public abstract class ITabPlayer implements TabPlayer {
sendMessage(scoreboardManager.scoreboard_off, true);
}
if (scoreboardManager.remember_toggle_choice) {
scoreboardManager.sb_off_players.add(getName());
TAB.getInstance().getConfiguration().playerdata.set("scoreboard-off", scoreboardManager.sb_off_players);synchronized (scoreboardManager.sb_off_players){
TAB.getInstance().getConfiguration().playerdata.set("scoreboard-off", scoreboardManager.sb_off_players);
if (scoreboardManager.hiddenByDefault) {
scoreboardManager.sb_off_players.remove(getName());
} else {
scoreboardManager.sb_off_players.add(getName());
}
synchronized (scoreboardManager.sb_off_players){
TAB.getInstance().getConfiguration().playerdata.set("scoreboard-off", new ArrayList<>(scoreboardManager.sb_off_players));
}
}
}
@@ -448,7 +456,6 @@ public abstract class ITabPlayer implements TabPlayer {
return scoreboardVisible;
}
@Override
public void setActiveScoreboard(Scoreboard board) {
activeScoreboard = board;
}
@@ -458,7 +465,6 @@ public abstract class ITabPlayer implements TabPlayer {
return activeScoreboard;
}
@Override
public void setGroup(String permissionGroup, boolean refreshIfChanged) {
if (this.permissionGroup.equals(permissionGroup)) return;
if (permissionGroup != null) {
@@ -477,11 +483,6 @@ public abstract class ITabPlayer implements TabPlayer {
return forcedScoreboard != null;
}
@Override
public boolean isVanished() {
return false;
}
@Override
public void showBossBar(BossBar bossbar) {
BossBarLine line = (BossBarLine) bossbar;
@@ -524,12 +525,10 @@ public abstract class ITabPlayer implements TabPlayer {
attributes.put(attribute, value);
}
@Override
public void setOtherPluginScoreboard(String objectiveName) {
this.otherPluginScoreboard = objectiveName;
}
@Override
public String getOtherPluginScoreboard() {
return otherPluginScoreboard;
}
@@ -542,7 +541,7 @@ public abstract class ITabPlayer implements TabPlayer {
@Override
public void forceTeamName(String name) {
if (forcedTeamName == name) return;
if (String.valueOf(forcedTeamName).equals(name)) return;
if (name != null && name.length() > 16) throw new IllegalArgumentException("Team name cannot be more than 16 characters long.");
NameTag nametags = TAB.getInstance().getFeatureManager().getNameTagFeature();
if (nametags == null) return;
@@ -556,4 +555,29 @@ public abstract class ITabPlayer implements TabPlayer {
public String getForcedTeamName() {
return forcedTeamName;
}
@Override
public void pauseTeamHandling() {
if (teamHandlingPaused) return;
NameTag f = TAB.getInstance().getFeatureManager().getNameTagFeature();
if (f != null && !f.isDisabledWorld(getWorldName())) {
f.unregisterTeam(this);
}
teamHandlingPaused = true; //setting to true after, so unregisterTeam method runs
}
@Override
public void resumeTeamHandling() {
if (!teamHandlingPaused) return;
teamHandlingPaused = false; //setting to false before, so registerTeam method runs
NameTag f = TAB.getInstance().getFeatureManager().getNameTagFeature();
if (f != null && !f.isDisabledWorld(getWorldName())) {
f.registerTeam(this);
}
}
@Override
public boolean hasTeamHandlingPaused() {
return teamHandlingPaused;
}
}
@@ -6,19 +6,14 @@ import java.util.Map;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.config.ConfigurationFile;
import me.neznamy.tab.shared.features.AlignedSuffix;
import me.neznamy.tab.shared.features.BelowName;
import me.neznamy.tab.shared.features.GhostPlayerFix;
import me.neznamy.tab.shared.features.GroupRefresher;
import me.neznamy.tab.shared.features.HeaderFooter;
import me.neznamy.tab.shared.features.PingSpoof;
import me.neznamy.tab.shared.features.Playerlist;
import me.neznamy.tab.shared.features.PluginInfo;
import me.neznamy.tab.shared.features.SpectatorFix;
import me.neznamy.tab.shared.features.TabObjective;
import me.neznamy.tab.shared.features.UpdateChecker;
import me.neznamy.tab.shared.features.bossbar.BossBar;
import me.neznamy.tab.shared.features.layout.Layout;
import me.neznamy.tab.shared.features.scoreboard.ScoreboardManager;
import me.neznamy.tab.shared.permission.PermissionPlugin;
import me.neznamy.tab.shared.placeholders.Placeholder;
import me.neznamy.tab.shared.placeholders.PlayerPlaceholder;
@@ -84,6 +79,12 @@ public interface Platform {
*/
public int getMaxPlayers();
/**
* Returns name of config file in the jar file on specific platform
* @return name of config file of the platform
*/
public String getConfigName();
/**
* Removes an old config option that is not present anymore
* @param config - configuration file
@@ -155,11 +156,7 @@ public interface Platform {
public default void loadUniversalFeatures() {
TAB tab = TAB.getInstance();
if (tab.getConfiguration().config.getBoolean("enable-header-footer", true)) tab.getFeatureManager().registerFeature("headerfooter", new HeaderFooter(tab));
if (tab.getConfiguration().config.getBoolean("do-not-move-spectators", false)) tab.getFeatureManager().registerFeature("spectatorfix", new SpectatorFix());
if (tab.getConfiguration().config.getBoolean("classic-vanilla-belowname.enabled", true)) tab.getFeatureManager().registerFeature("belowname", new BelowName(tab));
if (tab.getConfiguration().premiumconfig != null && tab.getConfiguration().premiumconfig.getBoolean("scoreboard.enabled", false)) tab.getFeatureManager().registerFeature("scoreboard", new ScoreboardManager(tab));
if (tab.getConfiguration().removeGhostPlayers) tab.getFeatureManager().registerFeature("ghostplayerfix", new GhostPlayerFix());
if (tab.getConfiguration().config.getString("yellow-number-in-tablist", "%ping%").length() > 0) tab.getFeatureManager().registerFeature("tabobjective", new TabObjective(tab));
if (ProtocolVersion.SERVER_VERSION.getMinorVersion() >= 8 && tab.getConfiguration().config.getBoolean("change-tablist-prefix-suffix", true)) {
Playerlist playerlist = new Playerlist(tab);
tab.getFeatureManager().registerFeature("playerlist", playerlist);
@@ -170,6 +167,5 @@ public interface Platform {
new UpdateChecker(tab);
if (tab.getConfiguration().layout) tab.getFeatureManager().registerFeature("layout", new Layout(tab));
if (tab.getConfiguration().bossbar.getBoolean("bossbar-enabled", false)) tab.getFeatureManager().registerFeature("bossbar", new BossBar(tab));
if (tab.getConfiguration().config.getBoolean("ping-spoof.enabled", false)) tab.getFeatureManager().registerFeature("pingspoof", new PingSpoof());
}
}
@@ -70,10 +70,11 @@ public class Property {
* @param temporaryValue - temporary value to be assigned
*/
public void setTemporaryValue(String temporaryValue) {
this.temporaryValue = RGBUtils.getInstance().applyFormats(temporaryValue, true);
if (temporaryValue != null) {
analyze(temporaryValue);
this.temporaryValue = RGBUtils.getInstance().applyFormats(temporaryValue, true);
analyze(this.temporaryValue);
} else {
this.temporaryValue = null;
analyze(rawValue);
}
update();
@@ -188,11 +189,10 @@ public class Property {
* @return format for the viewer
*/
public String getFormat(TabPlayer viewer) {
if (viewer == null) return lastReplacedValue;
String format = lastReplacedValue;
for (String identifier : relPlaceholders) {
RelationalPlaceholder pl = (RelationalPlaceholder) TAB.getInstance().getPlaceholderManager().getPlaceholder(identifier);
if (pl != null) format = format.replace(pl.getIdentifier(), pl.getLastValue(viewer, owner));
if (pl != null) format = format.replace(pl.getIdentifier(), viewer == null ? "" : pl.getLastValue(viewer, owner));
}
return format;
}
@@ -6,6 +6,7 @@ package me.neznamy.tab.shared;
public enum ProtocolVersion {
UNKNOWN (999),
v1_17 (755),
v1_16_5 (754),
v1_16_4 (754),
v1_16_3 (753),
@@ -61,7 +62,7 @@ public enum ProtocolVersion {
//version's network id found at https://wiki.vg/Protocol_version_numbers
private int networkId;
//minor versio, such as 16
//minor version, such as 16
private int minorVersion;
//friendly name displayed in %player-version% placeholder
@@ -25,14 +25,14 @@ public class TAB {
private static TAB instance;
//version of plugin
public static final String pluginVersion = "2.8.11-pre16";
public static final String pluginVersion = "2.9.0";
//player data
public final Map<UUID, TabPlayer> data = new ConcurrentHashMap<UUID, TabPlayer>();
//the command
public TabCommand command;
//command used if plugin is disabled due to a broken configuration file
public final DisabledCommand disabledCommand = new DisabledCommand();
@@ -153,7 +153,7 @@ public class TAB {
platform.loadFeatures();
command = new TabCommand(this);
featureManager.load();
getPlayers().forEach(p -> p.markAsLoaded());
getPlayers().forEach(p -> ((ITabPlayer)p).markAsLoaded());
errorManager.printConsoleWarnCount();
print('a', "Enabled in " + (System.currentTimeMillis()-time) + "ms");
platform.callLoadEvent();
@@ -112,7 +112,7 @@ public class TabCommand extends SubCommand {
@Override
public List<String> complete(TabPlayer sender, String[] arguments) {
if (!sender.hasPermission("tab.tabcomplete")) return new ArrayList<String>();
if (!hasPermission(sender, "tab.tabcomplete")) return new ArrayList<String>();
return super.complete(sender, arguments);
}
}
@@ -21,7 +21,7 @@ public class BossBarCommand extends SubCommand{
public void execute(TabPlayer sender, String[] args) {
BossBar bossbar = (BossBar) TAB.getInstance().getFeatureManager().getFeature("bossbar");
if (bossbar == null) {
sender.sendMessage("&cBossbar feature is not enabled, therefore toggle command cannot be used.", true);
sendMessage(sender, "&cBossbar feature is not enabled, therefore toggle command cannot be used.");
return;
}
if (sender == null) {
@@ -51,14 +51,15 @@ public class DebugCommand extends SubCommand {
TAB tab = TAB.getInstance();
sendMessage(sender, "&3[TAB] &a&lShowing debug information");
sendMessage(sender, "&7&m>-------------------------------<");
sendMessage(sender, "&6Server version: &a" + tab.getPlatform().getServerVersion());
sendMessage(sender, "&6Plugin version: &a" + tab.getPluginVersion() + (tab.isPremium() ? " Premium" : ""));
String c2 = tab.isPremium() ? "&b" : "&a";
sendMessage(sender, "&6Server version: " + c2 + tab.getPlatform().getServerVersion());
sendMessage(sender, "&6Plugin version: " + c2 + tab.getPluginVersion() + (tab.isPremium() ? " Premium" : ""));
if (tab.getErrorManager().errorLog.exists()) {
sendMessage(sender, "&6" + tab.getErrorManager().errorLog.getPath() + " size: &c" + tab.getErrorManager().errorLog.length()/1024 + "KB");
}
sendMessage(sender, "&6Permission plugin: &a" + tab.getPermissionPlugin().getName());
sendMessage(sender, getGroupChoiceLogic());
sendMessage(sender, "&6Sorting system: &a" + getSortingType());
sendMessage(sender, "&6Permission plugin: " + c2 + tab.getPermissionPlugin().getName());
sendMessage(sender, "&6Permission group choice logic: " + c2 + getGroupChoiceLogic());
sendMessage(sender, "&6Sorting system: " + c2 + getSortingType());
sendMessage(sender, "&7&m>-------------------------------<");
if (analyzed == null) return;
sendMessage(sender, "&ePlayer: &a" + analyzed.getName());
@@ -96,11 +97,11 @@ public class DebugCommand extends SubCommand {
private String getGroupChoiceLogic() {
GroupRefresher group = (GroupRefresher) TAB.getInstance().getFeatureManager().getFeature("group");
if (group.groupsByPermissions) {
return "&6Permission group choice logic: &8&mPrimary group&8 / &r&8&mChoose from list&8 / &aPermissions";
return "Permissions";
} else if (group.usePrimaryGroup) {
return "&6Permission group choice logic: &aPrimary group&8 / &r&8&mChoose from list&8 / &r&8&mPermissions";
return "Primary group";
} else {
return "&6Permission group choice logic: &8&mPrimary group&r&8 / &aChoose from list&8 / &r&8&mPermissions";
return "Choose from list";
}
}
@@ -196,7 +197,8 @@ public class DebugCommand extends SubCommand {
} else {
Property pr = analyzed.getProperty(property);
String rawValue = pr.getCurrentRawValue().replace('\u00a7', '&');
String value = String.format("&a%s: &e\"&r%s&r&e\" &7(%s) &9(Source: %s)".replace('&', '\u00a7'), property, rawValue, rawValue.length(), pr.getSource());
String c = TAB.getInstance().isPremium() ? "&7" : "&9";
String value = String.format(("&a%s: &e\"&r%s&r&e\" &7(%s) " + c + "(Source: %s)").replace('&', '\u00a7'), property, rawValue, rawValue.length(), pr.getSource());
sendRawMessage(sender, value);
}
}
@@ -1,6 +1,7 @@
package me.neznamy.tab.shared.command.level1;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.ITabPlayer;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.command.SubCommand;
import me.neznamy.tab.shared.features.scoreboard.ScoreboardManager;
@@ -45,7 +46,7 @@ public class ScoreboardCommand extends SubCommand {
return;
}
}
if (p.getOtherPluginScoreboard() != null) return; //not overriding other plugins
if (((ITabPlayer)p).getOtherPluginScoreboard() != null) return; //not overriding other plugins
boolean silent = args.length >= 3 && args[2].equals("-s");
if (args.length >= 1) {
switch(args[0]) {
@@ -38,12 +38,12 @@ public class AnnounceBarCommand extends SubCommand{
try {
duration = Integer.parseInt(args[1]);
} catch (Exception e) {
sender.sendMessage(args[1] + " is not a number!", false);
sendMessage(sender, args[1] + " is not a number!");
return;
}
BossBarLine bar = feature.lines.get(barname);
if (bar == null) {
sender.sendMessage("Bar not found", false);
sendMessage(sender, "Bar not found");
return;
}
new Thread(() -> {
@@ -40,12 +40,12 @@ public class AnnounceScoreboardCommand extends SubCommand{
try {
duration = Integer.parseInt(args[1]);
} catch (Exception e) {
sender.sendMessage(args[1] + " is not a number!", false);
sendMessage(sender, args[1] + " is not a number!");
return;
}
Scoreboard sb = feature.getScoreboards().get(scoreboard);
if (sb == null) {
sender.sendMessage("Scoreboard not found", false);
sendMessage(sender, "Scoreboard not found");
return;
}
announce(feature, sb, duration);
@@ -48,7 +48,7 @@ public class SendBarCommand extends SubCommand{
}
BossBarLine bar = feature.lines.get(barname);
if (bar == null) {
sender.sendMessage("Bar not found", false);
sendMessage(sender, "No bar found with name \"" + bar + "\"");
return;
}
new Thread(() -> {
@@ -40,6 +40,7 @@ public class Configs {
public boolean removeGhostPlayers;
public boolean layout;
public boolean pipelineInjection;
public boolean bukkitPermissions;
//animations.yml file
public ConfigurationFile animation;
@@ -110,8 +111,7 @@ public class Configs {
*/
@SuppressWarnings("unchecked")
public void loadConfig() throws Exception {
String source = tab.getPlatform().getSeparatorType().equals("world") ? "bukkitconfig.yml" : "bungeeconfig.yml";
config = new YamlConfigurationFile(Configs.class.getClassLoader().getResourceAsStream(source), new File(tab.getPlatform().getDataFolder(), "config.yml"), Arrays.asList("# Detailed explanation of all options available at https://github.com/NEZNAMY/TAB/wiki/config.yml", ""));
config = new YamlConfigurationFile(Configs.class.getClassLoader().getResourceAsStream(tab.getPlatform().getConfigName()), new File(tab.getPlatform().getDataFolder(), "config.yml"), Arrays.asList("# Detailed explanation of all options available at https://github.com/NEZNAMY/TAB/wiki/config.yml", ""));
removeStrings = new ArrayList<>();
for (String s : config.getStringList("placeholders.remove-strings", Arrays.asList("[] ", "< > "))) {
removeStrings.add(s.replace('&', '\u00a7'));
@@ -125,6 +125,9 @@ public class Configs {
removeGhostPlayers = (boolean) getSecretOption("remove-ghost-players", false);
layout = (boolean) getSecretOption("layout", false);
pipelineInjection = (boolean) getSecretOption("pipeline-injection", true);
if (tab.getPlatform().getSeparatorType().equals("server")) {
bukkitPermissions = config.getBoolean("use-bukkit-permissions-manager", false);
}
//checking for unnecessary copypaste in config
Set<Object> groups = config.getConfigurationSection("Groups").keySet();
@@ -48,8 +48,8 @@ public class AlignedSuffix implements QuitEventListener, WorldChangeListener {
}
}
public String formatNameAndUpdateLeader(TabPlayer player, String prefixAndName, String suffix) {
int playerNameWidth = getTextWidth(IChatBaseComponent.fromColoredText(prefixAndName + suffix));
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) {
maxWidth = playerNameWidth;
for (TabPlayer all : tab.getPlayers()) {
@@ -65,7 +65,7 @@ public class AlignedSuffix implements QuitEventListener, WorldChangeListener {
maxPlayer = player;
updateAllNames(player);
}
return formatName(prefixAndName, suffix);
return formatName(player.getProperty("tabprefix").getFormat(viewer) + player.getProperty("customtabname").getFormat(viewer), player.getProperty("tabsuffix").getFormat(viewer));
}
public String formatName(String prefixAndName, String suffix) {
@@ -109,7 +109,7 @@ public class AlignedSuffix implements QuitEventListener, WorldChangeListener {
* @return width of player's tablist name format
*/
private int getPlayerNameWidth(TabPlayer p) {
String format = p.getProperty("tabprefix").get() + p.getProperty("customtabname").get() + p.getProperty("tabsuffix").get();
String format = p.getProperty("tabprefix").getFormat(null) + p.getProperty("customtabname").getFormat(null) + p.getProperty("tabsuffix").getFormat(null);
return getTextWidth(IChatBaseComponent.fromColoredText(format));
}
@@ -123,7 +123,7 @@ public class BelowName implements Loadable, JoinEventListener, WorldChangeListen
}
private int getValue(TabPlayer p) {
return tab.getErrorManager().parseInteger(p.getProperty(numberPropertyName).updateAndGet(), 0, "belowname");
return tab.getErrorManager().parseInteger(p.getProperty(numberPropertyName).updateAndGet(), 0, "belowname number");
}
@Override
@@ -1,5 +1,6 @@
package me.neznamy.tab.shared.features;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@@ -26,13 +27,14 @@ import me.neznamy.tab.shared.packets.PacketPlayOutPlayerInfo.PlayerInfoData;
public class GlobalPlayerlist implements Loadable, JoinEventListener, QuitEventListener, WorldChangeListener, PlayerInfoPacketListener{
private TAB tab;
public final String PREMIUMVANISH_SEE_VANISHED_PERMISSION = "pv.see";
private List<String> spyServers;
private Map<String, List<String>> sharedServers;
private boolean displayAsSpectators;
public boolean vanishedAsSpectators;
private boolean isolateUnlistedServers;
private List<TabPlayer> vanishedPlayers = new ArrayList<TabPlayer>();
public GlobalPlayerlist(TAB tab) {
this.tab = tab;
@@ -53,11 +55,38 @@ public class GlobalPlayerlist implements Loadable, JoinEventListener, QuitEventL
}
tab.debug(String.format("Loaded GlobalPlayerlist feature with parameters spyServers=%s, sharedServers=%s, displayAsSpectators=%s, vanishedAsSpectators=%s, isolateUnlistedServers=%s",
spyServers, sharedServers, displayAsSpectators, vanishedAsSpectators, isolateUnlistedServers));
startTask();
}
private void startTask() {
tab.getCPUManager().startRepeatingMeasuredTask(500, "refreshing vanished players", getFeatureType(), UsageType.REPEATING_TASK, () -> {
for (TabPlayer p : tab.getPlayers()) {
if (vanishedPlayers.contains(p) && !p.isVanished()) {
vanishedPlayers.remove(p);
for (TabPlayer viewer : tab.getPlayers()) {
if (viewer == p) continue;
if (shouldSee(viewer, p)) {
viewer.sendCustomPacket(getAddPacket(p, viewer), getFeatureType());
}
}
}
if (!vanishedPlayers.contains(p) && p.isVanished()) {
vanishedPlayers.add(p);
for (TabPlayer all : tab.getPlayers()) {
if (all == p) continue;
if (!shouldSee(all, p)) {
all.sendCustomPacket(getRemovePacket(p), getFeatureType());
}
}
}
}
});
}
public boolean shouldSee(TabPlayer viewer, TabPlayer displayed) {
if (displayed == viewer) return true;
if (displayed.isVanished() && !viewer.hasPermission(PREMIUMVANISH_SEE_VANISHED_PERMISSION)) return false;
if (displayed.isVanished() && !viewer.hasPermission("tab.seevanished")) return false;
if (spyServers.contains(viewer.getWorldName())) return true;
return getServerGroup(viewer.getWorldName()).equals(getServerGroup(displayed.getWorldName()));
}
@@ -5,6 +5,7 @@ import java.util.Arrays;
import java.util.List;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.ITabPlayer;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.cpu.TabFeature;
import me.neznamy.tab.shared.cpu.UsageType;
@@ -33,7 +34,7 @@ public class GroupRefresher implements Feature {
@Override
public void run() {
for (TabPlayer p : tab.getPlayers()) {
p.setGroup(detectPermissionGroup(p), true);
((ITabPlayer) p).setGroup(detectPermissionGroup(p), true);
}
}
});
@@ -1,5 +1,6 @@
package me.neznamy.tab.shared.features;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
@@ -8,6 +9,7 @@ import java.util.Map;
import java.util.Set;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.ITabPlayer;
import me.neznamy.tab.shared.PacketAPI;
import me.neznamy.tab.shared.Property;
import me.neznamy.tab.shared.ProtocolVersion;
@@ -26,7 +28,7 @@ import me.neznamy.tab.shared.packets.PacketPlayOutScoreboardTeam;
public class NameTag implements Loadable, Refreshable, LoginPacketListener, QuitEventListener, WorldChangeListener, JoinEventListener {
protected TAB tab;
protected List<String> usedPlaceholders;
protected Set<String> usedPlaceholders;
protected List<String> disabledWorlds;
private boolean collisionRule;
private List<String> revertedCollision;
@@ -42,7 +44,11 @@ public class NameTag implements Loadable, Refreshable, LoginPacketListener, Quit
revertedCollision = tab.getConfiguration().config.getStringList("revert-collision-rule-in-" + tab.getPlatform().getSeparatorType()+"s", Arrays.asList("reverted" + tab.getPlatform().getSeparatorType()));
invisibleNametags = tab.getConfiguration().config.getBoolean("invisible-nametags", false);
sorting = new Sorting(tab, this);
usedPlaceholders = tab.getConfiguration().config.getUsedPlaceholderIdentifiersRecursive("tagprefix", "tagsuffix");
usedPlaceholders = new HashSet<>(tab.getConfiguration().config.getUsedPlaceholderIdentifiersRecursive("tagprefix", "tagsuffix"));
for (TabPlayer p : tab.getPlayers()) {
usedPlaceholders.addAll(tab.getPlaceholderManager().getUsedPlaceholderIdentifiersRecursive(
p.getProperty("tagprefix").getCurrentRawValue(), p.getProperty("tagsuffix").getCurrentRawValue()));
}
tab.debug(String.format("Loaded NameTag feature with parameters collisionRule=%s, revertedCollision=%s, disabledWorlds=%s, invisibleNametags=%s",
collisionRule, revertedCollision, disabledWorlds, invisibleNametags));
}
@@ -50,7 +56,7 @@ public class NameTag implements Loadable, Refreshable, LoginPacketListener, Quit
@Override
public void load(){
for (TabPlayer all : tab.getPlayers()) {
all.setTeamName(sorting.getTeamName(all));
((ITabPlayer) all).setTeamName(sorting.getTeamName(all));
updateProperties(all);
collision.put(all, true);
if (all.hasInvisibilityPotion()) invisiblePlayers.add(all.getName());
@@ -100,10 +106,11 @@ public class NameTag implements Loadable, Refreshable, LoginPacketListener, Quit
@Override
public List<String> getUsedPlaceholders() {
return usedPlaceholders;
return new ArrayList<>(usedPlaceholders);
}
public void unregisterTeam(TabPlayer p) {
if (p.hasTeamHandlingPaused()) return;
if (p.getTeamName() == null) return;
for (TabPlayer viewer : tab.getPlayers()) {
viewer.sendCustomPacket(new PacketPlayOutScoreboardTeam(p.getTeamName()).setTeamOptions(69), TabFeature.NAMETAGS);
@@ -111,10 +118,12 @@ public class NameTag implements Loadable, Refreshable, LoginPacketListener, Quit
}
public void unregisterTeam(TabPlayer p, TabPlayer viewer) {
if (p.hasTeamHandlingPaused()) return;
viewer.sendCustomPacket(new PacketPlayOutScoreboardTeam(p.getTeamName()).setTeamOptions(69), TabFeature.NAMETAGS);
}
public void registerTeam(TabPlayer p) {
if (p.hasTeamHandlingPaused()) return;
Property tagprefix = p.getProperty("tagprefix");
Property tagsuffix = p.getProperty("tagsuffix");
for (TabPlayer viewer : tab.getPlayers()) {
@@ -125,6 +134,7 @@ public class NameTag implements Loadable, Refreshable, LoginPacketListener, Quit
}
public void registerTeam(TabPlayer p, TabPlayer viewer) {
if (p.hasTeamHandlingPaused()) return;
Property tagprefix = p.getProperty("tagprefix");
Property tagsuffix = p.getProperty("tagsuffix");
String replacedPrefix = tagprefix.getFormat(viewer);
@@ -139,7 +149,7 @@ public class NameTag implements Loadable, Refreshable, LoginPacketListener, Quit
updateTeamData(p);
} else {
unregisterTeam(p);
p.setTeamName(newName);
((ITabPlayer) p).setTeamName(newName);
registerTeam(p);
}
}
@@ -215,7 +225,7 @@ public class NameTag implements Loadable, Refreshable, LoginPacketListener, Quit
@Override
public void onJoin(TabPlayer connectedPlayer) {
connectedPlayer.setTeamName(sorting.getTeamName(connectedPlayer));
((ITabPlayer) connectedPlayer).setTeamName(sorting.getTeamName(connectedPlayer));
updateProperties(connectedPlayer);
collision.put(connectedPlayer, true);
for (TabPlayer all : tab.getPlayers()) {
@@ -252,7 +262,11 @@ public class NameTag implements Loadable, Refreshable, LoginPacketListener, Quit
@Override
public void refreshUsedPlaceholders() {
usedPlaceholders = tab.getConfiguration().config.getUsedPlaceholderIdentifiersRecursive("tagprefix", "tagsuffix");
usedPlaceholders = new HashSet<>(tab.getConfiguration().config.getUsedPlaceholderIdentifiersRecursive("tagprefix", "tagsuffix"));
for (TabPlayer p : tab.getPlayers()) {
usedPlaceholders.addAll(tab.getPlaceholderManager().getUsedPlaceholderIdentifiersRecursive(
p.getProperty("tagprefix").getCurrentRawValue(), p.getProperty("tagsuffix").getCurrentRawValue()));
}
}
public void updateProperties(TabPlayer p) {
@@ -1,8 +1,12 @@
package me.neznamy.tab.shared.features;
import java.util.ArrayList;
import java.util.List;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.cpu.TabFeature;
import me.neznamy.tab.shared.features.types.Loadable;
import me.neznamy.tab.shared.features.types.packet.PlayerInfoPacketListener;
import me.neznamy.tab.shared.packets.PacketPlayOutPlayerInfo;
import me.neznamy.tab.shared.packets.PacketPlayOutPlayerInfo.EnumPlayerInfoAction;
@@ -11,7 +15,7 @@ import me.neznamy.tab.shared.packets.PacketPlayOutPlayerInfo.PlayerInfoData;
/**
* Sets ping of all players in the packet to configured value to prevent hacked clients from seeing exact ping value of each player
*/
public class PingSpoof implements PlayerInfoPacketListener {
public class PingSpoof implements PlayerInfoPacketListener, Loadable {
//fake ping value
private int value;
@@ -36,4 +40,24 @@ public class PingSpoof implements PlayerInfoPacketListener {
public TabFeature getFeatureType() {
return TabFeature.PING_SPOOF;
}
@Override
public void load() {
updateAll(false);
}
@Override
public void unload() {
updateAll(true);
}
private void updateAll(boolean realPing) {
List<PlayerInfoData> list = new ArrayList<PlayerInfoData>();
for (TabPlayer p : TAB.getInstance().getPlayers()) {
list.add(new PlayerInfoData(p.getUniqueId(), realPing ? (int) p.getPing() : 0));
}
for (TabPlayer p : TAB.getInstance().getPlayers()) {
p.sendCustomPacket(new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.UPDATE_LATENCY, list), getFeatureType());
}
}
}
@@ -2,7 +2,9 @@ package me.neznamy.tab.shared.features;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.Property;
@@ -25,7 +27,7 @@ import me.neznamy.tab.shared.packets.PacketPlayOutPlayerInfo.PlayerInfoData;
public class Playerlist implements JoinEventListener, Loadable, WorldChangeListener, Refreshable {
private TAB tab;
private List<String> usedPlaceholders;
private Set<String> usedPlaceholders;
public List<String> disabledWorlds;
private boolean antiOverrideNames;
private boolean antiOverrideTablist;
@@ -34,9 +36,9 @@ public class Playerlist implements JoinEventListener, Loadable, WorldChangeListe
public Playerlist(TAB tab) {
this.tab = tab;
disabledWorlds = tab.getConfiguration().config.getStringList("disable-features-in-"+tab.getPlatform().getSeparatorType()+"s.tablist-names", Arrays.asList("disabled" + tab.getPlatform().getSeparatorType()));
antiOverrideNames = tab.getConfiguration().config.getBoolean("anti-override.usernames", true);
antiOverrideNames = tab.getConfiguration().config.getBoolean("anti-override.usernames", true) && tab.getFeatureManager().isFeatureEnabled("injection");
refreshUsedPlaceholders();
antiOverrideTablist = tab.getConfiguration().config.getBoolean("anti-override.tablist-names", true);
antiOverrideTablist = tab.getConfiguration().config.getBoolean("anti-override.tablist-names", true) && tab.getFeatureManager().isFeatureEnabled("injection");
if (antiOverrideTablist) {
tab.getFeatureManager().registerFeature("playerlist_info", new PlayerInfoPacketListener() {
@@ -82,7 +84,7 @@ public class Playerlist implements JoinEventListener, Loadable, WorldChangeListe
disabling = true;
List<PlayerInfoData> updatedPlayers = new ArrayList<PlayerInfoData>();
for (TabPlayer p : tab.getPlayers()) {
if (!isDisabledWorld(disabledWorlds, p.getWorldName())) updatedPlayers.add(new PlayerInfoData(p.getUniqueId()));
if (!isDisabledWorld(disabledWorlds, p.getWorldName())) updatedPlayers.add(new PlayerInfoData(p.getTablistUUID()));
}
for (TabPlayer all : tab.getPlayers()) {
if (all.getVersion().getMinorVersion() >= 8) all.sendCustomPacket(new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.UPDATE_DISPLAY_NAME, updatedPlayers), getFeatureType());
@@ -91,10 +93,12 @@ public class Playerlist implements JoinEventListener, Loadable, WorldChangeListe
@Override
public void onWorldChange(TabPlayer p, String from, String to) {
if (isDisabledWorld(disabledWorlds, to) && !isDisabledWorld(disabledWorlds, from)) {
for (TabPlayer viewer : tab.getPlayers()) {
if (viewer.getVersion().getMinorVersion() < 8) continue;
viewer.sendCustomPacket(new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.UPDATE_DISPLAY_NAME, new PlayerInfoData(p.getTablistUUID(), getTabFormat(p, viewer))));
if (isDisabledWorld(disabledWorlds, to)) {
if (!isDisabledWorld(disabledWorlds, from)) {
for (TabPlayer viewer : tab.getPlayers()) {
if (viewer.getVersion().getMinorVersion() < 8) continue;
viewer.sendCustomPacket(new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.UPDATE_DISPLAY_NAME, new PlayerInfoData(p.getTablistUUID())));
}
}
} else {
refresh(p, true);
@@ -140,7 +144,7 @@ public class Playerlist implements JoinEventListener, Loadable, WorldChangeListe
String format;
AlignedSuffix alignedSuffix = (AlignedSuffix) tab.getFeatureManager().getFeature("alignedsuffix");
if (alignedSuffix != null) {
format = alignedSuffix.formatNameAndUpdateLeader(refreshed, prefix.getFormat(viewer) + name.getFormat(viewer), suffix.getFormat(viewer));
format = alignedSuffix.formatNameAndUpdateLeader(refreshed, viewer);
} else {
format = prefix.getFormat(viewer) + name.getFormat(viewer) + suffix.getFormat(viewer);
}
@@ -156,7 +160,7 @@ public class Playerlist implements JoinEventListener, Loadable, WorldChangeListe
@Override
public List<String> getUsedPlaceholders() {
return usedPlaceholders;
return new ArrayList<>(usedPlaceholders);
}
@Override
@@ -179,7 +183,11 @@ public class Playerlist implements JoinEventListener, Loadable, WorldChangeListe
@Override
public void refreshUsedPlaceholders() {
usedPlaceholders = tab.getConfiguration().config.getUsedPlaceholderIdentifiersRecursive("tabprefix", "customtabname", "tabsuffix");
usedPlaceholders = new HashSet<>(tab.getConfiguration().config.getUsedPlaceholderIdentifiersRecursive("tabprefix", "customtabname", "tabsuffix"));
for (TabPlayer p : tab.getPlayers()) {
usedPlaceholders.addAll(tab.getPlaceholderManager().getUsedPlaceholderIdentifiersRecursive(p.getProperty("tabprefix").getCurrentRawValue(),
p.getProperty("customtabname").getCurrentRawValue(), p.getProperty("tabsuffix").getCurrentRawValue()));
}
}
@Override
@@ -5,6 +5,7 @@ import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.ITabPlayer;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.placeholders.PlayerPlaceholder;
@@ -68,7 +69,7 @@ public interface PluginMessageHandler {
}
if (subChannel.equals("Group")) {
String group = in.readUTF();
player.setGroup(group, true);
((ITabPlayer) player).setGroup(group, true);
}
}
@@ -1,8 +1,12 @@
package me.neznamy.tab.shared.features;
import java.util.ArrayList;
import java.util.List;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.cpu.TabFeature;
import me.neznamy.tab.shared.features.types.Loadable;
import me.neznamy.tab.shared.features.types.packet.PlayerInfoPacketListener;
import me.neznamy.tab.shared.packets.PacketPlayOutPlayerInfo;
import me.neznamy.tab.shared.packets.PacketPlayOutPlayerInfo.EnumGamemode;
@@ -14,7 +18,7 @@ import me.neznamy.tab.shared.packets.PacketPlayOutPlayerInfo.PlayerInfoData;
* the bottom of tablist with transparent name. Does not work on self as that would result
* in players not being able to clip through walls.
*/
public class SpectatorFix implements PlayerInfoPacketListener {
public class SpectatorFix implements PlayerInfoPacketListener, Loadable {
//if bypass permission should be enabled
private boolean allowBypass;
@@ -43,4 +47,26 @@ public class SpectatorFix implements PlayerInfoPacketListener {
public TabFeature getFeatureType() {
return TabFeature.SPECTATOR_FIX;
}
@Override
public void load() {
updateAll(false);
}
@Override
public void unload() {
updateAll(true);
}
private void updateAll(boolean realGamemode) {
for (TabPlayer p : TAB.getInstance().getPlayers()) {
if (allowBypass && p.hasPermission("tab.spectatorbypass")) continue;
List<PlayerInfoData> list = new ArrayList<PlayerInfoData>();
for (TabPlayer target : TAB.getInstance().getPlayers()) {
if (p == target) continue;
list.add(new PlayerInfoData(p.getUniqueId(), realGamemode ? EnumGamemode.values()[p.getGamemode()+1] : EnumGamemode.CREATIVE));
}
p.sendCustomPacket(new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.UPDATE_GAME_MODE, list), getFeatureType());
}
}
}
@@ -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.8.10";
private final String currentRelease = "2.9.0";
public UpdateChecker(TAB tab) {
new Thread(new Runnable() {
@@ -6,6 +6,7 @@ import java.util.List;
import java.util.Set;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.ITabPlayer;
import me.neznamy.tab.shared.PacketAPI;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.cpu.TabFeature;
@@ -153,7 +154,7 @@ public class Scoreboard implements me.neznamy.tab.api.Scoreboard, Refreshable {
s.register(p);
}
players.add(p);
p.setActiveScoreboard(this);
((ITabPlayer)p).setActiveScoreboard(this);
}
/**
@@ -175,7 +176,7 @@ public class Scoreboard implements me.neznamy.tab.api.Scoreboard, Refreshable {
s.unregister(p);
}
players.remove(p);
p.setActiveScoreboard(null);
((ITabPlayer)p).setActiveScoreboard(null);
}
@Override
@@ -4,11 +4,14 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.ITabPlayer;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.cpu.TabFeature;
import me.neznamy.tab.shared.cpu.UsageType;
@@ -58,7 +61,7 @@ public class ScoreboardManager implements Loadable, JoinEventListener, QuitEvent
public boolean remember_toggle_choice;
//list of players with disabled scoreboard
public List<String> sb_off_players = Collections.synchronizedList(new ArrayList<String>());
public Set<String> sb_off_players = new HashSet<String>();
//scoreboards registered via API
public List<me.neznamy.tab.api.Scoreboard> APIscoreboards = new ArrayList<>();
@@ -70,7 +73,7 @@ public class ScoreboardManager implements Loadable, JoinEventListener, QuitEvent
public int staticNumber;
//hidden by default, toggle command must be ran to show it
private boolean hiddenByDefault;
public boolean hiddenByDefault;
//scoreboard toggle on message
public String scoreboard_on;
@@ -102,7 +105,7 @@ public class ScoreboardManager implements Loadable, JoinEventListener, QuitEvent
scoreboard_on = tab.getConfiguration().premiumconfig.getString("scoreboard-on", "&2Scorebord enabled");
scoreboard_off = tab.getConfiguration().premiumconfig.getString("scoreboard-off", "&7Scoreboard disabled");
if (remember_toggle_choice) {
sb_off_players = Collections.synchronizedList(new ArrayList<String>(tab.getConfiguration().getPlayerData("scoreboard-off")));
sb_off_players = Collections.synchronizedSet(new HashSet<String>(tab.getConfiguration().getPlayerData("scoreboard-off")));
}
staticNumber = tab.getConfiguration().premiumconfig.getInt("scoreboard.static-number", 0);
joinDelay = tab.getConfiguration().premiumconfig.getInt("scoreboard.delay-on-join-milliseconds", 0);
@@ -153,13 +156,13 @@ public class ScoreboardManager implements Loadable, JoinEventListener, QuitEvent
@Override
public void load() {
for (TabPlayer p : tab.getPlayers()) {
p.setScoreboardVisible(!sb_off_players.contains(p.getName()) && !hiddenByDefault, false);
p.setScoreboardVisible(hiddenByDefault == sb_off_players.contains(p.getName()), false);
}
tab.getCPUManager().startRepeatingMeasuredTask(1000, "refreshing scoreboard conditions", TabFeature.SCOREBOARD, UsageType.REPEATING_TASK, new Runnable() {
public void run() {
for (TabPlayer p : tab.getPlayers()) {
if (!p.isLoaded() || p.hasForcedScoreboard() || !p.isScoreboardVisible() ||
announcement != null || p.getOtherPluginScoreboard() != null || joinDelayed.contains(p)) continue;
announcement != null || ((ITabPlayer)p).getOtherPluginScoreboard() != null || joinDelayed.contains(p)) continue;
me.neznamy.tab.api.Scoreboard board = p.getActiveScoreboard();
String current = board == null ? "null" : board.getName();
String highest = detectHighestScoreboard(p);
@@ -178,7 +181,7 @@ public class ScoreboardManager implements Loadable, JoinEventListener, QuitEvent
board.unregister();
}
for (TabPlayer p : tab.getPlayers()) {
p.setActiveScoreboard(null);
((ITabPlayer)p).setActiveScoreboard(null);
}
scoreboards.clear();
}
@@ -189,11 +192,11 @@ public class ScoreboardManager implements Loadable, JoinEventListener, QuitEvent
joinDelayed.add(p);
tab.getCPUManager().runTaskLater(joinDelay, "processing player join", getFeatureType(), UsageType.PLAYER_JOIN_EVENT, () -> {
if (p.getOtherPluginScoreboard() == null) p.setScoreboardVisible(!sb_off_players.contains(p.getName()) && !hiddenByDefault, false);
if (((ITabPlayer)p).getOtherPluginScoreboard() == null) p.setScoreboardVisible(hiddenByDefault == sb_off_players.contains(p.getName()), false);
joinDelayed.remove(p);
});
} else {
p.setScoreboardVisible(!sb_off_players.contains(p.getName()) && !hiddenByDefault, false);
p.setScoreboardVisible(hiddenByDefault == sb_off_players.contains(p.getName()), false);
}
}
@@ -207,7 +210,7 @@ public class ScoreboardManager implements Loadable, JoinEventListener, QuitEvent
if (scoreboard != null) {
Scoreboard board = scoreboards.get(scoreboard);
if (board != null) {
p.setActiveScoreboard(board);
((ITabPlayer)p).setActiveScoreboard(board);
board.register(p);
}
}
@@ -230,7 +233,7 @@ public class ScoreboardManager implements Loadable, JoinEventListener, QuitEvent
} else {
p.getActiveScoreboard().getRegisteredUsers().remove(p);
}
p.setActiveScoreboard(null);
((ITabPlayer)p).setActiveScoreboard(null);
}
}
@@ -290,7 +293,7 @@ public class ScoreboardManager implements Loadable, JoinEventListener, QuitEvent
public boolean onPacketSend(TabPlayer receiver, PacketPlayOutScoreboardDisplayObjective packet) {
if (packet.slot == DisplaySlot && !packet.objectiveName.equals(ObjectiveName)) {
tab.debug("Player " + receiver.getName() + " received scoreboard called " + packet.objectiveName + ", hiding TAB one.");
receiver.setOtherPluginScoreboard(packet.objectiveName);
((ITabPlayer)receiver).setOtherPluginScoreboard(packet.objectiveName);
if (receiver.getActiveScoreboard() != null) {
tab.getCPUManager().runMeasuredTask("sending packets", TabFeature.SCOREBOARD, UsageType.ANTI_OVERRIDE, () -> receiver.getActiveScoreboard().unregister(receiver));
}
@@ -300,9 +303,9 @@ public class ScoreboardManager implements Loadable, JoinEventListener, QuitEvent
@Override
public void onPacketSend(TabPlayer receiver, PacketPlayOutScoreboardObjective packet) {
if (packet.method == 1 && receiver.getOtherPluginScoreboard() != null && receiver.getOtherPluginScoreboard().equals(packet.objectiveName)) {
if (packet.method == 1 && ((ITabPlayer)receiver).getOtherPluginScoreboard() != null && ((ITabPlayer)receiver).getOtherPluginScoreboard().equals(packet.objectiveName)) {
tab.debug("Player " + receiver.getName() + " no longer has another scoreboard, sending TAB one.");
receiver.setOtherPluginScoreboard(null);
((ITabPlayer)receiver).setOtherPluginScoreboard(null);
tab.getCPUManager().runMeasuredTask("sending packets", TabFeature.SCOREBOARD, UsageType.ANTI_OVERRIDE, () -> sendHighestScoreboard(receiver));
}
}
@@ -23,7 +23,7 @@ public abstract class StaticLine extends ScoreboardLine {
public StaticLine(Scoreboard parent, int lineNumber, String text, String forcedNameStart) {
super(parent, lineNumber);
this.text = TAB.getInstance().getPlaceholderManager().color(text);
String legacy = RGBUtils.getInstance().convertRGBtoLegacy(text);
String legacy = RGBUtils.getInstance().convertRGBtoLegacy(this.text);
//1.8+
String[] v1_8 = splitText(forcedNameStart, legacy, 40);
prefix = v1_8[0];
@@ -6,6 +6,7 @@ import java.util.List;
import java.util.Map;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.ITabPlayer;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.cpu.TabFeature;
import me.neznamy.tab.shared.cpu.UsageType;
@@ -71,11 +72,11 @@ public class Sorting {
@Override
public void run() {
for (TabPlayer p : tab.getPlayers()) {
if (!p.isLoaded() || p.getForcedTeamName() != null) continue;
if (!p.isLoaded() || p.getForcedTeamName() != null || p.hasTeamHandlingPaused()) continue;
String newName = getTeamName(p);
if (!p.getTeamName().equals(newName)) {
nametags.unregisterTeam(p);
p.setTeamName(newName);
((ITabPlayer) p).setTeamName(newName);
nametags.registerTeam(p);
}
}
@@ -108,10 +109,10 @@ public class Sorting {
* @return unique up to 16 character long sequence that sorts the player
*/
public String getTeamName(TabPlayer p) {
p.setTeamNameNote("");
((ITabPlayer) p).setTeamNameNote("");
StringBuilder sb = new StringBuilder();
for (SortingType type : sorting) {
sb.append(type.getChars(p));
sb.append(type.getChars((ITabPlayer) p));
}
if (sb.length() > 12) {
sb.setLength(12);
@@ -2,7 +2,7 @@ package me.neznamy.tab.shared.features.sorting.types;
import java.util.LinkedHashMap;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.ITabPlayer;
import me.neznamy.tab.shared.TAB;
/**
@@ -21,7 +21,7 @@ public class GroupPermission extends SortingType {
}
@Override
public String getChars(TabPlayer p) {
public String getChars(ITabPlayer p) {
String chars = null;
for (String localgroup : sortedGroups.keySet()) {
if (p.hasPermission("tab.sort." + localgroup)) {
@@ -2,7 +2,7 @@ package me.neznamy.tab.shared.features.sorting.types;
import java.util.LinkedHashMap;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.ITabPlayer;
import me.neznamy.tab.shared.TAB;
/**
@@ -21,13 +21,13 @@ public class Groups extends SortingType {
}
@Override
public String getChars(TabPlayer p) {
public String getChars(ITabPlayer p) {
String group = p.getGroup();
String chars = sortedGroups.get(group.toLowerCase());
if (chars == null) {
chars = String.valueOf(sortedGroups.size()+1);
if (!group.equals("<null>")) {
TAB.getInstance().getErrorManager().oneTimeConsoleError(String.format("Group \"&e%s&c\" is not defined in sorting list! This will result in players in that group not being sorted correctly. To fix this, add group \"&e%s&c\" into &egroup-sorting-priority-list in config.yml&c. Your current list: %s", group, group, sortedGroups.keySet()));
TAB.getInstance().getErrorManager().oneTimeConsoleError(String.format("Group \"%s\" is not defined in sorting list! This will result in players in that group not being sorted correctly. To fix this, add group \"%s\" into &egroup-sorting-priority-list in config.yml. Your current list: %s", group, group, sortedGroups.keySet()));
}
p.setTeamNameNote(p.getTeamNameNote() + "&cPlayer's primary group is not in sorting list. &r");
} else {
@@ -4,7 +4,7 @@ import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.ITabPlayer;
import me.neznamy.tab.shared.TAB;
/**
@@ -36,7 +36,7 @@ public class Placeholder extends SortingType {
}
@Override
public String getChars(TabPlayer p) {
public String getChars(ITabPlayer p) {
String output = setPlaceholders(p);
p.setTeamNameNote(p.getTeamNameNote() + "Placeholder returned \"" + output + "\". ");
if (output.contains("&")) output = output.replace('&', '\u00a7');
@@ -1,6 +1,6 @@
package me.neznamy.tab.shared.features.sorting.types;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.ITabPlayer;
/**
* Sorting by a placeholder alphabetically
@@ -16,7 +16,7 @@ public class PlaceholderAtoZ extends SortingType {
}
@Override
public String getChars(TabPlayer p) {
public String getChars(ITabPlayer p) {
String output = setPlaceholders(p);
p.setTeamNameNote(p.getTeamNameNote() + "Placeholder returned \"" + output + "\". ");
return output;
@@ -1,6 +1,6 @@
package me.neznamy.tab.shared.features.sorting.types;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.ITabPlayer;
import me.neznamy.tab.shared.TAB;
/**
@@ -17,7 +17,7 @@ public class PlaceholderHighToLow extends SortingType {
}
@Override
public String getChars(TabPlayer p) {
public String getChars(ITabPlayer p) {
String output = setPlaceholders(p);
p.setTeamNameNote(p.getTeamNameNote() + "Placeholder returned \"" + output + "\". ");
int intValue = TAB.getInstance().getErrorManager().parseInteger(output, 0, "numeric sorting placeholder");
@@ -1,6 +1,6 @@
package me.neznamy.tab.shared.features.sorting.types;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.ITabPlayer;
import me.neznamy.tab.shared.TAB;
/**
@@ -17,7 +17,7 @@ public class PlaceholderLowToHigh extends SortingType {
}
@Override
public String getChars(TabPlayer p) {
public String getChars(ITabPlayer p) {
String output = setPlaceholders(p);
p.setTeamNameNote(p.getTeamNameNote() + "Placeholder returned \"" + output + "\". ");
int intValue = TAB.getInstance().getErrorManager().parseInteger(output, 0, "numeric sorting placeholder");
@@ -1,6 +1,6 @@
package me.neznamy.tab.shared.features.sorting.types;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.ITabPlayer;
/**
* Sorting by a placeholder from Z to A
@@ -16,7 +16,7 @@ public class PlaceholderZtoA extends SortingType {
}
@Override
public String getChars(TabPlayer p) {
public String getChars(ITabPlayer p) {
char[] chars = setPlaceholders(p).toCharArray();
p.setTeamNameNote(p.getTeamNameNote() + "Placeholder returned \"" + new String(chars) + "\". ");
for (int i=0; i<chars.length; i++) {
@@ -5,6 +5,7 @@ import java.util.LinkedHashMap;
import java.util.List;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.ITabPlayer;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.placeholders.Placeholder;
@@ -79,5 +80,5 @@ public abstract class SortingType {
* @param p - player to get chars for
* @return an as-short-as-possible character sequence for unique sorting
*/
public abstract String getChars(TabPlayer p);
public abstract String getChars(ITabPlayer p);
}
@@ -14,4 +14,12 @@ public interface Loadable extends Feature {
* Unloads all players and sends clear packets
*/
public void unload();
/**
* Default override to the method in Feature interface to not need to define it in
* classes implementing only this interface as load/unload methods alone do not use this
*/
public default Object getFeatureType() {
return null;
}
}
@@ -161,6 +161,46 @@ public class IChatBaseComponent {
public boolean isObfuscated(){
return obfuscated == null ? false : obfuscated;
}
/**
* Returns value of bold
* @return value of bold
*/
public Boolean getBold(){
return bold;
}
/**
* Returns value of italic
* @return value of italic
*/
public Boolean getItalic(){
return italic;
}
/**
* Returns value of underlined
* @return value of underlined
*/
public Boolean getUnderlined(){
return underlined;
}
/**
* Returns value of strikethrough
* @return value of strikethrough
*/
public Boolean getStrikethrough(){
return strikethrough;
}
/**
* Returns value of obfuscation
* @return value of obfuscation
*/
public Boolean getObfuscated(){
return obfuscated;
}
/**
* Sets text of this component
@@ -281,7 +321,6 @@ public class IChatBaseComponent {
* @return self
*/
public IChatBaseComponent onClickChangePage(int newpage) {
if (ProtocolVersion.SERVER_VERSION.getMinorVersion() < 8) throw new UnsupportedOperationException("Not supported on <1.8");
return onClick(ClickAction.CHANGE_PAGE, String.valueOf(newpage));
}
@@ -1,7 +1,6 @@
package me.neznamy.tab.shared.packets;
import me.neznamy.tab.shared.ProtocolVersion;
import me.neznamy.tab.shared.rgb.RGBUtils;
/**
* An interface represending a platform-specific packet builder
@@ -79,15 +78,6 @@ public interface PacketBuilder {
* @throws Exception - when something fails
*/
public Object build(PacketPlayOutScoreboardTeam packet, ProtocolVersion clientVersion) throws Exception;
/**
* Constructs platform-specific PacketPlayOutTitle class based on custom packet class
* @param packet - custom packet to be built
* @param clientVersion - version of client to receive the packet
* @return platform-specific packet
* @throws Exception - when something fails
*/
public Object build(PacketPlayOutTitle packet, ProtocolVersion clientVersion) throws Exception;
/**
* Cuts given string to specified character length (or length-1 if last character is a color character) and translates RGB to legacy colors
@@ -97,7 +87,7 @@ public interface PacketBuilder {
*/
public default String cutTo(String string, int length) {
if (string == null) return "";
String legacyText = RGBUtils.getInstance().convertRGBtoLegacy(string);
String legacyText = IChatBaseComponent.optimizedComponent(string).toLegacyText();
if (legacyText.length() <= length) return legacyText;
if (legacyText.charAt(length-1) == '\u00a7') {
return legacyText.substring(0, length-1); //cutting one extra character to prevent prefix ending with "&"
@@ -1,124 +0,0 @@
package me.neznamy.tab.shared.packets;
import me.neznamy.tab.shared.ProtocolVersion;
import me.neznamy.tab.shared.TAB;
/**
* A class representing platform specific packet class
*/
public class PacketPlayOutTitle extends UniversalPacketPlayOut {
//packet action
public EnumTitleAction action;
//displayed text
public String text;
//ticks to spend fading in
public int fadeIn;
//ticks to stay
public int stay;
//ticks to spend fading out
public int fadeOut;
/**
* Constructs new instance with all arguments
* @param action - packet action
* @param text - displayed text
* @param fadeIn - ticks to spend fading in
* @param stay - ticks to stay
* @param fadeOut - ticks to spend fading out
*/
private PacketPlayOutTitle(EnumTitleAction action, String text, int fadeIn, int stay, int fadeOut) {
this.action = action;
this.text = text;
this.fadeIn = fadeIn;
this.stay = stay;
this.fadeOut = fadeOut;
}
/**
* Creates new packet with action set to TITLE with given text
* @param text - text to display
* @return Created packet with with TITLE action and given text
*/
public static PacketPlayOutTitle title(String text) {
return new PacketPlayOutTitle(EnumTitleAction.TITLE, text, 0, 0, 0);
}
/**
* Creates new packet with action set to SUBTITLE with given text.
* Note: subtitle only displays after title is sent. If you don't want any title, send a title packet with invisible text such as &r
* @param text - text to display
* @return Created packet with with0 SUBTITLE action and given text
*/
public static PacketPlayOutTitle subtitle(String text) {
return new PacketPlayOutTitle(EnumTitleAction.SUBTITLE, text, 0, 0, 0);
}
/**
* Creates new packet with action set to ACTIONBAR with given text.
* Note: This was added in 1.11
* @param text - text to display
* @return Created packet with with ACTIONBAR action and given text
*/
public static PacketPlayOutTitle actionbar(String text) {
if (ProtocolVersion.SERVER_VERSION.getMinorVersion() < 11) throw new IllegalStateException("Not supported on <1.11");
return new PacketPlayOutTitle(EnumTitleAction.ACTIONBAR, text, 0, 0, 0);
}
/**
* Creates new packet with action set to TIMES with given parameters
* @param fadeIn - ticks to fade in
* @param stay - ticks to stay
* @param fadeOut - ticks to fade out
* @return Created packet with TIMES action and given parameters
*/
public static PacketPlayOutTitle times(int fadeIn, int stay, int fadeOut) {
return new PacketPlayOutTitle(EnumTitleAction.TIMES, null, fadeIn, stay, fadeOut);
}
/**
* Clears current title/subtitle and prevents any new from appearing
* @return Created packet with CLEAR action
*/
public static PacketPlayOutTitle clear() {
return new PacketPlayOutTitle(EnumTitleAction.CLEAR, null, 0, 0, 0);
}
/**
* Resets title times to their original values and makes titles appear again if CLEAR was used before
* @return Created packet with RESET action
*/
public static PacketPlayOutTitle reset() {
return new PacketPlayOutTitle(EnumTitleAction.RESET, null, 0, 0, 0);
}
@Override
protected Object build(ProtocolVersion clientVersion) throws Exception {
return TAB.getInstance().getPacketBuilder().build(this, clientVersion);
}
/**
* An override to toString() method for better output
*/
@Override
public String toString() {
return String.format("PacketPlayOutTitle{action%s,text=%s,fadeIn=%s,stay=%s,fadeOut=%s}", action, text, fadeIn, stay, fadeOut);
}
/**
* List of possible packet actions
*/
public enum EnumTitleAction {
TITLE,
SUBTITLE,
ACTIONBAR,
TIMES,
CLEAR,
RESET;
}
}
@@ -36,10 +36,7 @@ public class LuckPerms implements PermissionPlugin, PrefixSuffixProvider {
return "<null>";
}
User user = api.getUserManager().getUser(p.getUniqueId());
if (user == null) {
TAB.getInstance().getErrorManager().printError("LuckPerms v" + version + " returned null user for " + p.getName() + ", uuid=" + p.getUniqueId() + ", online=" + p.isOnline() + ", func=getPrimaryGroup");
return "<null>";
}
if (user == null) return "<null>";
return user.getPrimaryGroup();
}
@@ -51,10 +48,7 @@ public class LuckPerms implements PermissionPlugin, PrefixSuffixProvider {
return new String[]{"<null>"};
}
User user = api.getUserManager().getUser(p.getUniqueId());
if (user == null) {
TAB.getInstance().getErrorManager().printError("LuckPerms v" + version + " returned null user for " + p.getName() + ", uuid=" + p.getUniqueId() + ", online=" + p.isOnline() + ", func=getAllGroups");
return new String[] {"<null>"};
}
if (user == null) return new String[] {"<null>"};
return user.getNodes().stream().filter(NodeType.INHERITANCE::matches).map(NodeType.INHERITANCE::cast).map(InheritanceNode::getGroupName).collect(Collectors.toSet()).toArray(new String[0]);
}
@@ -67,10 +61,7 @@ public class LuckPerms implements PermissionPlugin, PrefixSuffixProvider {
return "";
}
User user = api.getUserManager().getUser(p.getUniqueId());
if (user == null) {
TAB.getInstance().getErrorManager().printError("LuckPerms v" + version + " returned null user for " + p.getName() + ", uuid=" + p.getUniqueId() + ", online=" + p.isOnline() + ", func=getPrefix");
return "";
}
if (user == null) return "";
Optional<QueryOptions> options = LuckPermsProvider.get().getContextManager().getQueryOptions(user);
if (!options.isPresent()) return "";
String prefix = user.getCachedData().getMetaData(options.get()).getPrefix();
@@ -90,10 +81,7 @@ public class LuckPerms implements PermissionPlugin, PrefixSuffixProvider {
return "";
}
User user = api.getUserManager().getUser(p.getUniqueId());
if (user == null) {
TAB.getInstance().getErrorManager().printError("LuckPerms v" + version + " returned null user for " + p.getName() + ", uuid=" + p.getUniqueId() + ", online=" + p.isOnline() + ", func=getSuffix");
return "";
}
if (user == null) return "";
Optional<QueryOptions> options = LuckPermsProvider.get().getContextManager().getQueryOptions(user);
if (!options.isPresent()) return "";
String suffix = user.getCachedData().getMetaData(options.get()).getSuffix();
@@ -1,8 +1,8 @@
package me.neznamy.tab.shared.permission;
import java.util.HashSet;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.TAB;
@@ -49,7 +49,7 @@ public class UltraPermissions implements PermissionPlugin {
TAB.getInstance().getErrorManager().printError("UltraPermissions v" + version + " returned null user for " + p.getName() + " (" + p.getUniqueId() + ")");
return new String[]{"<null>"};
}
Set<String> groups = new HashSet<String>();
List<String> groups = new ArrayList<String>();
Object user = optUser.get();
Object activeGroups = user.getClass().getMethod("getActiveGroups").invoke(user);
Iterable<Object> bestToWorst = (Iterable<Object>) activeGroups.getClass().getMethod("bestToWorst").invoke(activeGroups);
@@ -36,25 +36,27 @@ public abstract class Placeholder {
if (!identifier.startsWith("%") || !identifier.endsWith("%")) throw new IllegalArgumentException("Identifier must start and end with %");
this.identifier = identifier;
this.refresh = refresh;
if (TAB.getInstance().getConfiguration().premiumconfig != null) {
Map<Object, Object> original = TAB.getInstance().getConfiguration().premiumconfig.getConfigurationSection("placeholder-output-replacements." + identifier);
for (Entry<Object, Object> entry : original.entrySet()) {
String key = entry.getKey().toString();
String value = entry.getValue().toString();
replacements.put(key.replace('&', '\u00a7'), value);
//snakeyaml converts yes & no to booleans, making them not work when used without "
if (key.equals("true")) {
replacements.put("yes", value);
}
if (key.equals("false")) {
replacements.put("no", value);
}
if (key.equals("else") && value.equals("%value%")) {
TAB.getInstance().print('9', "Hint: Placeholder " + identifier + " has configured \"else\" replacement to %value%, which is default behavior already. You can remove it for cleaner configuration.");
}
for (String id : TAB.getInstance().getPlaceholderManager().detectAll(entry.getValue().toString())) {
if (!outputPlaceholders.contains(id)) outputPlaceholders.add(id);
}
if (TAB.getInstance().isPremium()) loadReplacements();
}
private void loadReplacements() {
Map<Object, Object> original = TAB.getInstance().getConfiguration().premiumconfig.getConfigurationSection("placeholder-output-replacements." + identifier);
for (Entry<Object, Object> entry : original.entrySet()) {
String key = entry.getKey().toString();
String value = entry.getValue().toString();
replacements.put(key.replace('&', '\u00a7'), value);
//snakeyaml converts yes & no to booleans, making them not work when used without "
if (key.equals("true")) {
replacements.put("yes", value);
}
if (key.equals("false")) {
replacements.put("no", value);
}
if (key.equals("else") && value.equals("%value%")) {
TAB.getInstance().print('9', "Hint: Placeholder " + identifier + " has configured \"else\" replacement to %value%, which is default behavior already. You can remove it for cleaner configuration.");
}
for (String id : TAB.getInstance().getPlaceholderManager().detectAll(entry.getValue().toString())) {
if (!outputPlaceholders.contains(id)) outputPlaceholders.add(id);
}
}
}
@@ -40,7 +40,8 @@ public abstract class PlayerPlaceholder extends Placeholder {
if (newValue.equals(identifier) && !lastValue.containsKey(p.getName())) {
lastValue.put(p.getName(), identifier);
}
if (!newValue.equals("ERROR") && !newValue.equals(identifier) && (!lastValue.containsKey(p.getName()) || !lastValue.get(p.getName()).equals(newValue))) {
//using String.valueOf to remove one check and fix rare NPE caused by multi thread access
if (!newValue.equals("ERROR") && !newValue.equals(identifier) && !String.valueOf(lastValue.get(p.getName())).equals(newValue)) {
lastValue.put(p.getName(), newValue);
return true;
}
@@ -33,13 +33,13 @@ public abstract class SimpleCondition {
*/
static {
conditionTypes.put("permission:", PermissionCondition.class);
conditionTypes.put("!=", NotEqualsCondition.class);
conditionTypes.put("=", EqualsCondition.class);
conditionTypes.put("<-", ContainsCondition.class);
conditionTypes.put(">=", MoreThanOrEqualsCondition.class);
conditionTypes.put(">", MoreThanCondition.class);
conditionTypes.put("<=", LessThanOrEqualsCondition.class);
conditionTypes.put("<", LessThanCondition.class);
conditionTypes.put("!=", NotEqualsCondition.class);
conditionTypes.put("=", EqualsCondition.class);
}
/**
@@ -2,9 +2,12 @@ package me.neznamy.tab.shared.rgb;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.packets.EnumChatFormat;
import me.neznamy.tab.shared.packets.IChatBaseComponent;
import me.neznamy.tab.shared.rgb.format.BukkitFormat;
import me.neznamy.tab.shared.rgb.format.CMIFormat;
import me.neznamy.tab.shared.rgb.format.HtmlFormat;
@@ -29,6 +32,10 @@ public class RGBUtils {
//list of gradient patterns
private Set<GradientPattern> gradients = new HashSet<GradientPattern>();
//TAB's RGB format
private final Pattern tabPattern = Pattern.compile("#[0-9a-fA-F]{6}");
private final Pattern tabPatternLegacy = Pattern.compile("#[0-9a-fA-F]{6}\\|.");
public RGBUtils() {
registerRGBFormatter(new BukkitFormat());
@@ -66,6 +73,28 @@ public class RGBUtils {
return replaced;
}
public String convertToBukkitFormat(String text, boolean rgbClient) {
if (rgbClient) {
//converting random formats to TAB one
String replaced = applyFormats(text, false);
Matcher m = tabPatternLegacy.matcher(replaced);
while (m.find()) {
String hexcode = m.group();
String fixed = "&x&" + hexcode.charAt(1) + "&" + hexcode.charAt(2) + "&" + hexcode.charAt(3) + "&" + hexcode.charAt(4) + "&" + hexcode.charAt(5) + "&" + hexcode.charAt(6);
replaced = replaced.replace(hexcode, fixed.replace('&', '\u00a7'));
}
m = tabPattern.matcher(replaced);
while (m.find()) {
String hexcode = m.group();
String fixed = "&x&" + hexcode.charAt(1) + "&" + hexcode.charAt(2) + "&" + hexcode.charAt(3) + "&" + hexcode.charAt(4) + "&" + hexcode.charAt(5) + "&" + hexcode.charAt(6);
replaced = replaced.replace(hexcode, fixed.replace('&', '\u00a7'));
}
return replaced;
} else {
return IChatBaseComponent.fromColoredText(text).toLegacyText();
}
}
/**
* Registers RGB formatter
* @param formatter - formatter to register
@@ -96,7 +125,7 @@ public class RGBUtils {
char c = applied.charAt(i);
if (c == '#') {
try {
if (containsLegacyCode(text, i)) {
if (containsLegacyCode(applied, i)) {
sb.append(new TextColor(applied.substring(i, i+7), EnumChatFormat.getByChar(applied.charAt(i+8))).getLegacyColor().getFormat());
i += 8;
} else {
@@ -9,7 +9,7 @@ import java.util.regex.Pattern;
public class BukkitFormat extends RGBFormatter {
//pattern for &x&R&R&G&G&B&B
private final Pattern pattern = Pattern.compile("[\\\u00a7&]{1}x[[\\\u00a7&]{1}0-9a-fA-F]{12}");;
private final Pattern pattern = Pattern.compile("[\\\u00a7&]{1}x[[\\\u00a7&]{1}0-9a-fA-F]{12}");
@Override
public String reformat(String text) {
+1 -1
View File
@@ -1,12 +1,12 @@
#sorting type, having premium version automatically overrides sorting options from advancedconfig (if set)
#GROUPS = groups from config.yml, in that order
#GROUP_PERMISSIONS = ^, but players need tab.sort.<group> permission to be considered in that group
#TABPREFIX_A_TO_Z = alphabetically by tabprefix property
#PLACEHOLDER_LOW_TO_HIGH = insert a numeric placeholder below, sorting from lowest value to highest
#PLACEHOLDER_HIGH_TO_LOW = ^, highest to lowest, can be used for some kind of levelling system
#PLACEHOLDER_A_TO_Z = alphabetically by the placeholder
#GROUPS_THEN_PLACEHOLDER_HIGH_TO_LOW = primary sorting by groups, secondary by numeric placeholder (high to low)
#GROUPS_THEN_PLACEHOLDER_LOW_TO_HIGH = primary sorting by groups, secondary by numeric placeholder (low to high)
#... and more
sorting-type: GROUPS
sorting-placeholder: "%some_level_maybe?%"
+3 -61
View File
@@ -5,32 +5,19 @@
<parent>
<groupId>me.neznamy</groupId>
<artifactId>TAB</artifactId>
<version>2.8.11-pre16</version>
<version>2.9.0</version>
</parent>
<artifactId>velocity-1.1.0</artifactId>
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
<repository>
<id>velocity</id>
<url>https://nexus.velocitypowered.com/repository/maven-public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>
<!-- TAB Core -->
<dependency>
<groupId>me.neznamy</groupId>
@@ -38,37 +25,13 @@
<version>${project.version}</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>com.github.NEZNAMY</groupId>
<artifactId>YamlAssist</artifactId>
</exclusion>
<exclusion>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.j2objc</groupId>
<artifactId>j2objc-annotations</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.errorprone</groupId>
<artifactId>error_prone_annotations</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>listenablefuture</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>failureaccess</artifactId>
</exclusion>
<exclusion>
<groupId>org.checkerframework</groupId>
<artifactId>checker-qual</artifactId>
<groupId>com.github.NEZNAMY</groupId>
<artifactId>YamlAssist</artifactId>
</exclusion>
</exclusions>
</dependency>
@@ -104,10 +67,6 @@
<groupId>org.spongepowered</groupId>
<artifactId>configurate-yaml</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</exclusion>
<exclusion>
<groupId>net.kyori</groupId>
<artifactId>
@@ -162,10 +121,6 @@
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
@@ -180,18 +135,5 @@
<version>2.2.1</version>
<scope>compile</scope>
</dependency>
<!-- Missing velocity packets -->
<dependency>
<groupId>com.github.NEZNAMY</groupId>
<artifactId>VelocityPacketInjector</artifactId>
<version>1.0.0_fix</version>
<exclusions>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>
@@ -16,7 +16,7 @@ import com.velocitypowered.api.plugin.Plugin;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ProxyServer;
import me.neznamy.injector.VelocityPacketRegistry;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.ProtocolVersion;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.features.PluginMessageHandler;
@@ -55,10 +55,6 @@ public class Main {
System.out.println("\u00a7c[TAB] The plugin requires Velocity 1.1.0 and up to work. Get it at https://velocitypowered.com/downloads");
return;
}
if (!new VelocityPacketRegistry().registerPackets()) {
System.out.println("\u00a7c[TAB] Your velocity version is way too new for this plugin version. Update the plugin or downgrade Velocity.");
return;
}
if (server.getConfiguration().isOnlineMode()) {
System.out.println("\u00a76[TAB] If you experience tablist prefix/suffix not working and global playerlist duplicating players, toggle "
+ "\"use-online-uuid-in-tablist\" option in config.yml (set it to opposite value).");
@@ -112,14 +108,23 @@ public class Main {
sender.sendMessage(Identity.nil(), Component.text(message.replace('&', '\u00a7')));
}
} else {
TAB.getInstance().command.execute(sender instanceof Player ? TAB.getInstance().getPlayer(((Player)sender).getUniqueId()) : null, args);
TabPlayer p = null;
if (sender instanceof Player) {
p = TAB.getInstance().getPlayer(((Player)sender).getUniqueId());
if (p == null) return; //player not loaded correctly
}
TAB.getInstance().command.execute(p, args);
}
}
@Override
public List<String> suggest(CommandSource sender, String[] args) {
if (TAB.getInstance().isDisabled()) return new ArrayList<String>();
return TAB.getInstance().command.complete(sender instanceof Player ? TAB.getInstance().getPlayer(((Player)sender).getUniqueId()) : null, args);
TabPlayer p = null;
if (sender instanceof Player) {
p = TAB.getInstance().getPlayer(((Player)sender).getUniqueId());
if (p == null) return new ArrayList<String>(); //player not loaded correctly
}
return TAB.getInstance().command.complete(p, args);
}
}
}
@@ -1,34 +1,15 @@
package me.neznamy.tab.platforms.velocity.v1_1_0;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import com.velocitypowered.proxy.protocol.packet.ScoreboardDisplay;
import com.velocitypowered.proxy.protocol.packet.ScoreboardObjective;
import com.velocitypowered.proxy.protocol.packet.ScoreboardObjective.HealthDisplay;
import com.velocitypowered.proxy.protocol.packet.ScoreboardScore;
import com.velocitypowered.proxy.protocol.packet.Team;
import me.neznamy.tab.shared.ProtocolVersion;
import me.neznamy.tab.shared.packets.EnumChatFormat;
import me.neznamy.tab.shared.packets.IChatBaseComponent;
import me.neznamy.tab.shared.packets.PacketBuilder;
import me.neznamy.tab.shared.packets.PacketPlayOutBoss;
import me.neznamy.tab.shared.packets.PacketPlayOutChat;
import me.neznamy.tab.shared.packets.PacketPlayOutPlayerInfo;
import me.neznamy.tab.shared.packets.PacketPlayOutPlayerInfo.EnumGamemode;
import me.neznamy.tab.shared.packets.PacketPlayOutPlayerInfo.EnumPlayerInfoAction;
import me.neznamy.tab.shared.packets.PacketPlayOutPlayerInfo.PlayerInfoData;
import me.neznamy.tab.shared.packets.PacketPlayOutPlayerListHeaderFooter;
import me.neznamy.tab.shared.packets.PacketPlayOutScoreboardDisplayObjective;
import me.neznamy.tab.shared.packets.PacketPlayOutScoreboardObjective;
import me.neznamy.tab.shared.packets.PacketPlayOutScoreboardObjective.EnumScoreboardHealthDisplay;
import me.neznamy.tab.shared.packets.PacketPlayOutScoreboardScore;
import me.neznamy.tab.shared.packets.PacketPlayOutScoreboardTeam;
import me.neznamy.tab.shared.packets.PacketPlayOutTitle;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
/**
* Packet builder for Velocity platform
@@ -46,20 +27,8 @@ public class VelocityPacketBuilder implements PacketBuilder {
}
@Override
public Object build(PacketPlayOutPlayerInfo packet, ProtocolVersion clientVersion) throws Exception {
List<Object> items = new ArrayList<Object>();
for (PlayerInfoData data : packet.entries) {
Object item = Class.forName("com.velocitypowered.proxy.protocol.packet.PlayerListItem$Item").getConstructor(UUID.class).newInstance(data.uniqueId);
item.getClass().getMethod("setDisplayName", Component.class).invoke(item, data.displayName == null ? null : Main.stringToComponent(data.displayName.toString(clientVersion)));
if (data.gameMode != null) {
item.getClass().getMethod("setGameMode", int.class).invoke(item, data.gameMode.ordinal()-1);
}
item.getClass().getMethod("setLatency", int.class).invoke(item, data.latency);
item.getClass().getMethod("setProperties", List.class).invoke(item, data.skin);
item.getClass().getMethod("setName", String.class).invoke(item, data.name);
items.add(item);
}
return Class.forName("com.velocitypowered.proxy.protocol.packet.PlayerListItem").getConstructor(int.class, List.class).newInstance(packet.action.ordinal(), items);
public Object build(PacketPlayOutPlayerInfo packet, ProtocolVersion clientVersion) {
return packet;
}
@Override
@@ -69,79 +38,36 @@ public class VelocityPacketBuilder implements PacketBuilder {
@Override
public Object build(PacketPlayOutScoreboardDisplayObjective packet, ProtocolVersion clientVersion) {
return new ScoreboardDisplay((byte)packet.slot, packet.objectiveName);
return null;
}
@Override
public Object build(PacketPlayOutScoreboardObjective packet, ProtocolVersion clientVersion) {
return new ScoreboardObjective(packet.objectiveName, jsonOrCut(packet.displayName, clientVersion, 32), packet.renderType == null ? null : HealthDisplay.valueOf(packet.renderType.toString()), (byte)packet.method);
return null;
}
@Override
public Object build(PacketPlayOutScoreboardScore packet, ProtocolVersion clientVersion) {
return new ScoreboardScore(packet.player, (byte) packet.action.ordinal(), packet.objectiveName, packet.score);
return null;
}
@Override
public Object build(PacketPlayOutScoreboardTeam packet, ProtocolVersion clientVersion) {
int color = 0;
if (clientVersion.getMinorVersion() >= 13) {
color = (packet.color != null ? packet.color : EnumChatFormat.lastColorsOf(packet.playerPrefix)).getNetworkId();
}
return new Team(packet.name, (byte)packet.method, jsonOrCut(packet.name, clientVersion, 16), jsonOrCut(packet.playerPrefix, clientVersion, 16), jsonOrCut(packet.playerSuffix, clientVersion, 16),
packet.nametagVisibility, packet.collisionRule, color, (byte)packet.options, packet.players.toArray(new String[0]));
return null;
}
@Override
public Object build(PacketPlayOutTitle packet, ProtocolVersion clientVersion) throws Exception {
Object velocityPacket = Class.forName("com.velocitypowered.proxy.protocol.packet.TitlePacket").getConstructor().newInstance();
int actionId = packet.action.ordinal();
if (clientVersion.getNetworkId() <= ProtocolVersion.v1_10_2.getNetworkId() && actionId >= 2) {
actionId--;
}
velocityPacket.getClass().getMethod("setAction", int.class).invoke(velocityPacket, actionId);
if (packet.text != null) velocityPacket.getClass().getMethod("setComponent", String.class).invoke(velocityPacket, IChatBaseComponent.optimizedComponent(packet.text).toString(clientVersion));
velocityPacket.getClass().getMethod("setFadeIn", int.class).invoke(velocityPacket, packet.fadeIn);
velocityPacket.getClass().getMethod("setStay", int.class).invoke(velocityPacket, packet.stay);
velocityPacket.getClass().getMethod("setFadeOut", int.class).invoke(velocityPacket, packet.fadeOut);
return velocityPacket;
}
@SuppressWarnings("unchecked")
@Override
public PacketPlayOutPlayerInfo readPlayerInfo(Object packet, ProtocolVersion clientVersion) throws Exception{
List<PlayerInfoData> listData = new ArrayList<PlayerInfoData>();
for (Object item : (List<Object>) packet.getClass().getMethod("getItems").invoke(packet)) {
Component displayNameComponent = (Component) item.getClass().getMethod("getDisplayName").invoke(item);
String displayName = displayNameComponent == null ? null : GsonComponentSerializer.gson().serialize(displayNameComponent);
listData.add(new PlayerInfoData(
(String) item.getClass().getMethod("getName").invoke(item),
(UUID) item.getClass().getMethod("getUuid").invoke(item),
item.getClass().getMethod("getProperties").invoke(item),
(int) item.getClass().getMethod("getLatency").invoke(item),
EnumGamemode.values()[(int)item.getClass().getMethod("getGameMode").invoke(item)+1],
displayName == null ? null : IChatBaseComponent.fromString(displayName)
)
);
}
return new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.values()[(int) (packet.getClass().getMethod("getAction").invoke(packet))], listData);
public PacketPlayOutPlayerInfo readPlayerInfo(Object packet, ProtocolVersion clientVersion) {
return null;
}
@Override
public PacketPlayOutScoreboardObjective readObjective(Object bungeePacket, ProtocolVersion clientVersion) throws Exception {
ScoreboardObjective packet = (ScoreboardObjective) bungeePacket;
String title;
if (clientVersion.getMinorVersion() >= 13) {
title = packet.value == null ? null : IChatBaseComponent.fromString(packet.value).toLegacyText();
} else {
title = packet.value;
}
EnumScoreboardHealthDisplay renderType = (packet.type == null ? null : EnumScoreboardHealthDisplay.valueOf(packet.type.toString().toUpperCase()));
return new PacketPlayOutScoreboardObjective(packet.action, packet.name, title, renderType);
public PacketPlayOutScoreboardObjective readObjective(Object packet, ProtocolVersion clientVersion) {
return null;
}
@Override
public PacketPlayOutScoreboardDisplayObjective readDisplayObjective(Object bungeePacket, ProtocolVersion clientVersion) throws Exception {
return new PacketPlayOutScoreboardDisplayObjective(((ScoreboardDisplay) bungeePacket).position, ((ScoreboardDisplay) bungeePacket).name);
public PacketPlayOutScoreboardDisplayObjective readDisplayObjective(Object packet, ProtocolVersion clientVersion) {
return null;
}
}
@@ -1,110 +0,0 @@
package me.neznamy.tab.platforms.velocity.v1_1_0;
import java.util.Collection;
import com.google.common.collect.Lists;
import com.velocitypowered.proxy.protocol.packet.Team;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.cpu.TabFeature;
import me.neznamy.tab.shared.cpu.UsageType;
import me.neznamy.tab.shared.features.PipelineInjector;
public class VelocityPipelineInjector extends PipelineInjector {
//handler to inject before
private final String INJECT_POSITION = "handler";
/**
* Constructs new instance with given parameter
* @param tab - tab instance
*/
public VelocityPipelineInjector(TAB tab) {
super(tab);
}
@Override
public void inject(TabPlayer player) {
if (player.getVersion().getMinorVersion() < 8) return;
uninject(player);
player.getChannel().pipeline().addBefore(INJECT_POSITION, DECODER_NAME, new VelocityChannelDuplexHandler(player));
}
@Override
public void uninject(TabPlayer player) {
if (player.getVersion().getMinorVersion() < 8) return;
if (player.getChannel().pipeline().names().contains(DECODER_NAME)) player.getChannel().pipeline().remove(DECODER_NAME);
}
/**
* Removes all real players from packet if the packet doesn't come from TAB
* @param packet - packet to modify
*/
private void modifyPlayers(Team packet){
if (!tab.getFeatureManager().isFeatureEnabled("nametag16")) return;
long time = System.nanoTime();
if (packet.players == null) return;
if (packet.getFriendlyFire() != 69) {
Collection<String> col = Lists.newArrayList(packet.getPlayers());
for (TabPlayer p : tab.getPlayers()) {
if (col.contains(p.getName()) && !tab.getFeatureManager().getNameTagFeature().isDisabledWorld(p.getWorldName())) {
logTeamOverride(packet.name, p.getName());
col.remove(p.getName());
}
}
packet.players = col.toArray(new String[0]);
}
tab.getCPUManager().addTime(TabFeature.NAMETAGS, UsageType.ANTI_OVERRIDE, System.nanoTime()-time);
}
/**
* Custom channel duplex handler override
*/
public class VelocityChannelDuplexHandler extends ChannelDuplexHandler {
//injected player
private TabPlayer player;
/**
* Constructs new instance with given player
* @param player - player to inject
*/
public VelocityChannelDuplexHandler(TabPlayer player) {
this.player = player;
}
@Override
public void write(ChannelHandlerContext context, Object packet, ChannelPromise channelPromise) throws Exception {
try {
switch (packet.getClass().getSimpleName()) {
case "PlayerListItem":
super.write(context, tab.getFeatureManager().onPacketPlayOutPlayerInfo(player, packet), channelPromise);
return;
case "Team":
if (antiOverrideTeams) modifyPlayers((Team) packet);
break;
case "JoinGame":
//making sure to not send own packets before join packet is actually sent
super.write(context, packet, channelPromise);
tab.getFeatureManager().onLoginPacket(player);
return;
case "ScoreboardDisplay":
if (antiOverrideObjectives && tab.getFeatureManager().onDisplayObjective(player, packet)) return;
break;
case "ScoreboardObjective":
if (antiOverrideObjectives) tab.getFeatureManager().onObjective(player, packet);
break;
default:
break;
}
} 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);
}
}
}
@@ -6,8 +6,11 @@ import java.util.List;
import com.velocitypowered.api.proxy.ProxyServer;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.placeholders.Placeholder;
import me.neznamy.tab.shared.placeholders.PlaceholderRegistry;
import me.neznamy.tab.shared.placeholders.PlayerPlaceholder;
import me.neznamy.tab.shared.placeholders.ServerPlaceholder;
/**
@@ -36,6 +39,24 @@ public class VelocityPlaceholderRegistry implements PlaceholderRegistry {
}
});
}
placeholders.add(new PlayerPlaceholder("%canseeonline%", 2000) {
public String get(TabPlayer p) {
int var = 0;
for (TabPlayer all : TAB.getInstance().getPlayers()){
if (!all.isVanished() || p.hasPermission("tab.seevanished")) var++;
}
return String.valueOf(var);
}
});
placeholders.add(new PlayerPlaceholder("%canseestaffonline%", 2000) {
public String get(TabPlayer p) {
int var = 0;
for (TabPlayer all : TAB.getInstance().getPlayers()){
if (all.isStaff() && (!all.isVanished() || p.hasPermission("tab.seevanished"))) var++;
}
return String.valueOf(var);
}
});
return placeholders;
}
}
@@ -10,7 +10,6 @@ import me.neznamy.tab.api.event.VelocityTABLoadEvent;
import me.neznamy.tab.shared.Platform;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.features.GlobalPlayerlist;
import me.neznamy.tab.shared.features.NameTag;
import me.neznamy.tab.shared.features.PlaceholderManager;
import me.neznamy.tab.shared.permission.LuckPerms;
import me.neznamy.tab.shared.permission.PermissionPlugin;
@@ -38,7 +37,9 @@ public class VelocityPlatform implements Platform {
@Override
public PermissionPlugin detectPermissionPlugin() {
if (server.getPluginManager().getPlugin("luckperms").isPresent()) {
if (TAB.getInstance().getConfiguration().bukkitPermissions) {
return new VaultBridge(Main.plm);
} else if (server.getPluginManager().getPlugin("luckperms").isPresent()) {
return new LuckPerms(server.getPluginManager().getPlugin("luckperms").get().getDescription().getVersion().get());
} else {
return new VaultBridge(Main.plm);
@@ -46,13 +47,11 @@ public class VelocityPlatform implements Platform {
}
@Override
public void loadFeatures() throws Exception{
public void loadFeatures() {
TAB tab = TAB.getInstance();
tab.getPlaceholderManager().addRegistry(new VelocityPlaceholderRegistry(server));
tab.getPlaceholderManager().addRegistry(new UniversalPlaceholderRegistry());
tab.getPlaceholderManager().registerPlaceholders();
if (tab.getConfiguration().pipelineInjection) tab.getFeatureManager().registerFeature("injection", new VelocityPipelineInjector(tab));
if (tab.getConfiguration().config.getBoolean("change-nametag-prefix-suffix", true)) tab.getFeatureManager().registerFeature("nametag16", new NameTag(tab));
loadUniversalFeatures();
if (tab.getConfiguration().config.getBoolean("global-playerlist.enabled", false)) tab.getFeatureManager().registerFeature("globalplayerlist", new GlobalPlayerlist(tab));
for (Player p : server.getAllPlayers()) {
@@ -109,4 +108,9 @@ public class VelocityPlatform implements Platform {
public int getMaxPlayers() {
return server.getConfiguration().getShowMaxPlayers();
}
@Override
public String getConfigName() {
return "velocityconfig.yml";
}
}
@@ -3,21 +3,25 @@ package me.neznamy.tab.platforms.velocity.v1_1_0;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.player.TabListEntry;
import com.velocitypowered.api.util.GameProfile;
import com.velocitypowered.api.util.GameProfile.Property;
import io.netty.channel.Channel;
import me.neznamy.tab.shared.ITabPlayer;
import me.neznamy.tab.shared.ProtocolVersion;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.packets.IChatBaseComponent;
import me.neznamy.tab.shared.packets.PacketPlayOutBoss;
import me.neznamy.tab.shared.packets.PacketPlayOutChat;
import me.neznamy.tab.shared.packets.PacketPlayOutPlayerInfo;
import me.neznamy.tab.shared.packets.PacketPlayOutPlayerInfo.PlayerInfoData;
import me.neznamy.tab.shared.packets.PacketPlayOutPlayerListHeaderFooter;
import me.neznamy.tab.shared.packets.UniversalPacketPlayOut;
import net.kyori.adventure.audience.MessageType;
import net.kyori.adventure.bossbar.BossBar;
import net.kyori.adventure.bossbar.BossBar.Color;
@@ -28,13 +32,13 @@ import net.kyori.adventure.identity.Identity;
/**
* TabPlayer for Velocity
*/
public class VelocityTabPlayer extends ITabPlayer{
public class VelocityTabPlayer extends ITabPlayer {
//the velocity player
private Player player;
//offline uuid used in tablist
private UUID offlineId;
// uuid used in tablist
private UUID tablistId;
//player's visible boss bars
private Map<UUID, BossBar> bossbars = new HashMap<UUID, BossBar>();
@@ -42,9 +46,8 @@ public class VelocityTabPlayer extends ITabPlayer{
/**
* Constructs new instance for given player
* @param p - velocity player
* @throws Exception - when reflection fails
*/
public VelocityTabPlayer(Player p) throws Exception {
public VelocityTabPlayer(Player p) {
player = p;
if (p.getCurrentServer().isPresent()) {
world = p.getCurrentServer().get().getServerInfo().getName();
@@ -52,17 +55,22 @@ public class VelocityTabPlayer extends ITabPlayer{
//tab reload while a player is connecting, how unfortunate
world = "<null>";
}
Object minecraftConnection = player.getClass().getMethod("getConnection").invoke(player);
channel = (Channel) minecraftConnection.getClass().getMethod("getChannel").invoke(minecraftConnection);
name = p.getUsername();
uniqueId = p.getUniqueId();
offlineId = UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(StandardCharsets.UTF_8));
UUID offlineId = UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(StandardCharsets.UTF_8));
tablistId = TAB.getInstance().getConfiguration().config.getBoolean("use-online-uuid-in-tablist", true) ? uniqueId : offlineId;
version = ProtocolVersion.fromNetworkId(player.getProtocolVersion().getProtocol());
init();
}
@Override
public boolean hasPermission(String permission) {
if (TAB.getInstance().getConfiguration().bukkitPermissions) {
String merge = "hasPermission:" + permission;
Main.plm.requestAttribute(this, merge);
if (!attributes.containsKey(merge)) return false;
return Boolean.parseBoolean(attributes.get(merge));
}
return player.hasPermission(permission);
}
@@ -74,58 +82,103 @@ public class VelocityTabPlayer extends ITabPlayer{
@Override
public void sendPacket(Object packet) {
if (packet == null || !player.isActive()) return;
if (packet instanceof UniversalPacketPlayOut){
handleCustomPacket((UniversalPacketPlayOut) packet);
return;
}
channel.writeAndFlush(packet, channel.voidPromise());
}
private void handleCustomPacket(UniversalPacketPlayOut packet) {
if (packet instanceof PacketPlayOutChat){
player.sendMessage(Identity.nil(), Main.stringToComponent(((PacketPlayOutChat)packet).message.toString(getVersion())), MessageType.valueOf(((PacketPlayOutChat)packet).type.name()));
handle((PacketPlayOutChat) packet);
}
if (packet instanceof PacketPlayOutPlayerListHeaderFooter) {
player.getTabList().setHeaderAndFooter(Main.stringToComponent(((PacketPlayOutPlayerListHeaderFooter) packet).header.toString(getVersion())), Main.stringToComponent(((PacketPlayOutPlayerListHeaderFooter) packet).footer.toString(getVersion())));
handle((PacketPlayOutPlayerListHeaderFooter) packet);
}
if (packet instanceof PacketPlayOutBoss) {
PacketPlayOutBoss boss = (PacketPlayOutBoss) packet;
Set<Flag> flags;
BossBar bar;
switch (boss.operation) {
case ADD:
flags = new HashSet<Flag>();
if (boss.createWorldFog) flags.add(Flag.CREATE_WORLD_FOG);
if (boss.darkenScreen) flags.add(Flag.DARKEN_SCREEN);
if (boss.playMusic) flags.add(Flag.PLAY_BOSS_MUSIC);
bar = BossBar.bossBar(Main.stringToComponent(IChatBaseComponent.optimizedComponent(boss.name).toString(getVersion())), boss.pct, Color.valueOf(boss.color.toString()), Overlay.valueOf(boss.overlay.toString()), flags);
bossbars.put(boss.id, bar);
player.showBossBar(bar);
handle((PacketPlayOutBoss) packet);
}
if (packet instanceof PacketPlayOutPlayerInfo) {
handle((PacketPlayOutPlayerInfo) packet);
}
}
private void handle(PacketPlayOutChat packet) {
player.sendMessage(Identity.nil(), Main.stringToComponent(packet.message.toString(getVersion())), MessageType.valueOf(packet.type.name()));
}
private void handle(PacketPlayOutPlayerListHeaderFooter packet) {
player.getTabList().setHeaderAndFooter(Main.stringToComponent(packet.header.toString(getVersion())), Main.stringToComponent(packet.footer.toString(getVersion())));
}
private void handle(PacketPlayOutBoss packet) {
Set<Flag> flags = new HashSet<Flag>();
BossBar bar;
switch (packet.operation) {
case ADD:
if (packet.createWorldFog) flags.add(Flag.CREATE_WORLD_FOG);
if (packet.darkenScreen) flags.add(Flag.DARKEN_SCREEN);
if (packet.playMusic) flags.add(Flag.PLAY_BOSS_MUSIC);
bar = BossBar.bossBar(Main.stringToComponent(IChatBaseComponent.optimizedComponent(packet.name).toString(getVersion())),
packet.pct,
Color.valueOf(packet.color.toString()),
Overlay.valueOf(packet.overlay.toString()),
flags);
bossbars.put(packet.id, bar);
player.showBossBar(bar);
break;
case REMOVE:
player.hideBossBar(bossbars.get(packet.id));
bossbars.remove(packet.id);
break;
case UPDATE_PCT:
bossbars.get(packet.id).percent(packet.pct);
break;
case UPDATE_NAME:
bossbars.get(packet.id).name(Main.stringToComponent(IChatBaseComponent.optimizedComponent(packet.name).toString(getVersion())));
break;
case UPDATE_STYLE:
bar = bossbars.get(packet.id);
//compensating for an already fixed bug for those who did not update Velocity
player.hideBossBar(bar);
bar.overlay(Overlay.valueOf(packet.overlay.toString()));
bar.color(Color.valueOf(packet.color.toString()));
player.showBossBar(bar);
break;
case UPDATE_PROPERTIES:
if (packet.createWorldFog) flags.add(Flag.CREATE_WORLD_FOG);
if (packet.darkenScreen) flags.add(Flag.DARKEN_SCREEN);
if (packet.playMusic) flags.add(Flag.PLAY_BOSS_MUSIC);
bossbars.get(packet.id).flags(flags);
break;
default:
break;
}
}
@SuppressWarnings("unchecked")
private void handle(PacketPlayOutPlayerInfo packet) {
for (PlayerInfoData data : packet.entries) {
switch (packet.action) {
case ADD_PLAYER:
player.getTabList().addEntry(TabListEntry.builder()
.tabList(player.getTabList())
.displayName(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)
.build());
break;
case REMOVE:
bossbars.remove(boss.id);
player.hideBossBar(bossbars.get(boss.id));
case REMOVE_PLAYER:
player.getTabList().removeEntry(data.uniqueId);
break;
case UPDATE_PCT:
bossbars.get(boss.id).percent(boss.pct);
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())));
}
break;
case UPDATE_NAME:
bossbars.get(boss.id).name(Main.stringToComponent(IChatBaseComponent.optimizedComponent(boss.name).toString(getVersion())));
case UPDATE_LATENCY:
for (TabListEntry entry : player.getTabList().getEntries()) {
if (entry.getProfile().getId().equals(data.uniqueId)) entry.setLatency(data.latency);
}
break;
case UPDATE_STYLE:
bar = bossbars.get(boss.id);
//compensating for an already fixed bug for those who did not update Velocity
player.hideBossBar(bar);
bar.overlay(Overlay.valueOf(boss.overlay.toString()));
bar.color(Color.valueOf(boss.color.toString()));
player.showBossBar(bar);
break;
case UPDATE_PROPERTIES:
flags = new HashSet<Flag>();
if (boss.createWorldFog) flags.add(Flag.CREATE_WORLD_FOG);
if (boss.darkenScreen) flags.add(Flag.DARKEN_SCREEN);
if (boss.playMusic) flags.add(Flag.PLAY_BOSS_MUSIC);
bossbars.get(boss.id).flags(flags);
case UPDATE_GAME_MODE:
for (TabListEntry entry : player.getTabList().getEntries()) {
if (entry.getProfile().getId().equals(data.uniqueId)) entry.setGameMode(data.gameMode.ordinal()-1);
}
break;
default:
break;
@@ -145,9 +198,16 @@ public class VelocityTabPlayer extends ITabPlayer{
@Override
public UUID getTablistUUID() {
return TAB.getInstance().getConfiguration().config.getBoolean("use-online-uuid-in-tablist", true) ? uniqueId : offlineId;
return tablistId;
}
@Override
public boolean isVanished() {
Main.plm.requestAttribute(this, "vanished");
if (!attributes.containsKey("vanished")) return false;
return Boolean.parseBoolean(attributes.get("vanished"));
}
@Override
public boolean isDisguised() {
Main.plm.requestAttribute(this, "disguised");
@@ -161,9 +221,14 @@ public class VelocityTabPlayer extends ITabPlayer{
if (!attributes.containsKey("invisible")) return false;
return Boolean.parseBoolean(attributes.get("invisible"));
}
@Override
public boolean isOnline() {
return player.isActive();
}
@Override
public int getGamemode() {
return 0; //shrug
}
}
@@ -1,7 +1,8 @@
# Detailed explanation of all options available at https://github.com/NEZNAMY/TAB/wiki/config.yml
#changing nametags, affecting sorting, collision rule
change-nametag-prefix-suffix: true
#taking permission nodes and groups from backend servers
use-bukkit-permissions-manager: false
#prefix/suffix in tablist
change-tablist-prefix-suffix: true