mirror of
https://github.com/NEZNAMY/TAB.git
synced 2026-11-13 12:42:06 -05:00
Compare commits
100
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
09dc8cd437 | ||
|
|
c613ba401b | ||
|
|
866df0b5cf | ||
|
|
8f2b56ba05 | ||
|
|
2049885f11 | ||
|
|
4caef337d5 | ||
|
|
a644792bf6 | ||
|
|
54c7f8fc6a | ||
|
|
2e59b87bbe | ||
|
|
f89242ad8f | ||
|
|
845903788c | ||
|
|
53a9047c20 | ||
|
|
a2b74bbc30 | ||
|
|
50ef93cc45 | ||
|
|
e2a5da9c14 | ||
|
|
bf31116d0d | ||
|
|
d79fa8c4f3 | ||
|
|
87e0a7bea3 | ||
|
|
b34cabd55c | ||
|
|
704bd36c77 | ||
|
|
5c2c4d0f4b | ||
|
|
80cca5cb34 | ||
|
|
dcd603f2f5 | ||
|
|
1bee3b49bf | ||
|
|
11bcccb8f9 | ||
|
|
7425493706 | ||
|
|
dca0cfd424 | ||
|
|
21314def89 | ||
|
|
90e544d279 | ||
|
|
89e21558a1 | ||
|
|
b28cc51457 | ||
|
|
2d0a203b5f | ||
|
|
2948666c1d | ||
|
|
b2a2659546 | ||
|
|
e2eb7102c9 | ||
|
|
56301e653b | ||
|
|
1d825e08d2 | ||
|
|
c81a27709c | ||
|
|
2b143172f8 | ||
|
|
84330ec6eb | ||
|
|
0bd703de7f | ||
|
|
e6a55b7d5c | ||
|
|
b6ec7631d2 | ||
|
|
5abbd00d63 | ||
|
|
515c94976e | ||
|
|
912adad8f6 | ||
|
|
70fdd193a3 | ||
|
|
9d83e968fc | ||
|
|
04329da133 | ||
|
|
19ccfbb1a6 | ||
|
|
c53ab09abc | ||
|
|
a4d8daac1d | ||
|
|
99d566d521 | ||
|
|
aa37f73161 | ||
|
|
087518378d | ||
|
|
913d27929b | ||
|
|
530d39bec5 | ||
|
|
cf70dc3845 | ||
|
|
d1421fee3f | ||
|
|
3ec490b36e | ||
|
|
ee42685179 | ||
|
|
e02d687771 | ||
|
|
dddb592253 | ||
|
|
d0ad88d317 | ||
|
|
3d3ce0151f | ||
|
|
f017b0e562 | ||
|
|
4ba2bb669b | ||
|
|
9fc2424736 | ||
|
|
980c01ea70 | ||
|
|
758edcaf5c | ||
|
|
950f825e31 | ||
|
|
0a985f5c78 | ||
|
|
58353f4e6d | ||
|
|
c3d2b5c4b0 | ||
|
|
c2764b4b8a | ||
|
|
9bc8ad0d23 | ||
|
|
488c3540a8 | ||
|
|
1d03950a64 | ||
|
|
e24ea7df2e | ||
|
|
fe5e3d6405 | ||
|
|
db8584e40b | ||
|
|
2e4db38d1a | ||
|
|
f82470c1b1 | ||
|
|
650cc93fc0 | ||
|
|
e61070307a | ||
|
|
2fa46867e5 | ||
|
|
636b2e760a | ||
|
|
8cecf46310 | ||
|
|
a7bcda7eba | ||
|
|
a610dd2c70 | ||
|
|
df98c77a48 | ||
|
|
331dc33c86 | ||
|
|
8493b37171 | ||
|
|
2449c46165 | ||
|
|
a642c2d344 | ||
|
|
88c7b988e7 | ||
|
|
36651260c6 | ||
|
|
6c0072dc54 | ||
|
|
e38f5a77c0 | ||
|
|
6443926a79 |
No files matched your search
@@ -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']
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -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());
|
||||
|
||||
+46
-118
@@ -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());
|
||||
}
|
||||
|
||||
+4
-4
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+10
-10
@@ -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
|
||||
|
||||
+11
-7
@@ -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) {
|
||||
|
||||
+7
-3
@@ -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;
|
||||
|
||||
+19
-7
@@ -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
-2
@@ -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 {
|
||||
|
||||
+4
-9
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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>
|
||||
|
||||
+4
-17
@@ -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());
|
||||
}
|
||||
}
|
||||
+61
-33
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+16
-15
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -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
@@ -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>
|
||||
|
||||
@@ -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
@@ -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(() -> {
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
+16
-13
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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
-2
@@ -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');
|
||||
|
||||
+2
-2
@@ -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;
|
||||
|
||||
+2
-2
@@ -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");
|
||||
|
||||
+2
-2
@@ -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");
|
||||
|
||||
+2
-2
@@ -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;
|
||||
}
|
||||
|
||||
+2
-2
@@ -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,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
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
-86
@@ -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;
|
||||
}
|
||||
}
|
||||
-110
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+21
@@ -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;
|
||||
}
|
||||
}
|
||||
+9
-5
@@ -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";
|
||||
}
|
||||
}
|
||||
+120
-55
@@ -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
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -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
|
||||
Reference in new issue
Block a user