mirror of
https://github.com/NEZNAMY/TAB.git
synced 2026-11-13 12:42:06 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c231220b42 | ||
|
|
1c6e5bec73 | ||
|
|
8919aaad94 | ||
|
|
ff6a2fe734 | ||
|
|
5ca4f7e411 | ||
|
|
2c105718b0 | ||
|
|
9cc471f66f | ||
|
|
e18867c938 | ||
|
|
27bd942c4c | ||
|
|
234ca72e73 | ||
|
|
f35a09a34d | ||
|
|
fa6d06a4ac | ||
|
|
ec6daeeadb | ||
|
|
f24f25f071 | ||
|
|
dbf0e3af9f | ||
|
|
6ecb607c0b | ||
|
|
1bf6b00be0 | ||
|
|
4b4f52e39a | ||
|
|
1170efbe02 | ||
|
|
3e86e73fed | ||
|
|
dd43861572 | ||
|
|
61a19ca9e0 | ||
|
|
d02af31e7c | ||
|
|
ab7b88b67b | ||
|
|
b80c816c5a | ||
|
|
c0ad6f49e7 | ||
|
|
91a56a8c2c | ||
|
|
135a473dc5 | ||
|
|
a8b53b07e4 | ||
|
|
171cbd4497 | ||
|
|
a1383612bc | ||
|
|
fe798c19f3 | ||
|
|
ead3add4cc | ||
|
|
db13c2d1c5 | ||
|
|
f2daab4b80 | ||
|
|
6fd02c83ab | ||
|
|
c288a0503a | ||
|
|
2e2b65a4bb | ||
|
|
982d0a53f9 | ||
|
|
f89ecfb595 | ||
|
|
bddb96a5fa | ||
|
|
39b29d12e4 | ||
|
|
6cb1e2c06d | ||
|
|
d932a9a862 | ||
|
|
341b552d0b | ||
|
|
1586bd9768 | ||
|
|
e8dde3a756 | ||
|
|
bb591bf56d | ||
|
|
8cf83b276a | ||
|
|
a1547a7288 | ||
|
|
0722403a23 | ||
|
|
cd4a91d975 | ||
|
|
c7870b4e9d | ||
|
|
239dae5a65 | ||
|
|
13c89d18d7 | ||
|
|
c5dc42eafe | ||
|
|
59b3faab1e | ||
|
|
b88beb5002 | ||
|
|
9fea35c25d | ||
|
|
372013bcc6 | ||
|
|
20ca58b570 | ||
|
|
9c4cca20fb | ||
|
|
6b8536a86e | ||
|
|
3b41857637 | ||
|
|
fa78ac2157 | ||
|
|
0a0bb9c83c | ||
|
|
36834a039e | ||
|
|
4960c898bb | ||
|
|
af61edbc5c | ||
|
|
237bfc08a1 | ||
|
|
032e9a089d | ||
|
|
ba83779dde | ||
|
|
267d72f844 | ||
|
|
b533cdb89f | ||
|
|
3f118ac76b | ||
|
|
08a8f0097c | ||
|
|
c7a3599e46 | ||
|
|
62f80baa69 |
No files matched your search
@@ -0,0 +1,36 @@
|
||||
name: Build
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
jobs:
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
|
||||
- name: Set up JDK 11
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 11
|
||||
- name: Cache SonarCloud packages
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.sonar/cache
|
||||
key: ${{ runner.os }}-sonar
|
||||
restore-keys: ${{ runner.os }}-sonar
|
||||
- name: Cache Maven packages
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.m2
|
||||
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
|
||||
restore-keys: ${{ runner.os }}-m2
|
||||
- name: Build and analyze
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
|
||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||
run: mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar
|
||||
@@ -4,8 +4,8 @@ It's already been a year and I still can't see any positives of it. This way I j
|
||||
|
||||
|
||||
## Compiling
|
||||
Plugin can be compiled using maven. Once you've purchased the premium version, you can enable premium features by setting [this line to return true](https://github.com/NEZNAMY/TAB/blob/master/shared/src/main/java/me/neznamy/tab/shared/TAB.java#L78) and apply your code improvements. Enabling it without purchasing the plugin may result in the features not working correctly.
|
||||
**No support is provided for self-compiled jars, only for official compilations.** If you compiled it yourself, it is highly likely you modified something, which might be the reason why is the plugin not working. If you didn't modify anything, you can just get the plugin from official download places.
|
||||
Plugin can be compiled using maven. Once you've purchased the premium version, you can enable premium features by setting [this line to return true](https://github.com/NEZNAMY/TAB/blob/master/shared/src/main/java/me/neznamy/tab/shared/TAB.java#L82) and apply your code improvements. Enabling it without purchasing the plugin may result in the features not working correctly.
|
||||
**No support is provided for self-compiled jars, only for official compilations.** If you compiled it yourself, it is highly likely you modified something, which might be the reason why is the plugin not working. If you didn't modify anything, you can just get the plugin from official download locations.
|
||||
|
||||
|
||||
## Links
|
||||
@@ -34,8 +34,8 @@ Discord invite link: https://discord.gg/EaSvdk6
|
||||
<!-- TAB -->
|
||||
<dependency>
|
||||
<groupId>com.github.NEZNAMY</groupId>
|
||||
<artifactId>TAB-API</artifactId>
|
||||
<version>2.8.10</version>
|
||||
<artifactId>TAB</artifactId>
|
||||
<version>2.9.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
```
|
||||
```
|
||||
+14
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>me.neznamy</groupId>
|
||||
<artifactId>TAB</artifactId>
|
||||
<version>2.9.0</version>
|
||||
<version>2.9.2</version>
|
||||
</parent>
|
||||
<artifactId>bukkit</artifactId>
|
||||
|
||||
@@ -54,6 +54,10 @@
|
||||
<groupId>com.github.NEZNAMY</groupId>
|
||||
<artifactId>YamlAssist</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.googlecode.json-simple</groupId>
|
||||
<artifactId>json-simple</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
@@ -133,5 +137,14 @@
|
||||
<version>1.11</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- Bukkit Metrics -->
|
||||
<dependency>
|
||||
<groupId>org.bstats</groupId>
|
||||
<artifactId>bstats-bukkit</artifactId>
|
||||
<version>2.2.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -32,7 +32,22 @@ public class BukkitEventListener implements Listener {
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onJoin(PlayerJoinEvent e) {
|
||||
if (TAB.getInstance().isDisabled()) return;
|
||||
TAB.getInstance().getCPUManager().runTask("processing PlayerJoinEvent", () -> TAB.getInstance().getFeatureManager().onJoin(new BukkitTabPlayer(e.getPlayer())));
|
||||
TAB.getInstance().getCPUManager().runTask("processing PlayerJoinEvent", () -> {
|
||||
try {
|
||||
int i = 0;
|
||||
int version;
|
||||
while ((version = Main.getProtocolVersion(e.getPlayer())) == -1 && ++i < 100) {
|
||||
Thread.sleep(2);
|
||||
}
|
||||
if (!e.getPlayer().isOnline()) return;
|
||||
if (i == 50) {
|
||||
TAB.getInstance().getErrorManager().printError("Failed to get protocol version of " + e.getPlayer().getName() + " after 50 retries");
|
||||
}
|
||||
TAB.getInstance().getFeatureManager().onJoin(new BukkitTabPlayer(e.getPlayer(), version));
|
||||
} catch (InterruptedException pluginDisabled) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,193 +0,0 @@
|
||||
package me.neznamy.tab.platforms.bukkit;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.plugin.RegisteredServiceProvider;
|
||||
import org.bukkit.plugin.ServicePriority;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import me.neznamy.tab.platforms.bukkit.nms.NMSStorage;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.features.Metrics;
|
||||
|
||||
/**
|
||||
* bStats metrics for bukkit
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class BukkitMetrics extends Metrics {
|
||||
|
||||
private Main plugin;
|
||||
|
||||
public BukkitMetrics(Main plugin) {
|
||||
super("https://bStats.org/submitData/bukkit");
|
||||
if (plugin == null) {
|
||||
throw new IllegalArgumentException("Plugin cannot be null!");
|
||||
}
|
||||
this.plugin = plugin;
|
||||
|
||||
// Get the config file
|
||||
File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats");
|
||||
File configFile = new File(bStatsFolder, "config.yml");
|
||||
YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile);
|
||||
if (!config.isSet("serverUuid")) {
|
||||
config.addDefault("enabled", true);
|
||||
config.addDefault("serverUuid", UUID.randomUUID().toString());
|
||||
config.addDefault("logFailedRequests", false);
|
||||
config.addDefault("logSentData", false);
|
||||
config.addDefault("logResponseStatusText", false);
|
||||
config.options().header(
|
||||
"bStats collects some data for plugin authors like how many servers are using their plugins.\n" +
|
||||
"To honor their work, you should not disable it.\n" +
|
||||
"This has nearly no effect on the server performance!\n" +
|
||||
"Check out https://bStats.org/ to learn more :)"
|
||||
).copyDefaults(true);
|
||||
try {
|
||||
config.save(configFile);
|
||||
} catch (IOException ignored) { }
|
||||
}
|
||||
|
||||
// Load the data
|
||||
enabled = config.getBoolean("enabled", true);
|
||||
serverUUID = config.getString("serverUuid");
|
||||
logFailedRequests = config.getBoolean("logFailedRequests", false);
|
||||
logSentData = config.getBoolean("logSentData", false);
|
||||
logResponseStatusText = config.getBoolean("logResponseStatusText", false);
|
||||
|
||||
if (enabled) {
|
||||
boolean found = false;
|
||||
// Search for all other bStats Metrics classes to see if we are the first one
|
||||
for (Class<?> service : Bukkit.getServicesManager().getKnownServices()) {
|
||||
try {
|
||||
service.getField("B_STATS_VERSION"); // Our identifier :)
|
||||
found = true; // We aren't the first
|
||||
break;
|
||||
} catch (NoSuchFieldException ignored) { }
|
||||
}
|
||||
// Register our service
|
||||
Bukkit.getServicesManager().register(BukkitMetrics.class, this, plugin, ServicePriority.Normal);
|
||||
if (!found) {
|
||||
// We are the first!
|
||||
startSubmitting();
|
||||
}
|
||||
}
|
||||
addCustomChart(new SimplePie("unlimited_nametag_mode_enabled", new Callable<String>() {
|
||||
public String call() {
|
||||
return TAB.getInstance().getFeatureManager().isFeatureEnabled("nametagx") ? "Yes" : "No";
|
||||
}
|
||||
}));
|
||||
addCustomChart(new SimplePie("placeholderapi", new Callable<String>() {
|
||||
public String call() {
|
||||
return Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI") ? "Yes" : "No";
|
||||
}
|
||||
}));
|
||||
addCustomChart(new SimplePie("permission_system", new Callable<String>() {
|
||||
public String call() {
|
||||
return TAB.getInstance().getPermissionPlugin().getName();
|
||||
}
|
||||
}));
|
||||
addCustomChart(new SimplePie("server_version", new Callable<String>() {
|
||||
public String call() {
|
||||
return "1." + NMSStorage.getInstance().minorVersion + ".x";
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private void startSubmitting() {
|
||||
Timer timer = new Timer(true); // We use a timer cause the Bukkit scheduler is affected by server lags
|
||||
timer.scheduleAtFixedRate(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!plugin.isEnabled()) { // Plugin was disabled
|
||||
timer.cancel();
|
||||
return;
|
||||
}
|
||||
// Nevertheless we want our code to run in the Bukkit main thread, so we have to use the Bukkit scheduler
|
||||
// Don't be afraid! The connection to the bStats server is still async, only the stats collection is sync ;)
|
||||
Bukkit.getScheduler().runTask(plugin, () -> submitData());
|
||||
}
|
||||
}, 1000*60*5, 1000*60*30);
|
||||
// Submit the data every 30 minutes, first time after 5 minutes to give other plugins enough time to start
|
||||
// WARNING: Changing the frequency has no effect but your plugin WILL be blocked/deleted!
|
||||
// WARNING: Just don't do it!
|
||||
}
|
||||
|
||||
private JSONObject getServerData() {
|
||||
// Minecraft specific data
|
||||
int playerAmount = TAB.getInstance().getPlayers().size();
|
||||
int onlineMode = Bukkit.getOnlineMode() ? 1 : 0;
|
||||
String bukkitVersion = Bukkit.getVersion();
|
||||
|
||||
// OS/Java specific data
|
||||
String javaVersion = System.getProperty("java.version");
|
||||
String osName = System.getProperty("os.name");
|
||||
String osArch = System.getProperty("os.arch");
|
||||
String osVersion = System.getProperty("os.version");
|
||||
int coreCount = Runtime.getRuntime().availableProcessors();
|
||||
|
||||
JSONObject data = new JSONObject();
|
||||
|
||||
data.put("serverUUID", serverUUID);
|
||||
|
||||
data.put("playerAmount", playerAmount);
|
||||
data.put("onlineMode", onlineMode);
|
||||
data.put("bukkitVersion", bukkitVersion);
|
||||
|
||||
data.put("javaVersion", javaVersion);
|
||||
data.put("osName", osName);
|
||||
data.put("osArch", osArch);
|
||||
data.put("osVersion", osVersion);
|
||||
data.put("coreCount", coreCount);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
private void submitData() {
|
||||
JSONObject data = getServerData();
|
||||
|
||||
JSONArray pluginData = new JSONArray();
|
||||
// Search for all other bStats Metrics classes to get their plugin data
|
||||
for (Class<?> service : Bukkit.getServicesManager().getKnownServices()) {
|
||||
try {
|
||||
service.getField("B_STATS_VERSION"); // Our identifier :)
|
||||
|
||||
for (RegisteredServiceProvider<?> provider : Bukkit.getServicesManager().getRegistrations(service)) {
|
||||
try {
|
||||
pluginData.add(provider.getService().getMethod("getPluginData").invoke(provider.getProvider()));
|
||||
} catch (NullPointerException ignored) {
|
||||
} catch (NoSuchMethodException ignored) {
|
||||
} catch (IllegalAccessException ignored) {
|
||||
} catch (InvocationTargetException ignored) {
|
||||
}
|
||||
}
|
||||
} catch (NoSuchFieldException ignored) { }
|
||||
}
|
||||
|
||||
data.put("plugins", pluginData);
|
||||
|
||||
// Create a new thread for the connection to the bStats server
|
||||
new Thread(new Runnable() {
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
// Send the data
|
||||
sendData(data, logResponseStatusText);
|
||||
} catch (Throwable e) {
|
||||
// Something went wrong! :(
|
||||
if (logFailedRequests) {
|
||||
plugin.getLogger().log(Level.WARNING, "Could not submit plugin stats of " + plugin.getName(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,12 @@
|
||||
package me.neznamy.tab.platforms.bukkit;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
@@ -42,14 +43,14 @@ import me.neznamy.tab.shared.packets.PacketPlayOutScoreboardScore;
|
||||
import me.neznamy.tab.shared.packets.PacketPlayOutScoreboardTeam;
|
||||
import me.neznamy.tab.shared.rgb.TextColor;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public class BukkitPacketBuilder implements PacketBuilder {
|
||||
|
||||
//nms storage
|
||||
private NMSStorage nms;
|
||||
|
||||
//entity type ids
|
||||
private Map<EntityType, Integer> entityIds = new HashMap<EntityType, Integer>();
|
||||
private EnumMap<EntityType, Integer> entityIds = new EnumMap<>(EntityType.class);
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameter
|
||||
@@ -57,20 +58,20 @@ public class BukkitPacketBuilder implements PacketBuilder {
|
||||
*/
|
||||
public BukkitPacketBuilder(NMSStorage nms) {
|
||||
this.nms = nms;
|
||||
if (nms.minorVersion >= 13) {
|
||||
if (nms.getMinorVersion() >= 13) {
|
||||
entityIds.put(EntityType.ARMOR_STAND, 1);
|
||||
entityIds.put(EntityType.WITHER, 83);
|
||||
} else {
|
||||
entityIds.put(EntityType.WITHER, 64);
|
||||
if (nms.minorVersion >= 8){
|
||||
if (nms.getMinorVersion() >= 8){
|
||||
entityIds.put(EntityType.ARMOR_STAND, 30);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object build(PacketPlayOutBoss packet, ProtocolVersion clientVersion) throws Exception {
|
||||
if (nms.minorVersion >= 9) {
|
||||
public Object build(PacketPlayOutBoss packet, ProtocolVersion clientVersion) throws InstantiationException, IllegalAccessException, InvocationTargetException {
|
||||
if (nms.getMinorVersion() >= 9) {
|
||||
//1.9+ server, handled using bukkit api
|
||||
return packet;
|
||||
}
|
||||
@@ -89,34 +90,33 @@ public class BukkitPacketBuilder implements PacketBuilder {
|
||||
* @param packet - packet to build
|
||||
* @param clientVersion - client version
|
||||
* @return bytebuf with 1.9 bossbar packet content
|
||||
* @throws Exception - if something fails
|
||||
*/
|
||||
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 || clientVersion.getMinorVersion() >= 17 ? 0x0D : 0x0C);
|
||||
Type.UUID.write(buf, packet.id);
|
||||
Type.VAR_INT.writePrimitive(buf, packet.operation.ordinal());
|
||||
switch (packet.operation) {
|
||||
Type.UUID.write(buf, packet.getId());
|
||||
Type.VAR_INT.writePrimitive(buf, packet.getOperation().ordinal());
|
||||
switch (packet.getOperation()) {
|
||||
case ADD:
|
||||
Type.COMPONENT.write(buf, JsonParser.parseString(IChatBaseComponent.optimizedComponent(packet.name).toString(clientVersion)));
|
||||
Type.FLOAT.writePrimitive(buf, packet.pct);
|
||||
Type.VAR_INT.writePrimitive(buf, packet.color.ordinal());
|
||||
Type.VAR_INT.writePrimitive(buf, packet.overlay.ordinal());
|
||||
Type.COMPONENT.write(buf, JsonParser.parseString(IChatBaseComponent.optimizedComponent(packet.getName()).toString(clientVersion)));
|
||||
Type.FLOAT.writePrimitive(buf, packet.getPct());
|
||||
Type.VAR_INT.writePrimitive(buf, packet.getColor().ordinal());
|
||||
Type.VAR_INT.writePrimitive(buf, packet.getOverlay().ordinal());
|
||||
Type.BYTE.write(buf, packet.getFlags());
|
||||
break;
|
||||
case REMOVE:
|
||||
break;
|
||||
case UPDATE_PCT:
|
||||
Type.FLOAT.writePrimitive(buf, packet.pct);
|
||||
Type.FLOAT.writePrimitive(buf, packet.getPct());
|
||||
break;
|
||||
case UPDATE_NAME:
|
||||
Type.COMPONENT.write(buf, JsonParser.parseString(IChatBaseComponent.optimizedComponent(packet.name).toString(clientVersion)));
|
||||
Type.COMPONENT.write(buf, JsonParser.parseString(IChatBaseComponent.optimizedComponent(packet.getName()).toString(clientVersion)));
|
||||
break;
|
||||
case UPDATE_STYLE:
|
||||
Type.VAR_INT.writePrimitive(buf, packet.color.ordinal());
|
||||
Type.VAR_INT.writePrimitive(buf, packet.overlay.ordinal());
|
||||
Type.VAR_INT.writePrimitive(buf, packet.getColor().ordinal());
|
||||
Type.VAR_INT.writePrimitive(buf, packet.getOverlay().ordinal());
|
||||
break;
|
||||
case UPDATE_PROPERTIES:
|
||||
Type.BYTE.write(buf, packet.getFlags());
|
||||
@@ -125,7 +125,7 @@ public class BukkitPacketBuilder implements PacketBuilder {
|
||||
break;
|
||||
}
|
||||
return buf;
|
||||
} catch (Throwable t) {
|
||||
} catch (Exception t) {
|
||||
return TAB.getInstance().getErrorManager().printError(null, "Failed to create 1.9 bossbar packet using ViaVersion v" + Bukkit.getPluginManager().getPlugin("ViaVersion").getDescription().getVersion() + ". Is it the latest version?", t);
|
||||
}
|
||||
}
|
||||
@@ -135,25 +135,27 @@ public class BukkitPacketBuilder implements PacketBuilder {
|
||||
* @param packet - packet to build
|
||||
* @param clientVersion - client version
|
||||
* @return entity bossbar packet
|
||||
* @throws Exception - if something fails
|
||||
* @throws InvocationTargetException
|
||||
* @throws IllegalAccessException
|
||||
* @throws InstantiationException
|
||||
*/
|
||||
private Object buildBossPacketEntity(PacketPlayOutBoss packet, ProtocolVersion clientVersion) throws Exception {
|
||||
if (packet.operation == Action.UPDATE_STYLE) return null; //nothing to do here
|
||||
private Object buildBossPacketEntity(PacketPlayOutBoss packet, ProtocolVersion clientVersion) throws InstantiationException, IllegalAccessException, InvocationTargetException {
|
||||
if (packet.getOperation() == Action.UPDATE_STYLE) return null; //nothing to do here
|
||||
|
||||
int entityId = Math.abs(packet.id.hashCode());
|
||||
if (packet.operation == Action.REMOVE) {
|
||||
int entityId = packet.getId().hashCode();
|
||||
if (packet.getOperation() == Action.REMOVE) {
|
||||
return buildEntityDestroyPacket(entityId);
|
||||
}
|
||||
DataWatcher w = new DataWatcher();
|
||||
if (packet.operation == Action.UPDATE_PCT || packet.operation == Action.ADD) {
|
||||
float health = (float)300*packet.pct;
|
||||
if (packet.getOperation() == Action.UPDATE_PCT || packet.getOperation() == Action.ADD) {
|
||||
float health = 300*packet.getPct();
|
||||
if (health == 0) health = 1;
|
||||
w.helper().setHealth(health);
|
||||
}
|
||||
if (packet.operation == Action.UPDATE_NAME || packet.operation == Action.ADD) {
|
||||
w.helper().setCustomName(packet.name, clientVersion);
|
||||
if (packet.getOperation() == Action.UPDATE_NAME || packet.getOperation() == Action.ADD) {
|
||||
w.helper().setCustomName(packet.getName(), clientVersion);
|
||||
}
|
||||
if (packet.operation == Action.ADD) {
|
||||
if (packet.getOperation() == Action.ADD) {
|
||||
w.helper().setEntityFlags((byte) 32);
|
||||
return buildEntitySpawnPacket(entityId, null, EntityType.WITHER, new Location(null, 0,0,0), w);
|
||||
} else {
|
||||
@@ -162,152 +164,176 @@ public class BukkitPacketBuilder implements PacketBuilder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object build(PacketPlayOutChat packet, ProtocolVersion clientVersion) throws Exception {
|
||||
Object component = stringToComponent(packet.message.toString(clientVersion));
|
||||
if (nms.minorVersion >= 16) {
|
||||
return nms.newPacketPlayOutChat.newInstance(component, ((Object[])nms.ChatMessageType.getMethod("values").invoke(null))[packet.type.ordinal()], UUID.randomUUID());
|
||||
public Object build(PacketPlayOutChat packet, ProtocolVersion clientVersion) throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException, SecurityException {
|
||||
Object component = stringToComponent(packet.getMessage().toString(clientVersion));
|
||||
Constructor<?> c = nms.getConstructor("PacketPlayOutChat");
|
||||
if (nms.getMinorVersion() >= 16) {
|
||||
return c.newInstance(component, nms.getEnum("ChatMessageType")[packet.getType().ordinal()], UUID.randomUUID());
|
||||
}
|
||||
if (nms.minorVersion >= 12) {
|
||||
return nms.newPacketPlayOutChat.newInstance(component, Enum.valueOf(nms.ChatMessageType, packet.type.toString()));
|
||||
if (nms.getMinorVersion() >= 12) {
|
||||
return c.newInstance(component, Enum.valueOf((Class<Enum>) nms.getClass("ChatMessageType"), packet.getType().toString()));
|
||||
}
|
||||
if (nms.minorVersion >= 8) {
|
||||
return nms.newPacketPlayOutChat.newInstance(component, (byte) packet.type.ordinal());
|
||||
if (nms.getMinorVersion() >= 8) {
|
||||
return c.newInstance(component, (byte) packet.getType().ordinal());
|
||||
}
|
||||
if (nms.minorVersion == 7) {
|
||||
return nms.newPacketPlayOutChat.newInstance(component);
|
||||
if (nms.getMinorVersion() == 7) {
|
||||
return c.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(((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) {
|
||||
GameProfile profile = new GameProfile(data.uniqueId, data.name);
|
||||
public Object build(PacketPlayOutPlayerInfo packet, ProtocolVersion clientVersion) throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, SecurityException, NegativeArraySizeException {
|
||||
if (nms.getMinorVersion() < 8) return null;
|
||||
Object nmsPacket = nms.getConstructor("PacketPlayOutPlayerInfo").newInstance(nms.getEnum("EnumPlayerInfoAction")[packet.getAction().ordinal()], Array.newInstance(nms.getClass("EntityPlayer"), 0));
|
||||
List<Object> items = new ArrayList<>();
|
||||
for (PlayerInfoData data : packet.getEntries()) {
|
||||
GameProfile profile = new GameProfile(data.getUniqueId(), data.getName());
|
||||
|
||||
if (data.skin != null) profile.getProperties().putAll((PropertyMap) data.skin);
|
||||
List<Object> parameters = new ArrayList<Object>();
|
||||
if (nms.newPlayerInfoData.getParameterCount() == 5) {
|
||||
if (data.getSkin() != null) profile.getProperties().putAll((PropertyMap) data.getSkin());
|
||||
List<Object> parameters = new ArrayList<>();
|
||||
if (nms.getConstructor("PlayerInfoData").getParameterCount() == 5) {
|
||||
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()));
|
||||
parameters.add(data.getLatency());
|
||||
parameters.add(data.getGameMode() == null ? null : nms.getEnum("EnumGamemode")[nms.getEnum("EnumGamemode").length-EnumGamemode.values().length+data.getGameMode().ordinal()]); //not_set was removed in 1.17
|
||||
parameters.add(data.getDisplayName() == null ? null : toNMSComponent(data.getDisplayName(), clientVersion));
|
||||
items.add(nms.getConstructor("PlayerInfoData").newInstance(parameters.toArray()));
|
||||
}
|
||||
nms.PacketPlayOutPlayerInfo_PLAYERS.set(nmsPacket, items);
|
||||
nms.setField(nmsPacket, "PacketPlayOutPlayerInfo_PLAYERS", items);
|
||||
return nmsPacket;
|
||||
}
|
||||
|
||||
@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));
|
||||
public Object build(PacketPlayOutPlayerListHeaderFooter packet, ProtocolVersion clientVersion) throws InstantiationException, IllegalAccessException, InvocationTargetException {
|
||||
if (nms.getMinorVersion() < 8) return null;
|
||||
if (nms.getMinorVersion() >= 17) {
|
||||
return nms.getConstructor("PacketPlayOutPlayerListHeaderFooter").newInstance(toNMSComponent(packet.getHeader(), clientVersion), toNMSComponent(packet.getFooter(), clientVersion));
|
||||
}
|
||||
Object nmsPacket = nms.newPacketPlayOutPlayerListHeaderFooter.newInstance();
|
||||
nms.PacketPlayOutPlayerListHeaderFooter_HEADER.set(nmsPacket, toNMSComponent(packet.header, clientVersion));
|
||||
nms.PacketPlayOutPlayerListHeaderFooter_FOOTER.set(nmsPacket, toNMSComponent(packet.footer, clientVersion));
|
||||
Object nmsPacket = nms.getConstructor("PacketPlayOutPlayerListHeaderFooter").newInstance();
|
||||
nms.setField(nmsPacket, "PacketPlayOutPlayerListHeaderFooter_HEADER", toNMSComponent(packet.getHeader(), clientVersion));
|
||||
nms.setField(nmsPacket, "PacketPlayOutPlayerListHeaderFooter_FOOTER", toNMSComponent(packet.getFooter(), clientVersion));
|
||||
return nmsPacket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object build(PacketPlayOutScoreboardDisplayObjective packet, ProtocolVersion clientVersion) throws Exception {
|
||||
return nms.newPacketPlayOutScoreboardDisplayObjective.newInstance(packet.slot, newScoreboardObjective(packet.objectiveName));
|
||||
public Object build(PacketPlayOutScoreboardDisplayObjective packet, ProtocolVersion clientVersion) throws InstantiationException, IllegalAccessException, InvocationTargetException {
|
||||
return nms.getConstructor("PacketPlayOutScoreboardDisplayObjective").newInstance(packet.getSlot(), newScoreboardObjective(packet.getObjectiveName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object build(PacketPlayOutScoreboardObjective packet, ProtocolVersion clientVersion) throws Exception {
|
||||
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,
|
||||
public Object build(PacketPlayOutScoreboardObjective packet, ProtocolVersion clientVersion) throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, SecurityException {
|
||||
String displayName = clientVersion.getMinorVersion() < 13 ? cutTo(packet.getDisplayName(), 32) : packet.getDisplayName();
|
||||
if (nms.getMinorVersion() >= 13) {
|
||||
return nms.getConstructor("PacketPlayOutScoreboardObjective").newInstance(nms.getConstructor("ScoreboardObjective").newInstance(null, packet.getObjectiveName(), null,
|
||||
toNMSComponent(IChatBaseComponent.optimizedComponent(displayName), clientVersion),
|
||||
packet.renderType == null ? null : ((Object[])nms.EnumScoreboardHealthDisplay.getMethod("values").invoke(null))[packet.renderType.ordinal()]),
|
||||
packet.method);
|
||||
packet.getRenderType() == null ? null : nms.getEnum("EnumScoreboardHealthDisplay")[packet.getRenderType().ordinal()]),
|
||||
packet.getMethod());
|
||||
}
|
||||
|
||||
Object nmsPacket = nms.newPacketPlayOutScoreboardObjective.newInstance();
|
||||
nms.PacketPlayOutScoreboardObjective_OBJECTIVENAME.set(nmsPacket, packet.objectiveName);
|
||||
nms.PacketPlayOutScoreboardObjective_DISPLAYNAME.set(nmsPacket, displayName);
|
||||
if (nms.PacketPlayOutScoreboardObjective_RENDERTYPE != null && packet.renderType != null) {
|
||||
nms.PacketPlayOutScoreboardObjective_RENDERTYPE.set(nmsPacket, Enum.valueOf(nms.EnumScoreboardHealthDisplay, packet.renderType.toString()));
|
||||
Object nmsPacket = nms.getConstructor("PacketPlayOutScoreboardObjective").newInstance();
|
||||
nms.setField(nmsPacket, "PacketPlayOutScoreboardObjective_OBJECTIVENAME", packet.getObjectiveName());
|
||||
nms.setField(nmsPacket, "PacketPlayOutScoreboardObjective_DISPLAYNAME", displayName);
|
||||
if (nms.getMinorVersion() >= 8 && packet.getRenderType() != null) {
|
||||
nms.setField(nmsPacket, "PacketPlayOutScoreboardObjective_RENDERTYPE", Enum.valueOf((Class<Enum>) nms.getClass("EnumScoreboardHealthDisplay"), packet.getRenderType().toString()));
|
||||
}
|
||||
nms.PacketPlayOutScoreboardObjective_METHOD.set(nmsPacket, packet.method);
|
||||
nms.setField(nmsPacket, "PacketPlayOutScoreboardObjective_METHOD", packet.getMethod());
|
||||
return nmsPacket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object build(PacketPlayOutScoreboardScore packet, ProtocolVersion clientVersion) throws Exception {
|
||||
if (nms.minorVersion >= 13) {
|
||||
return nms.newPacketPlayOutScoreboardScore_1_13.newInstance(((Object[])nms.EnumScoreboardAction.getMethod("values").invoke(null))[packet.action.ordinal()], packet.objectiveName, packet.player, packet.score);
|
||||
public Object build(PacketPlayOutScoreboardScore packet, ProtocolVersion clientVersion) throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, SecurityException {
|
||||
if (nms.getMinorVersion() >= 13) {
|
||||
return nms.getConstructor("PacketPlayOutScoreboardScore_1_13").newInstance(nms.getEnum("EnumScoreboardAction")[packet.getAction().ordinal()], packet.getObjectiveName(), packet.getPlayer(), packet.getScore());
|
||||
}
|
||||
if (packet.action == PacketPlayOutScoreboardScore.Action.REMOVE) {
|
||||
return nms.newPacketPlayOutScoreboardScore_String.newInstance(packet.player);
|
||||
if (packet.getAction() == PacketPlayOutScoreboardScore.Action.REMOVE) {
|
||||
return nms.getConstructor("PacketPlayOutScoreboardScore_String").newInstance(packet.getPlayer());
|
||||
}
|
||||
Object score = nms.newScoreboardScore.newInstance(nms.newScoreboard.newInstance(), newScoreboardObjective(packet.objectiveName), packet.player);
|
||||
nms.ScoreboardScore_setScore.invoke(score, packet.score);
|
||||
if (nms.minorVersion >= 8) {
|
||||
return nms.newPacketPlayOutScoreboardScore.newInstance(score);
|
||||
Object score = nms.getConstructor("ScoreboardScore").newInstance(nms.getConstructor("Scoreboard").newInstance(), newScoreboardObjective(packet.getObjectiveName()), packet.getPlayer());
|
||||
nms.getMethod("ScoreboardScore_setScore").invoke(score, packet.getScore());
|
||||
if (nms.getMinorVersion() >= 8) {
|
||||
return nms.getConstructor("PacketPlayOutScoreboardScore").newInstance(score);
|
||||
}
|
||||
return nms.newPacketPlayOutScoreboardScore.newInstance(score, 0);
|
||||
return nms.getConstructor("PacketPlayOutScoreboardScore").newInstance(score, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object build(PacketPlayOutScoreboardTeam packet, ProtocolVersion clientVersion) throws Exception {
|
||||
String prefix = packet.playerPrefix;
|
||||
String suffix = packet.playerSuffix;
|
||||
public Object build(PacketPlayOutScoreboardTeam packet, ProtocolVersion clientVersion) throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException, SecurityException {
|
||||
Object team;
|
||||
if (nms.getMinorVersion() >= 13) {
|
||||
team = createTeamModern(packet, clientVersion);
|
||||
} else {
|
||||
team = createTeamLegacy(packet, clientVersion);
|
||||
}
|
||||
if (nms.getMinorVersion() >= 17) {
|
||||
switch (packet.getMethod()) {
|
||||
case 0:
|
||||
return nms.getMethod("PacketPlayOutScoreboardTeam_ofBoolean").invoke(null, team, true);
|
||||
case 1:
|
||||
return nms.getMethod("PacketPlayOutScoreboardTeam_of").invoke(null, team);
|
||||
case 2:
|
||||
return nms.getMethod("PacketPlayOutScoreboardTeam_ofBoolean").invoke(null, team, false);
|
||||
case 3:
|
||||
return nms.getMethod("PacketPlayOutScoreboardTeam_ofString").invoke(null, team, packet.getPlayers().toArray(new String[0])[0], nms.getEnum("PacketPlayOutScoreboardTeam_a")[0]);
|
||||
case 4:
|
||||
return nms.getMethod("PacketPlayOutScoreboardTeam_ofString").invoke(null, team, packet.getPlayers().toArray(new String[0])[0], nms.getEnum("PacketPlayOutScoreboardTeam_a")[1]);
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid action: " + packet.getMethod());
|
||||
}
|
||||
}
|
||||
return nms.getConstructor("PacketPlayOutScoreboardTeam").newInstance(team, packet.getMethod());
|
||||
}
|
||||
|
||||
private Object createTeamModern(PacketPlayOutScoreboardTeam packet, ProtocolVersion clientVersion) throws InstantiationException, IllegalAccessException, InvocationTargetException, SecurityException {
|
||||
String prefix = packet.getPlayerPrefix();
|
||||
String suffix = packet.getPlayerSuffix();
|
||||
if (clientVersion.getMinorVersion() < 13) {
|
||||
prefix = cutTo(prefix, 16);
|
||||
suffix = cutTo(suffix, 16);
|
||||
}
|
||||
Object team = nms.newScoreboardTeam.newInstance(nms.newScoreboard.newInstance(), packet.name);
|
||||
((Collection<String>)nms.ScoreboardTeam_getPlayerNameSet.invoke(team)).addAll(packet.players);
|
||||
if (nms.minorVersion >= 13) {
|
||||
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.ScoreboardTeam_setColor.invoke(team, ((Object[])nms.EnumChatFormat.getMethod("values").invoke(null))[format.ordinal()]);
|
||||
} else {
|
||||
if (prefix != null) nms.ScoreboardTeam_setPrefix.invoke(team, prefix);
|
||||
if (suffix != null) nms.ScoreboardTeam_setSuffix.invoke(team, suffix);
|
||||
Object team = nms.getConstructor("ScoreboardTeam").newInstance(nms.getConstructor("Scoreboard").newInstance(), packet.getName());
|
||||
((Collection<String>)nms.getMethod("ScoreboardTeam_getPlayerNameSet").invoke(team)).addAll(packet.getPlayers());
|
||||
if (prefix != null && prefix.length() > 0) nms.getMethod("ScoreboardTeam_setPrefix").invoke(team, toNMSComponent(IChatBaseComponent.optimizedComponent(prefix), clientVersion));
|
||||
if (suffix != null && suffix.length() > 0) nms.getMethod("ScoreboardTeam_setSuffix").invoke(team, toNMSComponent(IChatBaseComponent.optimizedComponent(suffix), clientVersion));
|
||||
EnumChatFormat format = packet.getColor() != null ? packet.getColor() : EnumChatFormat.lastColorsOf(prefix);
|
||||
nms.getMethod("ScoreboardTeam_setColor").invoke(team, nms.getEnum("EnumChatFormat")[format.ordinal()]);
|
||||
nms.getMethod("ScoreboardTeam_setNameTagVisibility").invoke(team, String.valueOf(packet.getNametagVisibility()).equals("always") ? nms.getEnum("EnumNameTagVisibility")[0] : nms.getEnum("EnumNameTagVisibility")[1]);
|
||||
nms.getMethod("ScoreboardTeam_setCollisionRule").invoke(team, String.valueOf(packet.getCollisionRule()).equals("always") ? nms.getEnum("EnumTeamPush")[0] : nms.getEnum("EnumTeamPush")[1]);
|
||||
return team;
|
||||
}
|
||||
|
||||
private Object createTeamLegacy(PacketPlayOutScoreboardTeam packet, ProtocolVersion clientVersion) throws IllegalAccessException, InvocationTargetException, InstantiationException, SecurityException {
|
||||
String prefix = packet.getPlayerPrefix();
|
||||
String suffix = packet.getPlayerSuffix();
|
||||
if (clientVersion.getMinorVersion() < 13) {
|
||||
prefix = cutTo(prefix, 16);
|
||||
suffix = cutTo(suffix, 16);
|
||||
}
|
||||
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);
|
||||
Object team = nms.getConstructor("ScoreboardTeam").newInstance(nms.getConstructor("Scoreboard").newInstance(), packet.getName());
|
||||
((Collection<String>)nms.getMethod("ScoreboardTeam_getPlayerNameSet").invoke(team)).addAll(packet.getPlayers());
|
||||
if (prefix != null) nms.getMethod("ScoreboardTeam_setPrefix").invoke(team, prefix);
|
||||
if (suffix != null) nms.getMethod("ScoreboardTeam_setSuffix").invoke(team, suffix);
|
||||
if (nms.getMinorVersion() >= 8) nms.getMethod("ScoreboardTeam_setNameTagVisibility").invoke(team, String.valueOf(packet.getNametagVisibility()).equals("always") ? nms.getEnum("EnumNameTagVisibility")[0] : nms.getEnum("EnumNameTagVisibility")[1]);
|
||||
if (nms.getMinorVersion() >= 9) nms.getMethod("ScoreboardTeam_setCollisionRule").invoke(team, String.valueOf(packet.getCollisionRule()).equals("always") ? nms.getEnum("EnumTeamPush")[0] : nms.getEnum("EnumTeamPush")[1]);
|
||||
return team;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds entity destroy packet with given parameter
|
||||
* @param id - entity id to destroy
|
||||
* @return destroy packet
|
||||
* @throws Exception - if reflection fails
|
||||
* @throws InvocationTargetException
|
||||
* @throws IllegalAccessException
|
||||
* @throws InstantiationException
|
||||
*/
|
||||
public Object buildEntityDestroyPacket(int id) throws Exception {
|
||||
if (nms.minorVersion >= 17) {
|
||||
return nms.newPacketPlayOutEntityDestroy.newInstance(id);
|
||||
public Object buildEntityDestroyPacket(int id) throws InstantiationException, IllegalAccessException, InvocationTargetException {
|
||||
try {
|
||||
return nms.getConstructor("PacketPlayOutEntityDestroy").newInstance(new int[] {id});
|
||||
} catch (IllegalArgumentException e) {
|
||||
//1.17.0
|
||||
return nms.getConstructor("PacketPlayOutEntityDestroy").newInstance(id);
|
||||
}
|
||||
return nms.newPacketPlayOutEntityDestroy.newInstance(new int[] {id});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -315,10 +341,12 @@ public class BukkitPacketBuilder implements PacketBuilder {
|
||||
* @param entityId - entity id
|
||||
* @param dataWatcher - datawatcher
|
||||
* @return metadata packet
|
||||
* @throws Exception - if reflection fails
|
||||
* @throws InvocationTargetException
|
||||
* @throws IllegalAccessException
|
||||
* @throws InstantiationException
|
||||
*/
|
||||
public Object buildEntityMetadataPacket(int entityId, DataWatcher dataWatcher) throws Exception {
|
||||
return nms.newPacketPlayOutEntityMetadata.newInstance(entityId, dataWatcher.toNMS(), true);
|
||||
public Object buildEntityMetadataPacket(int entityId, DataWatcher dataWatcher) throws InstantiationException, IllegalAccessException, InvocationTargetException {
|
||||
return nms.getConstructor("PacketPlayOutEntityMetadata").newInstance(entityId, dataWatcher.toNMS(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -329,26 +357,28 @@ public class BukkitPacketBuilder implements PacketBuilder {
|
||||
* @param loc - location to spawn at
|
||||
* @param dataWatcher - datawatcher
|
||||
* @return entity spawn packet
|
||||
* @throws Exception - if reflection fails
|
||||
* @throws IllegalAccessException
|
||||
* @throws InvocationTargetException
|
||||
* @throws InstantiationException
|
||||
*/
|
||||
public Object buildEntitySpawnPacket(int entityId, UUID uuid, EntityType entityType, Location loc, DataWatcher dataWatcher) throws Exception {
|
||||
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));
|
||||
nms.PacketPlayOutSpawnEntityLiving_PITCH.set(nmsPacket, (byte)(loc.getPitch() * 256.0f / 360.0f));
|
||||
if (nms.PacketPlayOutSpawnEntityLiving_DATAWATCHER != null) {
|
||||
nms.PacketPlayOutSpawnEntityLiving_DATAWATCHER.set(nmsPacket, dataWatcher.toNMS());
|
||||
public Object buildEntitySpawnPacket(int entityId, UUID uuid, EntityType entityType, Location loc, DataWatcher dataWatcher) throws IllegalAccessException, InstantiationException, InvocationTargetException {
|
||||
Object nmsPacket = nms.getConstructor("PacketPlayOutSpawnEntityLiving").newInstance(nms.getMethod("getHandle").invoke(Bukkit.getOnlinePlayers().iterator().next()));
|
||||
nms.setField(nmsPacket, "PacketPlayOutSpawnEntityLiving_ENTITYID", entityId);
|
||||
nms.setField(nmsPacket, "PacketPlayOutSpawnEntityLiving_ENTITYTYPE", entityIds.get(entityType));
|
||||
nms.setField(nmsPacket, "PacketPlayOutSpawnEntityLiving_YAW", (byte)(loc.getYaw() * 256.0f / 360.0f));
|
||||
nms.setField(nmsPacket, "PacketPlayOutSpawnEntityLiving_PITCH", (byte)(loc.getPitch() * 256.0f / 360.0f));
|
||||
if (nms.getMinorVersion() <= 14) {
|
||||
nms.setField(nmsPacket, "PacketPlayOutSpawnEntityLiving_DATAWATCHER", dataWatcher.toNMS());
|
||||
}
|
||||
if (nms.minorVersion >= 9) {
|
||||
nms.PacketPlayOutSpawnEntityLiving_UUID.set(nmsPacket, uuid);
|
||||
nms.PacketPlayOutSpawnEntityLiving_X.set(nmsPacket, loc.getX());
|
||||
nms.PacketPlayOutSpawnEntityLiving_Y.set(nmsPacket, loc.getY());
|
||||
nms.PacketPlayOutSpawnEntityLiving_Z.set(nmsPacket, loc.getZ());
|
||||
if (nms.getMinorVersion() >= 9) {
|
||||
nms.setField(nmsPacket, "PacketPlayOutSpawnEntityLiving_UUID", uuid);
|
||||
nms.setField(nmsPacket, "PacketPlayOutSpawnEntityLiving_X", loc.getX());
|
||||
nms.setField(nmsPacket, "PacketPlayOutSpawnEntityLiving_Y", loc.getY());
|
||||
nms.setField(nmsPacket, "PacketPlayOutSpawnEntityLiving_Z", loc.getZ());
|
||||
} else {
|
||||
nms.PacketPlayOutSpawnEntityLiving_X.set(nmsPacket, floor((double)loc.getX()*32));
|
||||
nms.PacketPlayOutSpawnEntityLiving_Y.set(nmsPacket, floor((double)loc.getY()*32));
|
||||
nms.PacketPlayOutSpawnEntityLiving_Z.set(nmsPacket, floor((double)loc.getZ()*32));
|
||||
nms.setField(nmsPacket, "PacketPlayOutSpawnEntityLiving_X", floor(loc.getX()*32));
|
||||
nms.setField(nmsPacket, "PacketPlayOutSpawnEntityLiving_Y", floor(loc.getY()*32));
|
||||
nms.setField(nmsPacket, "PacketPlayOutSpawnEntityLiving_Z", floor(loc.getZ()*32));
|
||||
}
|
||||
return nmsPacket;
|
||||
}
|
||||
@@ -358,68 +388,70 @@ public class BukkitPacketBuilder implements PacketBuilder {
|
||||
* @param entityId - entity id
|
||||
* @param location - location to teleport to
|
||||
* @return entity teleport packet
|
||||
* @throws Exception - if reflection fails
|
||||
* @throws IllegalAccessException
|
||||
* @throws InvocationTargetException
|
||||
* @throws InstantiationException
|
||||
*/
|
||||
public Object buildEntityTeleportPacket(int entityId, Location location) throws Exception {
|
||||
Object nmsPacket = nms.newPacketPlayOutEntityTeleport.newInstance(nms.getHandle.invoke(Bukkit.getOnlinePlayers().iterator().next()));
|
||||
nms.PacketPlayOutEntityTeleport_ENTITYID.set(nmsPacket, entityId);
|
||||
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());
|
||||
public Object buildEntityTeleportPacket(int entityId, Location location) throws IllegalAccessException, InstantiationException, InvocationTargetException {
|
||||
Object nmsPacket = nms.getConstructor("PacketPlayOutEntityTeleport").newInstance(nms.getMethod("getHandle").invoke(Bukkit.getOnlinePlayers().iterator().next()));
|
||||
nms.setField(nmsPacket, "PacketPlayOutEntityTeleport_ENTITYID", entityId);
|
||||
if (nms.getMinorVersion() >= 9) {
|
||||
nms.setField(nmsPacket, "PacketPlayOutEntityTeleport_X", location.getX());
|
||||
nms.setField(nmsPacket, "PacketPlayOutEntityTeleport_Y", location.getY());
|
||||
nms.setField(nmsPacket, "PacketPlayOutEntityTeleport_Z", location.getZ());
|
||||
} else {
|
||||
nms.PacketPlayOutEntityTeleport_X.set(nmsPacket, floor((double)location.getX()*32));
|
||||
nms.PacketPlayOutEntityTeleport_Y.set(nmsPacket, floor((double)location.getY()*32));
|
||||
nms.PacketPlayOutEntityTeleport_Z.set(nmsPacket, floor((double)location.getZ()*32));
|
||||
nms.setField(nmsPacket, "PacketPlayOutEntityTeleport_X", floor(location.getX()*32));
|
||||
nms.setField(nmsPacket, "PacketPlayOutEntityTeleport_Y", floor(location.getY()*32));
|
||||
nms.setField(nmsPacket, "PacketPlayOutEntityTeleport_Z", floor(location.getZ()*32));
|
||||
}
|
||||
nms.PacketPlayOutEntityTeleport_YAW.set(nmsPacket, (byte)((float)location.getYaw()/360*256));
|
||||
nms.PacketPlayOutEntityTeleport_PITCH.set(nmsPacket, (byte)((float)location.getPitch()/360*256));
|
||||
nms.setField(nmsPacket, "PacketPlayOutEntityTeleport_YAW", (byte) (location.getYaw()/360*256));
|
||||
nms.setField(nmsPacket, "PacketPlayOutEntityTeleport_PITCH", (byte) (location.getPitch()/360*256));
|
||||
return nmsPacket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketPlayOutPlayerInfo readPlayerInfo(Object nmsPacket, ProtocolVersion clientVersion) throws Exception {
|
||||
if (nms.minorVersion < 8) return null;
|
||||
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_getGamemode.invoke(nmsData);
|
||||
public PacketPlayOutPlayerInfo readPlayerInfo(Object nmsPacket, ProtocolVersion clientVersion) throws IllegalAccessException, InvocationTargetException {
|
||||
if (nms.getMinorVersion() < 8) return null;
|
||||
EnumPlayerInfoAction action = EnumPlayerInfoAction.valueOf(nms.getField("PacketPlayOutPlayerInfo_ACTION").get(nmsPacket).toString());
|
||||
List<PlayerInfoData> listData = new ArrayList<>();
|
||||
for (Object nmsData : (List<?>) nms.getField("PacketPlayOutPlayerInfo_PLAYERS").get(nmsPacket)) {
|
||||
Object nmsGamemode = nms.getMethod("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);
|
||||
GameProfile profile = (GameProfile) nms.getMethod("PlayerInfoData_getProfile").invoke(nmsData);
|
||||
Object nmsComponent = nms.getMethod("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));
|
||||
listData.add(new PlayerInfoData(profile.getName(), profile.getId(), profile.getProperties(), (int) nms.getMethod("PlayerInfoData_getLatency").invoke(nmsData), gamemode, listName));
|
||||
}
|
||||
return new PacketPlayOutPlayerInfo(action, listData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketPlayOutScoreboardObjective readObjective(Object nmsPacket, ProtocolVersion clientVersion) throws Exception {
|
||||
String objective = (String) nms.PacketPlayOutScoreboardObjective_OBJECTIVENAME.get(nmsPacket);
|
||||
public PacketPlayOutScoreboardObjective readObjective(Object nmsPacket, ProtocolVersion clientVersion) throws IllegalAccessException {
|
||||
String objective = (String) nms.getField("PacketPlayOutScoreboardObjective_OBJECTIVENAME").get(nmsPacket);
|
||||
String displayName;
|
||||
if (nms.minorVersion >= 13) {
|
||||
Object component = nms.PacketPlayOutScoreboardObjective_DISPLAYNAME.get(nmsPacket);
|
||||
Object component = nms.getField("PacketPlayOutScoreboardObjective_DISPLAYNAME").get(nmsPacket);
|
||||
if (nms.getMinorVersion() >= 13) {
|
||||
IChatBaseComponent c = component == null ? null : fromNMSComponent(component);
|
||||
displayName = c == null ? null : c.toLegacyText();
|
||||
} else {
|
||||
displayName = (String) nms.PacketPlayOutScoreboardObjective_DISPLAYNAME.get(nmsPacket);
|
||||
displayName = (String) component;
|
||||
}
|
||||
EnumScoreboardHealthDisplay renderType = null;
|
||||
if (nms.PacketPlayOutScoreboardObjective_RENDERTYPE != null) {
|
||||
Object nmsRender = nms.PacketPlayOutScoreboardObjective_RENDERTYPE.get(nmsPacket);
|
||||
if (nms.getMinorVersion() >= 8) {
|
||||
Object nmsRender = nms.getField("PacketPlayOutScoreboardObjective_RENDERTYPE").get(nmsPacket);
|
||||
if (nmsRender != null) {
|
||||
renderType = EnumScoreboardHealthDisplay.valueOf(nmsRender.toString());
|
||||
}
|
||||
}
|
||||
int method = nms.PacketPlayOutScoreboardObjective_METHOD.getInt(nmsPacket);
|
||||
int method = nms.getField("PacketPlayOutScoreboardObjective_METHOD").getInt(nmsPacket);
|
||||
return new PacketPlayOutScoreboardObjective(method, objective, displayName, renderType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketPlayOutScoreboardDisplayObjective readDisplayObjective(Object nmsPacket, ProtocolVersion clientVersion) throws Exception {
|
||||
public PacketPlayOutScoreboardDisplayObjective readDisplayObjective(Object nmsPacket, ProtocolVersion clientVersion) throws IllegalAccessException {
|
||||
return new PacketPlayOutScoreboardDisplayObjective(
|
||||
nms.PacketPlayOutScoreboardDisplayObjective_POSITION.getInt(nmsPacket),
|
||||
(String) nms.PacketPlayOutScoreboardDisplayObjective_OBJECTIVENAME.get(nmsPacket)
|
||||
nms.getField("PacketPlayOutScoreboardDisplayObjective_POSITION").getInt(nmsPacket),
|
||||
(String) nms.getField("PacketPlayOutScoreboardDisplayObjective_OBJECTIVENAME").get(nmsPacket)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -437,20 +469,21 @@ public class BukkitPacketBuilder implements PacketBuilder {
|
||||
* Converts json string into a component
|
||||
* @param json json as string
|
||||
* @return NMS component
|
||||
* @throws Exception if something fails
|
||||
* @throws InvocationTargetException
|
||||
* @throws IllegalAccessException
|
||||
*/
|
||||
public Object stringToComponent(String json) throws Exception {
|
||||
public Object stringToComponent(String json) throws IllegalAccessException, InvocationTargetException {
|
||||
if (json == null) return null;
|
||||
return nms.ChatSerializer_DESERIALIZE.invoke(null, json);
|
||||
return nms.getMethod("ChatSerializer_DESERIALIZE").invoke(null, json);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts minecraft IChatBaseComponent into TAB's component class. Currently does not support hover event.
|
||||
* @param component - component to convert
|
||||
* @return converted component
|
||||
* @throws Exception if something fails
|
||||
* @throws IllegalAccessException
|
||||
*/
|
||||
public IChatBaseComponent fromNMSComponent(Object component) throws Exception {
|
||||
public IChatBaseComponent fromNMSComponent(Object component) throws IllegalAccessException {
|
||||
long time = System.nanoTime();
|
||||
IChatBaseComponent obj = fromNMSComponent0(component);
|
||||
TAB.getInstance().getCPUManager().addMethodTime("fromNMSComponent", System.nanoTime()-time);
|
||||
@@ -458,42 +491,37 @@ public class BukkitPacketBuilder implements PacketBuilder {
|
||||
}
|
||||
|
||||
//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 {
|
||||
if (!nms.ChatComponentText.isInstance(component)) return null; //paper
|
||||
IChatBaseComponent chat = new IChatBaseComponent((String) nms.ChatComponentText_text.get(component));
|
||||
Object modifier = nms.ChatBaseComponent_modifier.get(component);
|
||||
public IChatBaseComponent fromNMSComponent0(Object component) throws IllegalAccessException {
|
||||
if (!nms.getClass("ChatComponentText").isInstance(component)) return null; //paper
|
||||
IChatBaseComponent chat = new IChatBaseComponent((String) nms.getField("ChatComponentText_text").get(component));
|
||||
Object modifier = nms.getField("ChatBaseComponent_modifier").get(component);
|
||||
if (modifier != null) {
|
||||
Object color = nms.ChatModifier_color.get(modifier);
|
||||
Object color = nms.getField("ChatModifier_color").get(modifier);
|
||||
if (color != null) {
|
||||
if (nms.minorVersion >= 16) {
|
||||
String name = (String) nms.ChatHexColor_name.get(color);
|
||||
if (nms.getMinorVersion() >= 16) {
|
||||
String name = (String) nms.getField("ChatHexColor_name").get(color);
|
||||
if (name != null) {
|
||||
//legacy code
|
||||
chat.setColor(new TextColor(EnumChatFormat.valueOf(name.toUpperCase())));
|
||||
} else {
|
||||
int rgb = (int) nms.ChatHexColor_rgb.get(color);
|
||||
int rgb = (int) nms.getField("ChatHexColor_rgb").get(color);
|
||||
chat.setColor(new TextColor((rgb >> 16) & 0xFF, (rgb >> 8) & 0xFF, rgb & 0xFF));
|
||||
}
|
||||
} else {
|
||||
chat.setColor(new TextColor(EnumChatFormat.valueOf(((Enum)color).name())));
|
||||
}
|
||||
}
|
||||
chat.setBold((Boolean) nms.ChatModifier_bold.get(modifier));
|
||||
chat.setItalic((Boolean) nms.ChatModifier_italic.get(modifier));
|
||||
chat.setObfuscated((Boolean) nms.ChatModifier_obfuscated.get(modifier));
|
||||
chat.setStrikethrough((Boolean) nms.ChatModifier_strikethrough.get(modifier));
|
||||
chat.setUnderlined((Boolean) nms.ChatModifier_underlined.get(modifier));
|
||||
Object clickEvent = nms.ChatModifier_clickEvent.get(modifier);
|
||||
chat.setBold((Boolean) nms.getField("ChatModifier_bold").get(modifier));
|
||||
chat.setItalic((Boolean) nms.getField("ChatModifier_italic").get(modifier));
|
||||
chat.setObfuscated((Boolean) nms.getField("ChatModifier_obfuscated").get(modifier));
|
||||
chat.setStrikethrough((Boolean) nms.getField("ChatModifier_strikethrough").get(modifier));
|
||||
chat.setUnderlined((Boolean) nms.getField("ChatModifier_underlined").get(modifier));
|
||||
Object clickEvent = nms.getField("ChatModifier_clickEvent").get(modifier);
|
||||
if (clickEvent != null) {
|
||||
chat.onClick(ClickAction.valueOf(nms.ChatClickable_action.get(clickEvent).toString().toUpperCase()), (String) nms.ChatClickable_value.get(clickEvent));
|
||||
chat.onClick(ClickAction.valueOf(nms.getField("ChatClickable_action").get(clickEvent).toString().toUpperCase()), (String) nms.getField("ChatClickable_value").get(clickEvent));
|
||||
}
|
||||
/* 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)));
|
||||
}*/
|
||||
}
|
||||
for (Object extra : (List<Object>) nms.ChatBaseComponent_extra.get(component)) {
|
||||
for (Object extra : (List<Object>) nms.getField("ChatBaseComponent_extra").get(component)) {
|
||||
chat.addExtra(fromNMSComponent0(extra));
|
||||
}
|
||||
return chat;
|
||||
@@ -504,9 +532,11 @@ public class BukkitPacketBuilder implements PacketBuilder {
|
||||
* @param component - component to convert
|
||||
* @param clientVersion - client version used to decide RGB conversion
|
||||
* @return converted component
|
||||
* @throws Exception if something fails
|
||||
* @throws InvocationTargetException
|
||||
* @throws IllegalAccessException
|
||||
* @throws InstantiationException
|
||||
*/
|
||||
public Object toNMSComponent(IChatBaseComponent component, ProtocolVersion clientVersion) throws Exception {
|
||||
public Object toNMSComponent(IChatBaseComponent component, ProtocolVersion clientVersion) throws InstantiationException, IllegalAccessException, InvocationTargetException {
|
||||
long time = System.nanoTime();
|
||||
Object obj = toNMSComponent0(component, clientVersion);
|
||||
TAB.getInstance().getCPUManager().addMethodTime("toNMSComponent", System.nanoTime()-time);
|
||||
@@ -514,56 +544,52 @@ public class BukkitPacketBuilder implements PacketBuilder {
|
||||
}
|
||||
|
||||
//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 {
|
||||
private Object toNMSComponent0(IChatBaseComponent component, ProtocolVersion clientVersion) throws InstantiationException, IllegalAccessException, InvocationTargetException {
|
||||
if (component == null) return null;
|
||||
Object chat = nms.newChatComponentText.newInstance(component.getText());
|
||||
Object chat = nms.getConstructor("ChatComponentText").newInstance(component.getText());
|
||||
Object modifier;
|
||||
if (nms.minorVersion >= 16) {
|
||||
if (nms.getMinorVersion() >= 16) {
|
||||
Object color = null;
|
||||
if (component.getColor() != null) {
|
||||
if (clientVersion.getMinorVersion() >= 16) {
|
||||
color = nms.ChatHexColor_ofInt.invoke(null, (component.getColor().getRed() << 16) + (component.getColor().getGreen() << 8) + component.getColor().getBlue());
|
||||
color = nms.getMethod("ChatHexColor_ofInt").invoke(null, (component.getColor().getRed() << 16) + (component.getColor().getGreen() << 8) + component.getColor().getBlue());
|
||||
} else {
|
||||
color = nms.ChatHexColor_ofString.invoke(null, component.getColor().getLegacyColor().toString().toLowerCase());
|
||||
color = nms.getMethod("ChatHexColor_ofString").invoke(null, component.getColor().getLegacyColor().toString().toLowerCase());
|
||||
}
|
||||
}
|
||||
modifier = nms.newChatModifier.newInstance(
|
||||
modifier = nms.getConstructor("ChatModifier").newInstance(
|
||||
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
|
||||
);
|
||||
component.getClickAction() == null ? null : nms.getConstructor("ChatClickable").newInstance(nms.getMethod("EnumClickAction_a").invoke(null, component.getClickAction().toString().toLowerCase()), component.getClickValue().toString()),
|
||||
null, //need to make it for 1.16
|
||||
null, null);
|
||||
} else {
|
||||
modifier = nms.newChatModifier.newInstance();
|
||||
modifier = nms.getConstructor("ChatModifier").newInstance();
|
||||
if (component.getClickAction() != null){
|
||||
nms.ChatModifier_clickEvent.set(modifier, nms.newChatClickable.newInstance(nms.EnumClickAction_a.invoke(null, component.getClickAction().toString().toLowerCase()), component.getClickValue().toString()));
|
||||
nms.setField(modifier, "ChatModifier_clickEvent", nms.getConstructor("ChatClickable").newInstance(nms.getMethod("EnumClickAction_a").invoke(null, component.getClickAction().toString().toLowerCase()), component.getClickValue().toString()));
|
||||
}
|
||||
/* if (component.getHoverAction() != null) {
|
||||
nms.ChatModifier_hoverEvent.set(modifier, nms.newChatHoverable.newInstance(nms.EnumHoverAction_a.invoke(null, (component.getHoverAction().toString().toLowerCase())), stringToComponent(component.getHoverValue().toString())));
|
||||
}*/
|
||||
if (component.getColor() != null) nms.ChatModifier_color.set(modifier, Enum.valueOf(nms.EnumChatFormat, component.getColor().getLegacyColor().toString()));
|
||||
if (component.isBold()) nms.ChatModifier_bold.set(modifier, true);
|
||||
if (component.isItalic()) nms.ChatModifier_italic.set(modifier, true);
|
||||
if (component.isUnderlined()) nms.ChatModifier_underlined.set(modifier, true);
|
||||
if (component.isStrikethrough()) nms.ChatModifier_strikethrough.set(modifier, true);
|
||||
if (component.isObfuscated()) nms.ChatModifier_obfuscated.set(modifier, true);
|
||||
if (component.getColor() != null) nms.setField(modifier, "ChatModifier_color", Enum.valueOf((Class<Enum>) nms.getClass("EnumChatFormat"), component.getColor().getLegacyColor().toString()));
|
||||
nms.setField(modifier, "ChatModifier_bold", component.getBold());
|
||||
nms.setField(modifier, "ChatModifier_italic", component.getItalic());
|
||||
nms.setField(modifier, "ChatModifier_underlined", component.getUnderlined());
|
||||
nms.setField(modifier, "ChatModifier_strikethrough", component.getStrikethrough());
|
||||
nms.setField(modifier, "ChatModifier_obfuscated", component.getObfuscated());
|
||||
}
|
||||
nms.ChatBaseComponent_modifier.set(chat, modifier);
|
||||
nms.setField(chat, "ChatBaseComponent_modifier", modifier);
|
||||
for (IChatBaseComponent extra : component.getExtra()) {
|
||||
nms.ChatComponentText_addSibling.invoke(chat, toNMSComponent0(extra, clientVersion));
|
||||
nms.getMethod("ChatComponentText_addSibling").invoke(chat, toNMSComponent0(extra, clientVersion));
|
||||
}
|
||||
return chat;
|
||||
}
|
||||
|
||||
private Object newScoreboardObjective(String objectiveName) throws Exception {
|
||||
if (nms.minorVersion >= 13) {
|
||||
return nms.newScoreboardObjective.newInstance(null, objectiveName, null, stringToComponent("{\"text\":\"\"}"), null);
|
||||
private Object newScoreboardObjective(String objectiveName) throws InstantiationException, IllegalAccessException, InvocationTargetException {
|
||||
if (nms.getMinorVersion() >= 13) {
|
||||
return nms.getConstructor("ScoreboardObjective").newInstance(null, objectiveName, null, stringToComponent("{\"text\":\"\"}"), null);
|
||||
}
|
||||
return nms.newScoreboardObjective.newInstance(null, objectiveName, nms.getFields(nms.IScoreboardCriteria, nms.IScoreboardCriteria).get(0).get(null));
|
||||
return nms.getConstructor("ScoreboardObjective").newInstance(null, objectiveName, nms.getFields(nms.getClass("IScoreboardCriteria"), nms.getClass("IScoreboardCriteria")).get(0).get(null));
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ import me.neznamy.tab.shared.features.PipelineInjector;
|
||||
public class BukkitPipelineInjector extends PipelineInjector {
|
||||
|
||||
//handler to inject before
|
||||
private final String INJECT_POSITION = "packet_handler";
|
||||
private static final String INJECT_POSITION = "packet_handler";
|
||||
|
||||
//nms storage
|
||||
private NMSStorage nms;
|
||||
@@ -55,36 +55,6 @@ public class BukkitPipelineInjector extends PipelineInjector {
|
||||
//java.util.NoSuchElementException: TABReader
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all real players from team if packet does not come from TAB and reports this to override log
|
||||
* @param packetPlayOutScoreboardTeam - team packet
|
||||
* @throws Exception - if reflection fails
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private void modifyPlayers(Object packetPlayOutScoreboardTeam) throws Exception {
|
||||
long time = System.nanoTime();
|
||||
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);
|
||||
tab.getCPUManager().addTime(TabFeature.NAMETAGS, UsageType.ANTI_OVERRIDE, System.nanoTime()-time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom channel duplex handler override
|
||||
@@ -103,38 +73,72 @@ public class BukkitPipelineInjector extends PipelineInjector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext context, Object packet) throws Exception {
|
||||
public void channelRead(ChannelHandlerContext context, Object packet) {
|
||||
try {
|
||||
Object modifiedPacket = tab.getFeatureManager().onPacketReceive(player, packet);
|
||||
if (modifiedPacket != null) super.channelRead(context, modifiedPacket);
|
||||
} catch (Throwable e){
|
||||
} catch (Exception e){
|
||||
tab.getErrorManager().printError("An error occurred when reading packets", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ChannelHandlerContext context, Object packet, ChannelPromise channelPromise) throws Exception {
|
||||
public void write(ChannelHandlerContext context, Object packet, ChannelPromise channelPromise) {
|
||||
try {
|
||||
if (nms.PacketPlayOutPlayerInfo.isInstance(packet)) {
|
||||
if (nms.getClass("PacketPlayOutPlayerInfo").isInstance(packet)) {
|
||||
super.write(context, tab.getFeatureManager().onPacketPlayOutPlayerInfo(player, packet), channelPromise);
|
||||
return;
|
||||
}
|
||||
if (tab.getFeatureManager().getNameTagFeature() != null && antiOverrideTeams && nms.PacketPlayOutScoreboardTeam.isInstance(packet)) {
|
||||
if (tab.getFeatureManager().getNameTagFeature() != null && antiOverrideTeams && nms.getClass("PacketPlayOutScoreboardTeam").isInstance(packet)) {
|
||||
modifyPlayers(packet);
|
||||
super.write(context, packet, channelPromise);
|
||||
return;
|
||||
}
|
||||
if (nms.PacketPlayOutScoreboardDisplayObjective.isInstance(packet) && antiOverrideObjectives && tab.getFeatureManager().onDisplayObjective(player, packet)) {
|
||||
if (nms.getClass("PacketPlayOutScoreboardDisplayObjective").isInstance(packet) && antiOverrideObjectives && tab.getFeatureManager().onDisplayObjective(player, packet)) {
|
||||
return;
|
||||
}
|
||||
if (antiOverrideObjectives && nms.PacketPlayOutScoreboardObjective.isInstance(packet)) {
|
||||
if (antiOverrideObjectives && nms.getClass("PacketPlayOutScoreboardObjective").isInstance(packet)) {
|
||||
tab.getFeatureManager().onObjective(player, packet);
|
||||
}
|
||||
tab.getFeatureManager().onPacketSend(player, packet);
|
||||
} catch (Throwable e){
|
||||
tab.getErrorManager().printError("An error occurred when reading packets", e);
|
||||
}
|
||||
super.write(context, packet, channelPromise);
|
||||
try {
|
||||
super.write(context, packet, channelPromise);
|
||||
} catch (Throwable e) {
|
||||
tab.getErrorManager().printError("Failed to forward packet " + packet.getClass().getSimpleName() + " to " + player.getName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all real players from team if packet does not come from TAB and reports this to override log
|
||||
* @param packetPlayOutScoreboardTeam - team packet
|
||||
* @throws IllegalAccessException
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private void modifyPlayers(Object packetPlayOutScoreboardTeam) throws IllegalAccessException {
|
||||
long time = System.nanoTime();
|
||||
Collection<String> players = (Collection<String>) nms.getField("PacketPlayOutScoreboardTeam_PLAYERS").get(packetPlayOutScoreboardTeam);
|
||||
String teamName = (String) nms.getField("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<>();
|
||||
for (String entry : players) {
|
||||
TabPlayer p = tab.getPlayer(entry);
|
||||
if (p == null) {
|
||||
newList.add(entry);
|
||||
continue;
|
||||
}
|
||||
if (!tab.getFeatureManager().getNameTagFeature().getPlayersInDisabledWorlds().contains(p) && !p.hasTeamHandlingPaused() &&
|
||||
!teamName.equals(p.getTeamName())) {
|
||||
logTeamOverride(teamName, entry);
|
||||
} else {
|
||||
newList.add(entry);
|
||||
}
|
||||
}
|
||||
nms.setField(packetPlayOutScoreboardTeam, "PacketPlayOutScoreboardTeam_PLAYERS", newList);
|
||||
tab.getCPUManager().addTime(TabFeature.NAMETAGS, UsageType.ANTI_OVERRIDE, System.nanoTime()-time);
|
||||
}
|
||||
}
|
||||
}
|
||||
+72
-87
@@ -1,11 +1,9 @@
|
||||
package me.neznamy.tab.platforms.bukkit;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
@@ -13,6 +11,7 @@ import java.util.UUID;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Statistic;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.RegisteredServiceProvider;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
@@ -47,9 +46,14 @@ public class BukkitPlaceholderRegistry implements PlaceholderRegistry {
|
||||
//placeholder registry buffer
|
||||
private List<Placeholder> placeholders;
|
||||
|
||||
private Object essentials;
|
||||
|
||||
//essentials methods
|
||||
private Method getUser;
|
||||
private Method getNickname;
|
||||
private Method essGetUser;
|
||||
private Method essGetNickname;
|
||||
private Method essIsAfk;
|
||||
|
||||
private Method purpurIsAfk;
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameter
|
||||
@@ -58,16 +62,18 @@ public class BukkitPlaceholderRegistry implements PlaceholderRegistry {
|
||||
public BukkitPlaceholderRegistry(JavaPlugin plugin) {
|
||||
decimal2.applyPattern("#.##");
|
||||
this.plugin = plugin;
|
||||
essentials = Bukkit.getPluginManager().getPlugin("Essentials");
|
||||
if (Bukkit.getPluginManager().isPluginEnabled("Vault")) {
|
||||
RegisteredServiceProvider<Economy> rspEconomy = Bukkit.getServicesManager().getRegistration(Economy.class);
|
||||
if (rspEconomy != null) economy = rspEconomy.getProvider();
|
||||
RegisteredServiceProvider<Chat> rspChat = Bukkit.getServicesManager().getRegistration(Chat.class);
|
||||
if (rspChat != null) chat = rspChat.getProvider();
|
||||
}
|
||||
if (Bukkit.getPluginManager().isPluginEnabled("Essentials")) {
|
||||
if (essentials != null) {
|
||||
try {
|
||||
getUser = Class.forName("com.earth2me.essentials.Essentials").getMethod("getUser", Player.class);
|
||||
getNickname = Class.forName("com.earth2me.essentials.User").getMethod("getNickname");
|
||||
essGetUser = Class.forName("com.earth2me.essentials.Essentials").getMethod("getUser", Player.class);
|
||||
essGetNickname = Class.forName("com.earth2me.essentials.User").getMethod("getNickname");
|
||||
essIsAfk = Class.forName("com.earth2me.essentials.User").getMethod("isAfk");
|
||||
} catch (Exception e) {
|
||||
TAB.getInstance().getErrorManager().printError("Failed to load essentials methods", e);
|
||||
}
|
||||
@@ -76,7 +82,7 @@ public class BukkitPlaceholderRegistry implements PlaceholderRegistry {
|
||||
|
||||
@Override
|
||||
public List<Placeholder> registerPlaceholders() {
|
||||
placeholders = new ArrayList<Placeholder>();
|
||||
placeholders = new ArrayList<>();
|
||||
placeholders.add(new PlayerPlaceholder("%money%", 1000) {
|
||||
public String get(TabPlayer p) {
|
||||
if (economy != null) return decimal2.format(economy.getBalance((Player) p.getPlayer()));
|
||||
@@ -94,42 +100,42 @@ public class BukkitPlaceholderRegistry implements PlaceholderRegistry {
|
||||
return String.valueOf(((Player) p.getPlayer()).getStatistic(Statistic.DEATHS));
|
||||
}
|
||||
});
|
||||
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 {
|
||||
Object nmsServer = Bukkit.getServer().getClass().getMethod("getServer").invoke(Bukkit.getServer());
|
||||
double value = ((double[]) nmsServer.getClass().getField("recentTps").get(nmsServer))[0];
|
||||
return decimal2.format(Math.min(20, value));
|
||||
} catch (Throwable t) {
|
||||
} catch (Exception t) {
|
||||
return "-1";
|
||||
}
|
||||
}
|
||||
});
|
||||
placeholders.add(new PlayerPlaceholder("%canseeonline%", 2000) {
|
||||
public String get(TabPlayer p) {
|
||||
int var = 0;
|
||||
int count = 0;
|
||||
for (TabPlayer all : TAB.getInstance().getPlayers()){
|
||||
if (((Player) p.getPlayer()).canSee((Player) all.getPlayer())) var++;
|
||||
if (((Player) p.getPlayer()).canSee((Player) all.getPlayer())) count++;
|
||||
}
|
||||
return String.valueOf(var);
|
||||
return String.valueOf(count);
|
||||
}
|
||||
});
|
||||
placeholders.add(new PlayerPlaceholder("%canseestaffonline%", 2000) {
|
||||
public String get(TabPlayer p) {
|
||||
int var = 0;
|
||||
int count = 0;
|
||||
for (TabPlayer all : TAB.getInstance().getPlayers()){
|
||||
if (all.isStaff() && ((Player) p.getPlayer()).canSee((Player) all.getPlayer())) var++;
|
||||
if (all.isStaff() && ((Player) p.getPlayer()).canSee((Player) all.getPlayer())) count++;
|
||||
}
|
||||
return String.valueOf(var);
|
||||
return String.valueOf(count);
|
||||
}
|
||||
});
|
||||
if (NMSStorage.getInstance().getMinorVersion() >= 6) {
|
||||
placeholders.add(new PlayerPlaceholder("%health%", 100) {
|
||||
public String get(TabPlayer p) {
|
||||
return String.valueOf((int) Math.ceil(((Player) p.getPlayer()).getHealth()));
|
||||
}
|
||||
});
|
||||
}
|
||||
registerAFKPlaceholder();
|
||||
registerVaultPlaceholders();
|
||||
registerPositionPlaceholders();
|
||||
@@ -142,47 +148,39 @@ public class BukkitPlaceholderRegistry implements PlaceholderRegistry {
|
||||
* Registers AFK placeholder
|
||||
*/
|
||||
private void registerAFKPlaceholder() {
|
||||
String noAfk = TAB.getInstance().getConfiguration().config.getString("placeholders.afk-no", "");
|
||||
String yesAfk = TAB.getInstance().getConfiguration().config.getString("placeholders.afk-yes", " &4*&4&lAFK&4*&r");
|
||||
Plugin afkplus = Bukkit.getPluginManager().getPlugin("AFKPlus");
|
||||
boolean antiafkplus = Bukkit.getPluginManager().isPluginEnabled("AntiAFKPlus");
|
||||
try {
|
||||
purpurIsAfk = Player.class.getMethod("isAfk");
|
||||
} catch (NoSuchMethodException | SecurityException e1) {
|
||||
//not purpur
|
||||
}
|
||||
String noAfk = TAB.getInstance().getConfiguration().getConfig().getString("placeholders.afk-no", "");
|
||||
String yesAfk = TAB.getInstance().getConfiguration().getConfig().getString("placeholders.afk-yes", " &4*&4&lAFK&4*&r");
|
||||
placeholders.add(new PlayerPlaceholder("%afk%", 500) {
|
||||
public String get(TabPlayer p) {
|
||||
boolean afk = false;
|
||||
try {
|
||||
if (Bukkit.getPluginManager().isPluginEnabled("Essentials")) {
|
||||
Object user = Bukkit.getPluginManager().getPlugin("Essentials").getClass().getMethod("getUser", Player.class).invoke(Bukkit.getPluginManager().getPlugin("Essentials"), p.getPlayer());
|
||||
afk = (boolean) user.getClass().getMethod("isAfk").invoke(user);
|
||||
if (essentials != null) {
|
||||
Object user = essGetUser.invoke(Bukkit.getPluginManager().getPlugin("Essentials"), p.getPlayer());
|
||||
if ((boolean) essIsAfk.invoke(user)) return yesAfk;
|
||||
}
|
||||
if (Bukkit.getPluginManager().isPluginEnabled("AFKPlus")) {
|
||||
Object AFKPlus = Bukkit.getPluginManager().getPlugin("AFKPlus");
|
||||
Object AFKPlusPlayer = AFKPlus.getClass().getMethod("getPlayer", UUID.class).invoke(AFKPlus, p.getUniqueId());
|
||||
afk = (boolean) AFKPlusPlayer.getClass().getMethod("isAFK").invoke(AFKPlusPlayer);
|
||||
if (afkplus != null) {
|
||||
Object afkplusplayer = afkplus.getClass().getMethod("getPlayer", UUID.class).invoke(afkplus, p.getUniqueId());
|
||||
if ((boolean) afkplusplayer.getClass().getMethod("isAFK").invoke(afkplusplayer)) return yesAfk;
|
||||
}
|
||||
if (Bukkit.getPluginManager().isPluginEnabled("AntiAFKPlus")) {
|
||||
if (antiafkplus) {
|
||||
Object api = Class.forName("de.kinglol12345.AntiAFKPlus.api.AntiAFKPlusAPI").getDeclaredMethod("getAPI").invoke(null);
|
||||
afk = (boolean) api.getClass().getMethod("isAFK", Player.class).invoke(api, p.getPlayer());
|
||||
if ((boolean) api.getClass().getMethod("isAFK", Player.class).invoke(api, p.getPlayer())) return yesAfk;
|
||||
}
|
||||
if (Bukkit.getPluginManager().isPluginEnabled("xAntiAFK")) {
|
||||
afk = (boolean) Class.forName("ch.soolz.xantiafk.xAntiAFKAPI").getMethod("isAfk", Player.class).invoke(null, p.getPlayer());
|
||||
}
|
||||
if (Bukkit.getPluginManager().isPluginEnabled("AutoAFK")) {
|
||||
Object plugin = Bukkit.getPluginManager().getPlugin("AutoAFK");
|
||||
Field f = plugin.getClass().getDeclaredField("afkList");
|
||||
f.setAccessible(true);
|
||||
HashMap<?, ?> map = (HashMap<?, ?>) f.get(plugin);
|
||||
afk = map.containsKey(p.getPlayer());
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
return TAB.getInstance().getErrorManager().printError("", "Failed to check AFK status of " + p.getName(), t);
|
||||
} catch (Exception e) {
|
||||
return TAB.getInstance().getErrorManager().printError("", "Failed to check AFK status of " + p.getName(), e);
|
||||
}
|
||||
if (!afk) {
|
||||
try {
|
||||
//purpur AFK API
|
||||
afk = (boolean) p.getPlayer().getClass().getMethod("isAfk").invoke(p.getPlayer());
|
||||
} catch (Throwable t) {
|
||||
//not purpur
|
||||
}
|
||||
try {
|
||||
if (purpurIsAfk != null && (boolean) purpurIsAfk.invoke(p.getPlayer())) return yesAfk;
|
||||
} catch (Exception e) {
|
||||
//not purpur
|
||||
}
|
||||
return afk ? yesAfk : noAfk;
|
||||
return noAfk;
|
||||
}
|
||||
@Override
|
||||
public String[] getNestedStrings(){
|
||||
@@ -199,23 +197,13 @@ public class BukkitPlaceholderRegistry implements PlaceholderRegistry {
|
||||
placeholders.add(new PlayerPlaceholder("%vault-prefix%", 500) {
|
||||
|
||||
public String get(TabPlayer p) {
|
||||
try {
|
||||
String prefix = chat.getPlayerPrefix((Player) p.getPlayer());
|
||||
return prefix != null ? prefix : "";
|
||||
} catch (Exception e) {
|
||||
return TAB.getInstance().getErrorManager().printError("", "Placeholder %vault-prefix% threw an exception", e);
|
||||
}
|
||||
return chat.getPlayerPrefix((Player) p.getPlayer());
|
||||
}
|
||||
});
|
||||
placeholders.add(new PlayerPlaceholder("%vault-suffix%", 500) {
|
||||
|
||||
public String get(TabPlayer p) {
|
||||
try {
|
||||
String suffix = chat.getPlayerSuffix((Player) p.getPlayer());
|
||||
return suffix != null ? suffix : "";
|
||||
} catch (Exception e) {
|
||||
return TAB.getInstance().getErrorManager().printError("", "Placeholder %vault-suffix% threw an exception", e);
|
||||
}
|
||||
return chat.getPlayerSuffix((Player) p.getPlayer());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
@@ -257,18 +245,18 @@ public class BukkitPlaceholderRegistry implements PlaceholderRegistry {
|
||||
* Registers essentials placeholders
|
||||
*/
|
||||
private void registerEssentialsPlaceholders() {
|
||||
if (Bukkit.getPluginManager().isPluginEnabled("Essentials")) {
|
||||
if (essentials != null) {
|
||||
placeholders.add(new PlayerPlaceholder("%essentialsnick%", 1000) {
|
||||
public String get(TabPlayer p) {
|
||||
if (getNickname == null) return "<Internal plugin error>";
|
||||
if (essGetNickname == null) return "<Internal plugin error>";
|
||||
String name = null;
|
||||
try {
|
||||
name = (String) getNickname.invoke(getUser.invoke(Bukkit.getPluginManager().getPlugin("Essentials"), p.getPlayer()));
|
||||
name = (String) essGetNickname.invoke(essGetUser.invoke(essentials, p.getPlayer()));
|
||||
} catch (Exception e) {
|
||||
TAB.getInstance().getErrorManager().printError("Failed to get Essentials nickname of " + p.getName(), e);
|
||||
}
|
||||
if (name == null || name.length() == 0) return p.getName();
|
||||
return TAB.getInstance().getConfiguration().essentialsNickPrefix + name;
|
||||
return TAB.getInstance().getConfiguration().getEssentialsNickPrefix() + name;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
@@ -285,33 +273,30 @@ public class BukkitPlaceholderRegistry implements PlaceholderRegistry {
|
||||
*/
|
||||
private void registerSyncPlaceholders() {
|
||||
PlaceholderManager pl = TAB.getInstance().getPlaceholderManager();
|
||||
for (String identifier : pl.allUsedPlaceholderIdentifiers) {
|
||||
for (String identifier : pl.getAllUsedPlaceholderIdentifiers()) {
|
||||
if (identifier.startsWith("%sync:")) {
|
||||
int refresh;
|
||||
if (pl.serverPlaceholderRefreshIntervals.containsKey(identifier)) {
|
||||
refresh = pl.serverPlaceholderRefreshIntervals.get(identifier);
|
||||
} else if (pl.playerPlaceholderRefreshIntervals.containsKey(identifier)) {
|
||||
refresh = pl.playerPlaceholderRefreshIntervals.get(identifier);
|
||||
if (pl.getServerPlaceholderRefreshIntervals().containsKey(identifier)) {
|
||||
refresh = pl.getServerPlaceholderRefreshIntervals().get(identifier);
|
||||
} else if (pl.getPlayerPlaceholderRefreshIntervals().containsKey(identifier)) {
|
||||
refresh = pl.getPlayerPlaceholderRefreshIntervals().get(identifier);
|
||||
} else {
|
||||
refresh = pl.defaultRefresh;
|
||||
refresh = pl.getDefaultRefresh();
|
||||
}
|
||||
placeholders.add(new PlayerPlaceholder(identifier, refresh) {
|
||||
|
||||
@Override
|
||||
public String get(TabPlayer p) {
|
||||
Bukkit.getScheduler().runTask(plugin, new Runnable() {
|
||||
Bukkit.getScheduler().runTask(plugin, () -> {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
long time = System.nanoTime();
|
||||
String syncedPlaceholder = identifier.substring(6, identifier.length()-1);
|
||||
String value = ((BukkitPlatform) TAB.getInstance().getPlatform()).setPlaceholders((Player) p.getPlayer(), "%" + syncedPlaceholder + "%");
|
||||
lastValue.put(p.getName(), value);
|
||||
if (!forceUpdate.contains(p.getName())) forceUpdate.add(p.getName());
|
||||
TAB.getInstance().getCPUManager().addPlaceholderTime(getIdentifier(), System.nanoTime()-time);
|
||||
}
|
||||
long time = System.nanoTime();
|
||||
String syncedPlaceholder = identifier.substring(6, identifier.length()-1);
|
||||
String value = ((BukkitPlatform) TAB.getInstance().getPlatform()).setPlaceholders((Player) p.getPlayer(), "%" + syncedPlaceholder + "%");
|
||||
getLastValues().put(p.getName(), value);
|
||||
if (!getForceUpdate().contains(p.getName())) getForceUpdate().add(p.getName());
|
||||
TAB.getInstance().getCPUManager().addPlaceholderTime(getIdentifier(), System.nanoTime()-time);
|
||||
});
|
||||
return lastValue.get(p.getName());
|
||||
return getLastValues().get(p.getName());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2,18 +2,16 @@ package me.neznamy.tab.platforms.bukkit;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import me.neznamy.tab.api.event.BukkitTABLoadEvent;
|
||||
import me.neznamy.tab.platforms.bukkit.features.BossBar_legacy;
|
||||
import me.neznamy.tab.platforms.bukkit.features.ExpansionDownloader;
|
||||
import me.neznamy.tab.platforms.bukkit.features.WitherBossBar;
|
||||
import me.neznamy.tab.platforms.bukkit.features.PerWorldPlayerlist;
|
||||
import me.neznamy.tab.platforms.bukkit.features.PetFix;
|
||||
import me.neznamy.tab.platforms.bukkit.features.TabExpansion;
|
||||
@@ -44,9 +42,6 @@ import net.milkbowl.vault.permission.Permission;
|
||||
* Bukkit implementation of Platform
|
||||
*/
|
||||
public class BukkitPlatform implements Platform {
|
||||
|
||||
//list of used expansions
|
||||
private Set<String> usedExpansions;
|
||||
|
||||
//plugin instance
|
||||
private JavaPlugin plugin;
|
||||
@@ -55,11 +50,11 @@ public class BukkitPlatform implements Platform {
|
||||
private NMSStorage nms;
|
||||
|
||||
//booleans to check plugin presence
|
||||
public boolean placeholderAPI;
|
||||
public boolean viaversion;
|
||||
public boolean idisguise;
|
||||
public boolean libsdisguises;
|
||||
public boolean essentials;
|
||||
private Plugin placeholderAPI;
|
||||
private boolean viaversion;
|
||||
private boolean idisguise;
|
||||
private boolean libsdisguises;
|
||||
private boolean essentials;
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters
|
||||
@@ -85,37 +80,34 @@ public class BukkitPlatform implements Platform {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadFeatures() throws Exception {
|
||||
placeholderAPI = Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI");
|
||||
public void loadFeatures() {
|
||||
placeholderAPI = Bukkit.getPluginManager().getPlugin("PlaceholderAPI");
|
||||
viaversion = Bukkit.getPluginManager().isPluginEnabled("ViaVersion");
|
||||
idisguise = Bukkit.getPluginManager().isPluginEnabled("iDisguise");
|
||||
libsdisguises = Bukkit.getPluginManager().isPluginEnabled("LibsDisguises");
|
||||
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 (nms.minorVersion >= 8 && tab.getConfiguration().pipelineInjection) {
|
||||
if (nms.getMinorVersion() >= 8 && tab.getConfiguration().isPipelineInjection()) {
|
||||
tab.getFeatureManager().registerFeature("injection", new BukkitPipelineInjector(tab, nms));
|
||||
}
|
||||
loadNametagFeature(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().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) {
|
||||
if (tab.getConfiguration().getConfig().getBoolean("ping-spoof.enabled", false)) tab.getFeatureManager().registerFeature("pingspoof", new PingSpoof());
|
||||
if (tab.getConfiguration().getConfig().getString("yellow-number-in-tablist", "%ping%").length() > 0) tab.getFeatureManager().registerFeature("tabobjective", new TabObjective(tab));
|
||||
if (tab.getConfiguration().getConfig().getBoolean("do-not-move-spectators", false)) tab.getFeatureManager().registerFeature("spectatorfix", new SpectatorFix());
|
||||
if (tab.getConfiguration().getConfig().getBoolean("classic-vanilla-belowname.enabled", true)) tab.getFeatureManager().registerFeature("belowname", new BelowName(tab));
|
||||
if (tab.getConfiguration().getPremiumConfig() != null && tab.getConfiguration().getPremiumConfig().getBoolean("scoreboard.enabled", false)) tab.getFeatureManager().registerFeature("scoreboard", new ScoreboardManager(tab));
|
||||
if (tab.getConfiguration().getBossbarConfig().getBoolean("bossbar-enabled", false) && nms.getMinorVersion() < 9) tab.getFeatureManager().registerFeature("bossbar1.8", new WitherBossBar(tab, plugin));
|
||||
if (nms.getMinorVersion() >= 9 && tab.getConfiguration().getConfig().getBoolean("fix-pet-names", false)) tab.getFeatureManager().registerFeature("petfix", new PetFix(nms));
|
||||
if (tab.getConfiguration().getConfig().getBoolean("per-world-playerlist.enabled", false)) tab.getFeatureManager().registerFeature("pwp", new PerWorldPlayerlist(plugin, tab));
|
||||
if (placeholderAPI != null) {
|
||||
new TabExpansion(plugin);
|
||||
new ExpansionDownloader(plugin).download(usedExpansions);
|
||||
}
|
||||
|
||||
for (Player p : getOnlinePlayers()) {
|
||||
tab.addPlayer(new BukkitTabPlayer(p));
|
||||
tab.addPlayer(new BukkitTabPlayer(p, Main.getProtocolVersion(p)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,8 +116,8 @@ public class BukkitPlatform implements Platform {
|
||||
* @param tab - tab instance
|
||||
*/
|
||||
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) && nms.minorVersion >= 8) {
|
||||
if (tab.getConfiguration().getConfig().getBoolean("change-nametag-prefix-suffix", true)) {
|
||||
if (tab.getConfiguration().getConfig().getBoolean("unlimited-nametag-prefix-suffix-mode.enabled", false) && nms.getMinorVersion() >= 8) {
|
||||
tab.getFeatureManager().registerFeature("nametagx", new NameTagX(plugin, nms, tab));
|
||||
} else {
|
||||
tab.getFeatureManager().registerFeature("nametag16", new NameTag(tab));
|
||||
@@ -136,17 +128,21 @@ public class BukkitPlatform implements Platform {
|
||||
/**
|
||||
* Returns list of online players from Bukkit API
|
||||
* @return list of online players from Bukkit API
|
||||
* @throws Exception - if reflection fails
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private Player[] getOnlinePlayers() throws Exception {
|
||||
Object players = Bukkit.class.getMethod("getOnlinePlayers").invoke(null);
|
||||
if (players instanceof Player[]) {
|
||||
//1.7.x
|
||||
return (Player[]) players;
|
||||
} else {
|
||||
//1.8+
|
||||
return ((Collection<Player>)players).toArray(new Player[0]);
|
||||
private Player[] getOnlinePlayers() {
|
||||
try {
|
||||
Object players = Bukkit.class.getMethod("getOnlinePlayers").invoke(null);
|
||||
if (players instanceof Player[]) {
|
||||
//1.7.x
|
||||
return (Player[]) players;
|
||||
} else {
|
||||
//1.8+
|
||||
return ((Collection<Player>)players).toArray(new Player[0]);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
TAB.getInstance().getErrorManager().printError("Failed to get online players", e);
|
||||
return new Player[0];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,18 +160,17 @@ public class BukkitPlatform implements Platform {
|
||||
registerRelationalPlaceholder(identifier, pl.getRelationalRefresh(identifier));
|
||||
} else {
|
||||
//normal placeholder
|
||||
String plugin = identifier.split("_")[0].substring(1).toLowerCase();
|
||||
if (plugin.equals("some")) return;
|
||||
usedExpansions.add(plugin);
|
||||
if (pl.serverPlaceholderRefreshIntervals.containsKey(identifier)) {
|
||||
registerServerPlaceholder(identifier, pl.serverPlaceholderRefreshIntervals.get(identifier));
|
||||
String expansion = identifier.split("_")[0].substring(1).toLowerCase();
|
||||
if (expansion.equals("some")) return;
|
||||
if (pl.getServerPlaceholderRefreshIntervals().containsKey(identifier)) {
|
||||
registerServerPlaceholder(identifier, pl.getServerPlaceholderRefreshIntervals().get(identifier));
|
||||
return;
|
||||
}
|
||||
if (pl.playerPlaceholderRefreshIntervals.containsKey(identifier)) {
|
||||
registerPlayerPlaceholder(identifier, pl.playerPlaceholderRefreshIntervals.get(identifier));
|
||||
if (pl.getPlayerPlaceholderRefreshIntervals().containsKey(identifier)) {
|
||||
registerPlayerPlaceholder(identifier, pl.getPlayerPlaceholderRefreshIntervals().get(identifier));
|
||||
return;
|
||||
}
|
||||
registerPlayerPlaceholder(identifier, pl.defaultRefresh);
|
||||
registerPlayerPlaceholder(identifier, pl.getDefaultRefresh());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -186,11 +181,12 @@ public class BukkitPlatform implements Platform {
|
||||
* @param refresh - refresh interval in milliseconds
|
||||
*/
|
||||
private void registerServerPlaceholder(String identifier, int refresh) {
|
||||
BukkitPlatform pl = this;
|
||||
TAB.getInstance().getPlaceholderManager().registerPlaceholder(new ServerPlaceholder(identifier, TAB.getInstance().getErrorManager().fixPlaceholderInterval(identifier, refresh)){
|
||||
|
||||
@Override
|
||||
public String get() {
|
||||
return setPlaceholders(null, identifier);
|
||||
return pl.setPlaceholders(null, identifier);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -201,11 +197,12 @@ public class BukkitPlatform implements Platform {
|
||||
* @param refresh - refresh interval in milliseconds
|
||||
*/
|
||||
private void registerPlayerPlaceholder(String identifier, int refresh) {
|
||||
BukkitPlatform pl = this;
|
||||
TAB.getInstance().getPlaceholderManager().registerPlaceholder(new PlayerPlaceholder(identifier, TAB.getInstance().getErrorManager().fixPlaceholderInterval(identifier, refresh)) {
|
||||
|
||||
@Override
|
||||
public String get(TabPlayer p) {
|
||||
return setPlaceholders((Player) p.getPlayer(), identifier);
|
||||
return pl.setPlaceholders((Player) p.getPlayer(), identifier);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -220,11 +217,11 @@ public class BukkitPlatform implements Platform {
|
||||
|
||||
@Override
|
||||
public String get(TabPlayer viewer, TabPlayer target) {
|
||||
if (!placeholderAPI) return identifier;
|
||||
if (placeholderAPI == null) return identifier;
|
||||
try {
|
||||
return PlaceholderAPI.setRelationalPlaceholders((Player) viewer.getPlayer(), (Player) target.getPlayer(), identifier);
|
||||
} catch (Throwable t) {
|
||||
TAB.getInstance().getErrorManager().printError("PlaceholderAPI v" + Bukkit.getPluginManager().getPlugin("PlaceholderAPI").getDescription().getVersion() + " generated an error when setting relational placeholder " + identifier + " for viewer " + viewer.getName() + " and target " + target.getName(), t, false, TAB.getInstance().getErrorManager().papiErrorLog);
|
||||
} catch (Exception t) {
|
||||
TAB.getInstance().getErrorManager().printError("PlaceholderAPI v" + placeholderAPI.getDescription().getVersion() + " generated an error when setting relational placeholder " + identifier + " for viewer " + viewer.getName() + " and target " + target.getName(), t, false, TAB.getInstance().getErrorManager().getPapiErrorLog());
|
||||
}
|
||||
return identifier;
|
||||
}
|
||||
@@ -238,12 +235,12 @@ public class BukkitPlatform implements Platform {
|
||||
* @return result from PlaceholderAPI
|
||||
*/
|
||||
public String setPlaceholders(Player player, String placeholder) {
|
||||
if (!placeholderAPI) return placeholder;
|
||||
if (placeholderAPI == null) return placeholder;
|
||||
try {
|
||||
return PlaceholderAPI.setPlaceholders(player, placeholder);
|
||||
} catch (Throwable t) {
|
||||
} catch (Exception t) {
|
||||
String playername = (player == null ? "<null>" : player.getName());
|
||||
TAB.getInstance().getErrorManager().printError("PlaceholderAPI v" + Bukkit.getPluginManager().getPlugin("PlaceholderAPI").getDescription().getVersion() + " generated an error when setting placeholder " + placeholder + " for player " + playername, t, false, TAB.getInstance().getErrorManager().papiErrorLog);
|
||||
TAB.getInstance().getErrorManager().printError("PlaceholderAPI v" + placeholderAPI.getDescription().getVersion() + " generated an error when setting placeholder " + placeholder + " for player " + playername, t, false, TAB.getInstance().getErrorManager().getPapiErrorLog());
|
||||
return "ERROR";
|
||||
}
|
||||
}
|
||||
@@ -296,4 +293,20 @@ public class BukkitPlatform implements Platform {
|
||||
public String getConfigName() {
|
||||
return "bukkitconfig.yml";
|
||||
}
|
||||
|
||||
public boolean isViaversionEnabled() {
|
||||
return viaversion;
|
||||
}
|
||||
|
||||
public boolean isLibsdisguisesEnabled() {
|
||||
return libsdisguises;
|
||||
}
|
||||
|
||||
public boolean isIdisguiseEnabled() {
|
||||
return idisguise;
|
||||
}
|
||||
|
||||
public boolean isEssentialsEnabled() {
|
||||
return essentials;
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,12 @@
|
||||
package me.neznamy.tab.platforms.bukkit;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
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.viaversion.viaversion.api.Via;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.boss.BarColor;
|
||||
import org.bukkit.boss.BarFlag;
|
||||
@@ -15,9 +14,11 @@ 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;
|
||||
import org.bukkit.metadata.MetadataValue;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.Channel;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.NMSStorage;
|
||||
@@ -42,78 +43,33 @@ public class BukkitTabPlayer extends ITabPlayer {
|
||||
private Object playerConnection;
|
||||
|
||||
//player's visible boss bars
|
||||
private Map<UUID, BossBar> bossbars = new HashMap<UUID, BossBar>();
|
||||
private Map<UUID, BossBar> bossbars = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameter
|
||||
* @param p - bukkit player
|
||||
*/
|
||||
public BukkitTabPlayer(Player p){
|
||||
public BukkitTabPlayer(Player p, int protocolVersion){
|
||||
player = p;
|
||||
world = p.getWorld().getName();
|
||||
try {
|
||||
handle = NMSStorage.getInstance().getHandle.invoke(player);
|
||||
playerConnection = NMSStorage.getInstance().PLAYER_CONNECTION.get(handle);
|
||||
handle = NMSStorage.getInstance().getMethod("getHandle").invoke(player);
|
||||
playerConnection = NMSStorage.getInstance().getField("PLAYER_CONNECTION").get(handle);
|
||||
} catch (Exception e) {
|
||||
TAB.getInstance().getErrorManager().printError("Failed to get playerConnection of " + p.getName(), e);
|
||||
}
|
||||
try {
|
||||
if (NMSStorage.getInstance().CHANNEL != null)
|
||||
channel = (Channel) NMSStorage.getInstance().CHANNEL.get(NMSStorage.getInstance().NETWORK_MANAGER.get(playerConnection));
|
||||
if (NMSStorage.getInstance().getField("CHANNEL") != null)
|
||||
channel = (Channel) NMSStorage.getInstance().getField("CHANNEL").get(NMSStorage.getInstance().getField("NETWORK_MANAGER").get(playerConnection));
|
||||
} catch (Exception e) {
|
||||
TAB.getInstance().getErrorManager().printError("Failed to get channel of " + p.getName(), e);
|
||||
}
|
||||
uniqueId = p.getUniqueId();
|
||||
name = p.getName();
|
||||
version = ProtocolVersion.fromNetworkId(getProtocolVersion());
|
||||
version = ProtocolVersion.fromNetworkId(protocolVersion);
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets protocol version and returns it
|
||||
* @return protocol version of this player
|
||||
*/
|
||||
private int getProtocolVersion() {
|
||||
if (Bukkit.getPluginManager().isPluginEnabled("ProtocolSupport")){
|
||||
int version = getProtocolVersionPS();
|
||||
//some PS versions return -1 on unsupported server versions instead of throwing exception
|
||||
if (version != -1 && version < ProtocolVersion.SERVER_VERSION.getNetworkId()) return version;
|
||||
}
|
||||
if (((BukkitPlatform)TAB.getInstance().getPlatform()).viaversion) {
|
||||
return getProtocolVersionVia();
|
||||
}
|
||||
return ProtocolVersion.SERVER_VERSION.getNetworkId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns protocol version of this player using ProtocolSupport
|
||||
* @return protocol version of this player using ProtocolSupport
|
||||
*/
|
||||
private int getProtocolVersionPS(){
|
||||
try {
|
||||
Object protocolVersion = Class.forName("protocolsupport.api.ProtocolSupportAPI").getMethod("getProtocolVersion", Player.class).invoke(null, player);
|
||||
int version = (int) protocolVersion.getClass().getMethod("getId").invoke(protocolVersion);
|
||||
TAB.getInstance().debug("ProtocolSupport returned protocol version " + version + " for " + getName());
|
||||
return version;
|
||||
} catch (Throwable e) {
|
||||
return TAB.getInstance().getErrorManager().printError(ProtocolVersion.SERVER_VERSION.getNetworkId(), "Failed to get protocol version of " + getName() + " using ProtocolSupport", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns protocol version of this player using ViaVersion
|
||||
* @return protocol version of this player using ViaVersion
|
||||
*/
|
||||
private int getProtocolVersionVia(){
|
||||
try {
|
||||
int version = Via.getAPI().getPlayerVersion(uniqueId);
|
||||
TAB.getInstance().debug("ViaVersion returned protocol version " + version + " for " + getName());
|
||||
return version;
|
||||
} catch (Throwable e) {
|
||||
return TAB.getInstance().getErrorManager().printError(ProtocolVersion.SERVER_VERSION.getNetworkId(), "Failed to get protocol version of " + getName() + " using ViaVersion v" + Bukkit.getPluginManager().getPlugin("ViaVersion").getDescription().getVersion() + ". Is it the latest version?", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String permission) {
|
||||
return player.hasPermission(permission);
|
||||
@@ -122,7 +78,7 @@ public class BukkitTabPlayer extends ITabPlayer {
|
||||
@Override
|
||||
public long getPing() {
|
||||
try {
|
||||
int ping = NMSStorage.getInstance().PING.getInt(handle);
|
||||
int ping = NMSStorage.getInstance().getField("PING").getInt(handle);
|
||||
if (ping > 10000 || ping < 0) ping = -1;
|
||||
return ping;
|
||||
} catch (Exception e) {
|
||||
@@ -134,63 +90,58 @@ public class BukkitTabPlayer extends ITabPlayer {
|
||||
public void sendPacket(Object nmsPacket) {
|
||||
if (nmsPacket == null || !player.isOnline()) return;
|
||||
try {
|
||||
if (((BukkitPlatform)TAB.getInstance().getPlatform()).viaversion && nmsPacket instanceof ByteBuf) {
|
||||
try {
|
||||
Via.getAPI().sendRawPacket(uniqueId, (ByteBuf) nmsPacket);
|
||||
} catch (IllegalArgumentException e) {
|
||||
//java.lang.IllegalArgumentException: This player is not controlled by ViaVersion!
|
||||
//this is only used to send 1.9 bossbar packets on 1.8 servers, no idea why it does this sometimes
|
||||
}
|
||||
if (((BukkitPlatform)TAB.getInstance().getPlatform()).isViaversionEnabled() && nmsPacket instanceof ByteBuf) {
|
||||
Via.getAPI().sendRawPacket(uniqueId, (ByteBuf) nmsPacket);
|
||||
return;
|
||||
}
|
||||
if (nmsPacket instanceof PacketPlayOutBoss) {
|
||||
handle((PacketPlayOutBoss) nmsPacket);
|
||||
return;
|
||||
}
|
||||
NMSStorage.getInstance().sendPacket.invoke(playerConnection, nmsPacket);
|
||||
} catch (Throwable e) {
|
||||
NMSStorage.getInstance().getMethod("sendPacket").invoke(playerConnection, nmsPacket);
|
||||
} catch (IllegalArgumentException e) {
|
||||
//java.lang.IllegalArgumentException: This player is not controlled by ViaVersion!
|
||||
//this is only used to send 1.9 bossbar packets on 1.8 servers, no idea why it does this sometimes
|
||||
} catch (Exception 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>();
|
||||
Set<BarFlag> flags = new HashSet<>();
|
||||
BossBar bar;
|
||||
switch (packet.operation) {
|
||||
switch (packet.getOperation()) {
|
||||
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")),
|
||||
if (packet.isCreateWorldFog()) flags.add(BarFlag.CREATE_FOG);
|
||||
if (packet.isDarkenScreen()) flags.add(BarFlag.DARKEN_SKY);
|
||||
if (packet.isPlayMusic()) flags.add(BarFlag.PLAY_BOSS_MUSIC);
|
||||
bar = Bukkit.createBossBar(RGBUtils.getInstance().convertToBukkitFormat(packet.getName(), getVersion().getMinorVersion() >= 16 && NMSStorage.getInstance().getMinorVersion() >= 16),
|
||||
BarColor.valueOf(packet.getColor().name()),
|
||||
BarStyle.valueOf(packet.getOverlay().name().replace("PROGRESS", "SOLID").replace("NOTCHED", "SEGMENTED")),
|
||||
flags.toArray(new BarFlag[0]));
|
||||
bossbars.put(packet.id, bar);
|
||||
bar.setProgress(packet.getPct());
|
||||
bossbars.put(packet.getId(), bar);
|
||||
bar.addPlayer(player);
|
||||
break;
|
||||
case REMOVE:
|
||||
bossbars.get(packet.id).removePlayer(player);
|
||||
bossbars.remove(packet.id);
|
||||
bossbars.get(packet.getId()).removePlayer(player);
|
||||
bossbars.remove(packet.getId());
|
||||
break;
|
||||
case UPDATE_PCT:
|
||||
bossbars.get(packet.id).setProgress(packet.pct);
|
||||
bossbars.get(packet.getId()).setProgress(packet.getPct());
|
||||
break;
|
||||
case UPDATE_NAME:
|
||||
bossbars.get(packet.id).setTitle(RGBUtils.getInstance().convertToBukkitFormat(packet.name, getVersion().getMinorVersion() >= 16 && NMSStorage.getInstance().minorVersion >= 16));
|
||||
bossbars.get(packet.getId()).setTitle(RGBUtils.getInstance().convertToBukkitFormat(packet.getName(), getVersion().getMinorVersion() >= 16 && NMSStorage.getInstance().getMinorVersion() >= 16));
|
||||
break;
|
||||
case UPDATE_STYLE:
|
||||
bar = bossbars.get(packet.id);
|
||||
//yet another platform with yet another buggy bossbar API, how lovely it is regressing back to APIs instead of internals
|
||||
bar.removePlayer(player);
|
||||
bar.setColor(BarColor.valueOf(packet.color.name()));
|
||||
bar.setStyle(BarStyle.valueOf(packet.overlay.name().replace("PROGRESS", "SOLID").replace("NOTCHED", "SEGMENTED")));
|
||||
bar.addPlayer(player);
|
||||
bossbars.get(packet.getId()).setColor(BarColor.valueOf(packet.getColor().name()));
|
||||
bossbars.get(packet.getId()).setStyle(BarStyle.valueOf(packet.getOverlay().name().replace("PROGRESS", "SOLID").replace("NOTCHED", "SEGMENTED")));
|
||||
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);
|
||||
bar = bossbars.get(packet.getId());
|
||||
processFlag(bar, packet.isCreateWorldFog(), BarFlag.CREATE_FOG);
|
||||
processFlag(bar, packet.isDarkenScreen(), BarFlag.DARKEN_SKY);
|
||||
processFlag(bar, packet.isPlayMusic(), BarFlag.PLAY_BOSS_MUSIC);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -216,44 +167,19 @@ public class BukkitTabPlayer extends ITabPlayer {
|
||||
|
||||
@Override
|
||||
public boolean isDisguised() {
|
||||
return isDisguisedLD() || isDisguisediDis();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns disguise status of player using LibsDisguises
|
||||
* @return disguise status of player using LibsDisguises
|
||||
*/
|
||||
private boolean isDisguisedLD() {
|
||||
try {
|
||||
if (!((BukkitPlatform)TAB.getInstance().getPlatform()).libsdisguises) return false;
|
||||
if (!((BukkitPlatform)TAB.getInstance().getPlatform()).isLibsdisguisesEnabled()) return false;
|
||||
return (boolean) Class.forName("me.libraryaddict.disguise.DisguiseAPI").getMethod("isDisguised", Entity.class).invoke(null, player);
|
||||
} catch (Throwable e) {
|
||||
} catch (Exception e) {
|
||||
return TAB.getInstance().getErrorManager().printError(false, "Failed to check disguise status using LibsDisguises", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns disguise status of player using iDisguise
|
||||
* @return disguise status of player using iDisguise
|
||||
*/
|
||||
private boolean isDisguisediDis() {
|
||||
try {
|
||||
if (!((BukkitPlatform)TAB.getInstance().getPlatform()).idisguise) return false;
|
||||
RegisteredServiceProvider<?> provider = Bukkit.getServicesManager().getRegistration(Class.forName("de.robingrether.idisguise.api.DisguiseAPI"));
|
||||
Object iDisguise = provider.getProvider();
|
||||
Method m = iDisguise.getClass().getMethod("isDisguised", Player.class);
|
||||
m.setAccessible(true);
|
||||
return (boolean) m.invoke(iDisguise, player);
|
||||
} catch (Throwable e) {
|
||||
return TAB.getInstance().getErrorManager().printError(false, "Failed to check disguise status using iDisguise", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSkin() {
|
||||
try {
|
||||
return Class.forName("com.mojang.authlib.GameProfile").getMethod("getProperties").invoke(NMSStorage.getInstance().getProfile.invoke(handle));
|
||||
} catch (Throwable e) {
|
||||
return Class.forName("com.mojang.authlib.GameProfile").getMethod("getProperties").invoke(NMSStorage.getInstance().getMethod("getProfile").invoke(handle));
|
||||
} catch (Exception e) {
|
||||
return TAB.getInstance().getErrorManager().printError(null, "Failed to get skin of " + getName(), e);
|
||||
}
|
||||
}
|
||||
@@ -271,15 +197,14 @@ public class BukkitTabPlayer extends ITabPlayer {
|
||||
@Override
|
||||
public boolean isVanished() {
|
||||
try {
|
||||
if (((BukkitPlatform)TAB.getInstance().getPlatform()).essentials) {
|
||||
if (((BukkitPlatform)TAB.getInstance().getPlatform()).isEssentialsEnabled()) {
|
||||
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();
|
||||
}
|
||||
List<MetadataValue> metadata = player.getMetadata("vanished");
|
||||
return !metadata.isEmpty() && metadata.get(0).asBoolean();
|
||||
} catch (Exception e) {
|
||||
TAB.getInstance().getErrorManager().printError("Failed to check vanish status of " + player.getName(), e);
|
||||
}
|
||||
|
||||
@@ -4,10 +4,18 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.bstats.bukkit.Metrics;
|
||||
import org.bstats.charts.SimplePie;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.NMSStorage;
|
||||
import me.neznamy.tab.shared.ProtocolVersion;
|
||||
@@ -20,42 +28,26 @@ public class Main extends JavaPlugin {
|
||||
|
||||
@Override
|
||||
public void onEnable(){
|
||||
ProtocolVersion.SERVER_VERSION = ProtocolVersion.fromFriendlyName(Bukkit.getBukkitVersion().split("-")[0]);
|
||||
Bukkit.getConsoleSender().sendMessage("\u00a77[TAB] Server version: " + Bukkit.getBukkitVersion().split("-")[0] + " (" + Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3] + ")");
|
||||
if (!isVersionSupported()){
|
||||
Bukkit.getPluginManager().disablePlugin(this);
|
||||
return;
|
||||
}
|
||||
if (ProtocolVersion.SERVER_VERSION == ProtocolVersion.UNKNOWN) {
|
||||
TAB.setInstance(new TAB(new BukkitPlatform(this, NMSStorage.getInstance()), new BukkitPacketBuilder(NMSStorage.getInstance()), ProtocolVersion.fromFriendlyName(Bukkit.getBukkitVersion().split("-")[0])));
|
||||
if (TAB.getInstance().getServerVersion() == ProtocolVersion.UNKNOWN) {
|
||||
Bukkit.getConsoleSender().sendMessage("\u00a7c[TAB] Unknown server version: " + Bukkit.getBukkitVersion() + "! Plugin may not work correctly.");
|
||||
}
|
||||
TAB.setInstance(new TAB(new BukkitPlatform(this, NMSStorage.getInstance()), new BukkitPacketBuilder(NMSStorage.getInstance())));
|
||||
Bukkit.getPluginManager().registerEvents(new BukkitEventListener(), this);
|
||||
Bukkit.getPluginCommand("tab").setExecutor((sender, c, cmd, args) -> {
|
||||
if (TAB.getInstance().isDisabled()) {
|
||||
for (String message : TAB.getInstance().disabledCommand.execute(args, sender.hasPermission("tab.reload"), sender.hasPermission("tab.admin"))) {
|
||||
sender.sendMessage(message.replace('&', '\u00a7'));
|
||||
}
|
||||
} else {
|
||||
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) -> {
|
||||
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);
|
||||
});
|
||||
TABCommand command = new TABCommand();
|
||||
Bukkit.getPluginCommand("tab").setExecutor(command);
|
||||
Bukkit.getPluginCommand("tab").setTabCompleter(command);
|
||||
TAB.getInstance().load();
|
||||
new BukkitMetrics(this);
|
||||
Metrics metrics = new Metrics(this, 5304);
|
||||
metrics.addCustomChart(new SimplePie("unlimited_nametag_mode_enabled", () -> TAB.getInstance().getFeatureManager().isFeatureEnabled("nametagx") ? "Yes" : "No"));
|
||||
metrics.addCustomChart(new SimplePie("placeholderapi", () -> Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI") ? "Yes" : "No"));
|
||||
metrics.addCustomChart(new SimplePie("permission_system", () -> TAB.getInstance().getPermissionPlugin().getName()));
|
||||
metrics.addCustomChart(new SimplePie("server_version", () -> "1." + NMSStorage.getInstance().getMinorVersion() + ".x"));
|
||||
metrics.addCustomChart(new SimplePie("using_premium_version", () -> TAB.getInstance().isPremium() ? "Yes" : "No"));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -69,7 +61,7 @@ public class Main extends JavaPlugin {
|
||||
* @return true if compatible, false if not
|
||||
*/
|
||||
private boolean isVersionSupported(){
|
||||
List<String> SUPPORTED_VERSIONS = Arrays.asList(
|
||||
List<String> supportedVersions = 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",
|
||||
@@ -77,19 +69,99 @@ public class Main extends JavaPlugin {
|
||||
String serverPackage = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
|
||||
try {
|
||||
NMSStorage.setInstance(new NMSStorage());
|
||||
if (SUPPORTED_VERSIONS.contains(serverPackage)) {
|
||||
if (supportedVersions.contains(serverPackage)) {
|
||||
return true;
|
||||
} else {
|
||||
Bukkit.getConsoleSender().sendMessage("\u00a7c[TAB] This plugin version does not claim to support your server version. This jar has only been tested on 1.7.x - 1.16.5. Disabling.");
|
||||
Bukkit.getConsoleSender().sendMessage("\u00a7c[TAB] No compatibility issue was found, but this plugin version does not claim to support your server version. This jar has only been tested on 1.5.x - 1.17. Disabling just to stay safe.");
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
if (SUPPORTED_VERSIONS.contains(serverPackage)) {
|
||||
} catch (Exception ex) {
|
||||
if (supportedVersions.contains(serverPackage)) {
|
||||
Bukkit.getConsoleSender().sendMessage("\u00a7c[TAB] Your server version is marked as compatible, but a compatibility issue was found. Please report the error below (include your server version & fork too)");
|
||||
e.printStackTrace();
|
||||
Bukkit.getConsoleSender().sendMessage(ex.getClass().getName() + ": " + ex.getMessage());
|
||||
for (StackTraceElement e : ex.getStackTrace()) {
|
||||
Bukkit.getConsoleSender().sendMessage("\t" + e.toString());
|
||||
}
|
||||
} else {
|
||||
Bukkit.getConsoleSender().sendMessage("\u00a7c[TAB] Your server version is completely unsupported. This plugin version only supports 1.7.x - 1.16.5. Disabling.");
|
||||
Bukkit.getConsoleSender().sendMessage("\u00a7c[TAB] Your server version is completely unsupported. This plugin version only supports 1.5.x - 1.17. Disabling.");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets protocol version and returns it
|
||||
* @return protocol version of this player
|
||||
*/
|
||||
public static int getProtocolVersion(Player player) {
|
||||
if (Bukkit.getPluginManager().isPluginEnabled("ProtocolSupport")){
|
||||
int version = getProtocolVersionPS(player);
|
||||
//some PS versions return -1 on unsupported server versions instead of throwing exception
|
||||
if (version != -1 && version < TAB.getInstance().getServerVersion().getNetworkId()) return version;
|
||||
}
|
||||
if (Bukkit.getPluginManager().isPluginEnabled("ViaVersion")) {
|
||||
return getProtocolVersionVia(player);
|
||||
}
|
||||
return TAB.getInstance().getServerVersion().getNetworkId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns protocol version of this player using ProtocolSupport
|
||||
* @return protocol version of this player using ProtocolSupport
|
||||
*/
|
||||
private static int getProtocolVersionPS(Player player){
|
||||
try {
|
||||
Object protocolVersion = Class.forName("protocolsupport.api.ProtocolSupportAPI").getMethod("getProtocolVersion", Player.class).invoke(null, player);
|
||||
int version = (int) protocolVersion.getClass().getMethod("getId").invoke(protocolVersion);
|
||||
TAB.getInstance().debug("ProtocolSupport returned protocol version " + version + " for " + player.getName() + "(online=" + player.isOnline() + ")");
|
||||
return version;
|
||||
} catch (Exception e) {
|
||||
TAB.getInstance().getErrorManager().printError("Failed to get protocol version of " + player.getName() + " using ProtocolSupport", e);
|
||||
return TAB.getInstance().getServerVersion().getNetworkId();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns protocol version of this player using ViaVersion
|
||||
* @return protocol version of this player using ViaVersion
|
||||
*/
|
||||
private static int getProtocolVersionVia(Player player){
|
||||
try {
|
||||
int version = Via.getAPI().getPlayerVersion(player.getUniqueId());
|
||||
TAB.getInstance().debug("ViaVersion returned protocol version " + version + " for " + player.getName() + "(online=" + player.isOnline() + ")");
|
||||
return version;
|
||||
} catch (Exception e) {
|
||||
TAB.getInstance().getErrorManager().printError("Failed to get protocol version of " + player.getName() + " using ViaVersion v" + Bukkit.getPluginManager().getPlugin("ViaVersion").getDescription().getVersion(), e);
|
||||
return TAB.getInstance().getServerVersion().getNetworkId();
|
||||
}
|
||||
}
|
||||
|
||||
public class TABCommand implements CommandExecutor, TabCompleter {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (TAB.getInstance().isDisabled()) {
|
||||
for (String message : TAB.getInstance().getDisabledCommand().execute(args, sender.hasPermission("tab.reload"), sender.hasPermission("tab.admin"))) {
|
||||
sender.sendMessage(message.replace('&', '\u00a7'));
|
||||
}
|
||||
} else {
|
||||
TabPlayer p = null;
|
||||
if (sender instanceof Player) {
|
||||
p = TAB.getInstance().getPlayer(((Player)sender).getUniqueId());
|
||||
if (p == null) return true; //player not loaded correctly
|
||||
}
|
||||
TAB.getInstance().getCommand().execute(p, args);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
|
||||
TabPlayer p = null;
|
||||
if (sender instanceof Player) {
|
||||
p = TAB.getInstance().getPlayer(((Player)sender).getUniqueId());
|
||||
if (p == null) return new ArrayList<>(); //player not loaded correctly
|
||||
}
|
||||
return TAB.getInstance().getCommand().complete(p, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
-99
@@ -1,99 +0,0 @@
|
||||
package me.neznamy.tab.platforms.bukkit.features;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
|
||||
/**
|
||||
* Utility to execute /papi ecloud download <expansion> on expansions which are used but not installed
|
||||
* If an expansion was successfully downloaded (new expansion count is higher than previous in expansions folder),
|
||||
* /papi reload is executed.
|
||||
* Since this feature was added into the plugin amount of non-working placeholders caused by missing expansion went down rapidly.
|
||||
* I'm not sure why, must be a coinscidence.
|
||||
*/
|
||||
public class ExpansionDownloader {
|
||||
|
||||
//the plugin to run bukkit tasks as
|
||||
private JavaPlugin plugin;
|
||||
|
||||
/**
|
||||
* Constructs new instance of the class with provided plugin instance
|
||||
* @param plugin - plugin to run bukkit tasks as
|
||||
*/
|
||||
public ExpansionDownloader(JavaPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to download all included expansions using /papi ecloud download <expansion> command and if something was successful /papi reload
|
||||
* @param expansions - list of expansions to attempt to download
|
||||
*/
|
||||
public void download(Set<String> expansions) {
|
||||
//starting the task in the first tick just like PlaceholderAPI does to prevent downloading before PlaceholderAPI loads all expansions
|
||||
Bukkit.getScheduler().runTaskLater(plugin, new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
//starting the task asynchronously to not freeze the server with Thread.sleep
|
||||
new Thread(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
//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());
|
||||
TAB.getInstance().debug("Expansions to install: " + expansions.toString());
|
||||
if (!expansions.isEmpty()) {
|
||||
File expansionsFolder = new File(Bukkit.getPluginManager().getPlugin("PlaceholderAPI").getDataFolder(), "expansions");
|
||||
int oldExpansionDownloadedCount = expansionsFolder.listFiles().length;
|
||||
for (String expansion : expansions) {
|
||||
Bukkit.getConsoleSender().sendMessage("\u00a7d[TAB] Expansion \u00a7e" + expansion + "\u00a7d is used but not installed. Installing!");
|
||||
runSyncCommand("papi ecloud download " + expansion);
|
||||
Thread.sleep(5000);
|
||||
}
|
||||
if (expansionsFolder.listFiles().length > oldExpansionDownloadedCount) {
|
||||
Bukkit.getConsoleSender().sendMessage("\u00a7d[TAB] Reloading PlaceholderAPI for the changes to take effect.");
|
||||
runSyncCommand("papi reload");
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException | ConcurrentModificationException e) {
|
||||
//fast shutdown probably
|
||||
} catch (NoClassDefFoundError e){
|
||||
//PAPI class not found, fast shutdown probably
|
||||
} catch (Throwable e) {
|
||||
TAB.getInstance().getErrorManager().printError("Failed to download PlaceholderAPI expansions. PlaceholderAPI version: " + Bukkit.getPluginManager().getPlugin("PlaceholderAPI").getDescription().getVersion(), e);
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs given command in the main thread
|
||||
* @param command - command to perform
|
||||
*/
|
||||
private void runSyncCommand(String command) {
|
||||
//back to main thread as commands need to be ran in it
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command);
|
||||
} catch (Exception e) {
|
||||
//papi ecloud is disabled
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+14
-11
@@ -3,6 +3,7 @@ package me.neznamy.tab.platforms.bukkit.features;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -39,12 +40,14 @@ public class PerWorldPlayerlist implements Loadable, Listener {
|
||||
*/
|
||||
public PerWorldPlayerlist(JavaPlugin plugin, TAB tab) {
|
||||
this.plugin = plugin;
|
||||
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");
|
||||
for (String group : sharedWorlds.keySet()) {
|
||||
if (sharedWorlds.get(group).size() == 1) {
|
||||
tab.getErrorManager().startupWarn("World group \"" + group + "\" in per-world-playerlist only contain a single world (\"" + sharedWorlds.get(group).get(0) +
|
||||
allowBypass = tab.getConfiguration().getConfig().getBoolean("per-world-playerlist.allow-bypass-permission", false);
|
||||
ignoredWorlds = tab.getConfiguration().getConfig().getStringList("per-world-playerlist.ignore-effect-in-worlds", Arrays.asList("ignoredworld", "build"));
|
||||
sharedWorlds = tab.getConfiguration().getConfig().getConfigurationSection("per-world-playerlist.shared-playerlist-world-groups");
|
||||
for (Entry<String, List<String>> group : sharedWorlds.entrySet()) {
|
||||
if (group.getValue() == null) {
|
||||
tab.getErrorManager().startupWarn("World group \"" + group + "\" in per-world-playerlist does not contain any worlds. You can just remove the group.");
|
||||
} else if (group.getValue().size() == 1) {
|
||||
tab.getErrorManager().startupWarn("World group \"" + group + "\" in per-world-playerlist only contain a single world (\"" + group.getValue().get(0) +
|
||||
"\"), which has no effect and only makes config less readable. Delete the group entirely for a cleaner config.");
|
||||
}
|
||||
}
|
||||
@@ -54,7 +57,7 @@ public class PerWorldPlayerlist implements Loadable, Listener {
|
||||
|
||||
@Override
|
||||
public void load(){
|
||||
Bukkit.getScheduler().runTask(plugin, () -> Bukkit.getOnlinePlayers().forEach(p -> checkPlayer(p)));
|
||||
Bukkit.getScheduler().runTask(plugin, () -> Bukkit.getOnlinePlayers().forEach(this::checkPlayer));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -96,10 +99,10 @@ public class PerWorldPlayerlist implements Loadable, Listener {
|
||||
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(viewer.getWorld().getName())) viewerWorldGroup = group;
|
||||
if (sharedWorlds.get(group).contains(target.getWorld().getName())) targetWorldGroup = group;
|
||||
for (Entry<String, List<String>> group : sharedWorlds.entrySet()) {
|
||||
if (group.getValue() != null) {
|
||||
if (group.getValue().contains(viewer.getWorld().getName())) viewerWorldGroup = group.getKey();
|
||||
if (group.getValue().contains(target.getWorld().getName())) targetWorldGroup = group.getKey();
|
||||
}
|
||||
}
|
||||
return viewerWorldGroup.equals(targetWorldGroup);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package me.neznamy.tab.platforms.bukkit.features;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -22,10 +23,10 @@ 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;
|
||||
private int petOwnerPosition;
|
||||
|
||||
//logger of last interacts to prevent feature not working on 1.16
|
||||
private Map<String, Long> lastInteractFix = new HashMap<String, Long>();
|
||||
private Map<String, Long> lastInteractFix = new HashMap<>();
|
||||
|
||||
//nms storage
|
||||
private NMSStorage nms;
|
||||
@@ -36,7 +37,7 @@ public class PetFix implements RawPacketListener, QuitEventListener {
|
||||
*/
|
||||
public PetFix(NMSStorage nms) {
|
||||
this.nms = nms;
|
||||
PET_OWNER_POSITION = getPetOwnerPosition();
|
||||
petOwnerPosition = getPetOwnerPosition();
|
||||
TAB.getInstance().debug("Loaded PetFix feature");
|
||||
}
|
||||
|
||||
@@ -45,16 +46,16 @@ public class PetFix implements RawPacketListener, QuitEventListener {
|
||||
* @return position of pet owner field based on server version
|
||||
*/
|
||||
private int getPetOwnerPosition() {
|
||||
if (nms.minorVersion >= 17) {
|
||||
if (nms.getMinorVersion() >= 17) {
|
||||
//1.17.x
|
||||
return 18;
|
||||
} else if (nms.minorVersion >= 15) {
|
||||
} else if (nms.getMinorVersion() >= 15) {
|
||||
//1.15.x, 1.16.x
|
||||
return 17;
|
||||
} else if (nms.minorVersion >= 14) {
|
||||
} else if (nms.getMinorVersion() >= 14) {
|
||||
//1.14.x
|
||||
return 16;
|
||||
} else if (nms.minorVersion >= 10) {
|
||||
} else if (nms.getMinorVersion() >= 10) {
|
||||
//1.10.x - 1.13.x
|
||||
return 14;
|
||||
} else {
|
||||
@@ -65,15 +66,16 @@ public class PetFix implements RawPacketListener, QuitEventListener {
|
||||
|
||||
/**
|
||||
* Cancels a packet if previous one arrived with no delay to prevent double toggle on 1.16
|
||||
* @throws IllegalAccessException
|
||||
*/
|
||||
@Override
|
||||
public Object onPacketReceive(TabPlayer sender, Object packet) throws Throwable {
|
||||
if (nms.PacketPlayInUseEntity.isInstance(packet)) {
|
||||
public Object onPacketReceive(TabPlayer sender, Object packet) throws IllegalAccessException {
|
||||
if (nms.getClass("PacketPlayInUseEntity").isInstance(packet)) {
|
||||
if (lastInteractFix.containsKey(sender.getName()) && (System.currentTimeMillis() - lastInteractFix.get(sender.getName()) < 5)) {
|
||||
//last interact packet was sent right now, cancelling to prevent double-toggle due to this feature enabled
|
||||
return null;
|
||||
}
|
||||
if (nms.PacketPlayInUseEntity_ACTION.get(packet).toString().equals("INTERACT")) {
|
||||
if (isInteract(nms.getField("PacketPlayInUseEntity_ACTION").get(packet))) {
|
||||
//this is the first packet, saving player so the next packet can be cancelled
|
||||
lastInteractFix.put(sender.getName(), System.currentTimeMillis());
|
||||
}
|
||||
@@ -81,32 +83,48 @@ public class PetFix implements RawPacketListener, QuitEventListener {
|
||||
return packet;
|
||||
}
|
||||
|
||||
private boolean isInteract(Object action) {
|
||||
if (nms.getMinorVersion() >= 17) {
|
||||
return nms.getClass("PacketPlayInUseEntity$d").isInstance(action);
|
||||
} else {
|
||||
return action.toString().equals("INTERACT");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes pet owner field from datawatcher
|
||||
* @throws IllegalAccessException
|
||||
* @throws SecurityException
|
||||
* @throws NoSuchMethodException
|
||||
* @throws InvocationTargetException
|
||||
* @throws InstantiationException
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void onPacketSend(TabPlayer receiver, Object packet) throws Throwable {
|
||||
if (nms.PacketPlayOutEntityMetadata.isInstance(packet)) {
|
||||
List<Object> items = (List<Object>) nms.PacketPlayOutEntityMetadata_LIST.get(packet);
|
||||
public void onPacketSend(TabPlayer receiver, Object packet) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException, SecurityException, InstantiationException {
|
||||
if (nms.getClass("PacketPlayOutEntityMetadata").isInstance(packet)) {
|
||||
Object removedEntry = null;
|
||||
List<Object> items = (List<Object>) nms.getField("PacketPlayOutEntityMetadata_LIST").get(packet);
|
||||
if (items == null) return;
|
||||
List<Object> newList = new ArrayList<Object>();
|
||||
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.getClass().getSimpleName().equals("Optional")) continue;
|
||||
if (nms.getField("DataWatcherObject_SLOT").getInt(nms.getField("DataWatcherItem_TYPE").get(item)) == petOwnerPosition) {
|
||||
Object value = nms.getField("DataWatcherItem_VALUE").get(item);
|
||||
if (value instanceof java.util.Optional || value instanceof com.google.common.base.Optional) {
|
||||
removedEntry = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
newList.add(item);
|
||||
}
|
||||
nms.PacketPlayOutEntityMetadata_LIST.set(packet, newList);
|
||||
if (removedEntry != null) items.remove(removedEntry);
|
||||
}
|
||||
//<1.15
|
||||
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.getClass().getSimpleName().equals("Optional")) {
|
||||
watcher.removeValue(PET_OWNER_POSITION);
|
||||
nms.PacketPlayOutSpawnEntityLiving_DATAWATCHER.set(packet, watcher.toNMS());
|
||||
Field datawatcher = nms.getField("PacketPlayOutSpawnEntityLiving_DATAWATCHER");
|
||||
if (nms.getClass("PacketPlayOutSpawnEntityLiving").isInstance(packet) && datawatcher != null) {
|
||||
DataWatcher watcher = DataWatcher.fromNMS(datawatcher.get(packet));
|
||||
DataWatcherItem petOwner = watcher.getItem(petOwnerPosition);
|
||||
if (petOwner != null && (petOwner.getValue() instanceof java.util.Optional || petOwner.getValue() instanceof com.google.common.base.Optional)) {
|
||||
watcher.removeValue(petOwnerPosition);
|
||||
nms.setField(packet, "PacketPlayOutSpawnEntityLiving_DATAWATCHER", watcher.toNMS());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ public class TabExpansion extends PlaceholderExpansion {
|
||||
private String findReplacement(String placeholder, Player player) {
|
||||
if (!TAB.getInstance().isPremium()) return "Placeholder output replacements require premium version to work";
|
||||
String output = ((BukkitPlatform) TAB.getInstance().getPlatform()).setPlaceholders(player, placeholder);
|
||||
Map<Object, String> replacements = TAB.getInstance().getConfiguration().premiumconfig.getConfigurationSection("placeholder-output-replacements." + placeholder);
|
||||
Map<Object, String> replacements = TAB.getInstance().getConfiguration().getPremiumConfig().getConfigurationSection("placeholder-output-replacements." + placeholder);
|
||||
return Placeholder.findReplacement(replacements, output).replace("%value%", output);
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -20,10 +20,10 @@ import me.neznamy.tab.shared.features.types.Loadable;
|
||||
/**
|
||||
* An additional class with additional code for <1.9 servers due to an entity being required
|
||||
*/
|
||||
public class BossBar_legacy implements Listener, Loadable {
|
||||
public class WitherBossBar implements Listener, Loadable {
|
||||
|
||||
//distance of wither in blocks
|
||||
private final int WITHER_DISTANCE = 75;
|
||||
private static final int WITHER_DISTANCE = 75;
|
||||
|
||||
//main bossbar feature
|
||||
private BossBar mainFeature;
|
||||
@@ -32,11 +32,11 @@ public class BossBar_legacy implements Listener, Loadable {
|
||||
* Constructs a new instance of the class
|
||||
* @param mainFeature - main bossbar feature
|
||||
*/
|
||||
public BossBar_legacy(TAB tab, JavaPlugin plugin) {
|
||||
public WitherBossBar(TAB tab, JavaPlugin plugin) {
|
||||
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, () -> teleport());
|
||||
tab.getCPUManager().startRepeatingMeasuredTask(900, "refreshing bossbar", TabFeature.BOSSBAR, UsageType.TELEPORTING_ENTITY, this::teleport);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -52,7 +52,7 @@ public class BossBar_legacy implements Listener, Loadable {
|
||||
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.getInstance().getPacketBuilder()).buildEntityTeleportPacket(Math.abs(l.getUniqueId().hashCode()), getWitherLocation(all)), TabFeature.BOSSBAR);
|
||||
all.sendPacket(((BukkitPacketBuilder)TAB.getInstance().getPacketBuilder()).buildEntityTeleportPacket(l.getUniqueId().hashCode(), getWitherLocation(all)), TabFeature.BOSSBAR);
|
||||
} catch (Exception e) {
|
||||
TAB.getInstance().getErrorManager().printError("Failed to create PacketPlayOutEntityTeleport", e);
|
||||
}
|
||||
+32
-32
@@ -17,9 +17,9 @@ import me.neznamy.tab.api.ArmorStand;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitPacketBuilder;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.NMSStorage;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcher;
|
||||
import me.neznamy.tab.shared.Property;
|
||||
import me.neznamy.tab.shared.ProtocolVersion;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.cpu.TabFeature;
|
||||
import me.neznamy.tab.shared.cpu.UsageType;
|
||||
@@ -70,14 +70,14 @@ public class BukkitArmorStand implements ArmorStand {
|
||||
* @param yOffset - offset in blocks
|
||||
* @param staticOffset - if offset is static or not
|
||||
*/
|
||||
public BukkitArmorStand(int entityId, TabPlayer owner, Property property, double yOffset, boolean staticOffset) {
|
||||
public BukkitArmorStand(int entityId, TabPlayer owner, Property property, double yOffset, boolean staticOffset, boolean markerFor18x) {
|
||||
this.entityId = entityId;
|
||||
this.owner = owner;
|
||||
this.staticOffset = staticOffset;
|
||||
player = (Player) owner.getPlayer();
|
||||
this.yOffset = yOffset;
|
||||
this.property = property;
|
||||
markerFor18x = ((NameTagX)TAB.getInstance().getFeatureManager().getFeature("nametagx")).markerFor18x;
|
||||
this.markerFor18x = markerFor18x;
|
||||
visible = getVisibility();
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ public class BukkitArmorStand implements ArmorStand {
|
||||
visible = getVisibility();
|
||||
nearbyPlayers.add(viewer);
|
||||
DataWatcher dataWatcher = createDataWatcher(property.getFormat(viewer), viewer);
|
||||
if (ProtocolVersion.SERVER_VERSION.getMinorVersion() >= 15) {
|
||||
if (NMSStorage.getInstance().getMinorVersion() >= 15) {
|
||||
return new Object[] {
|
||||
getSpawnPacket(getArmorStandLocationFor(viewer), null),
|
||||
getMetadataPacket(dataWatcher)
|
||||
@@ -145,7 +145,7 @@ public class BukkitArmorStand implements ArmorStand {
|
||||
* @param viewer - player to get location for
|
||||
* @return location of armor stand
|
||||
*/
|
||||
private Location getArmorStandLocationFor(TabPlayer viewer) {
|
||||
protected Location getArmorStandLocationFor(TabPlayer viewer) {
|
||||
return viewer.getVersion().getMinorVersion() == 8 && !markerFor18x ? getLocation().clone().add(0,-2,0) : getLocation();
|
||||
}
|
||||
|
||||
@@ -172,7 +172,7 @@ public class BukkitArmorStand implements ArmorStand {
|
||||
if (this.sneaking == sneaking) return; //idk
|
||||
this.sneaking = sneaking;
|
||||
for (TabPlayer viewer : getNearbyPlayers()) {
|
||||
if (viewer.getVersion().getMinorVersion() == 14 && !TAB.getInstance().getConfiguration().armorStandsAlwaysVisible) {
|
||||
if (viewer.getVersion().getMinorVersion() == 14 && !TAB.getInstance().getConfiguration().isArmorStandsAlwaysVisible()) {
|
||||
//1.14.x client sided bug, despawning completely
|
||||
if (sneaking) {
|
||||
viewer.sendPacket(getDestroyPacket(), TabFeature.NAMETAGX);
|
||||
@@ -185,7 +185,7 @@ public class BukkitArmorStand implements ArmorStand {
|
||||
Runnable spawn = () -> spawn(viewer);
|
||||
if (viewer.getVersion().getMinorVersion() == 8) {
|
||||
//1.8.0 client sided bug
|
||||
TAB.getInstance().getCPUManager().runTaskLater(50, "compensating for 1.8.0 bugs", TabFeature.NAMETAGX, UsageType.v1_8_0_BUG_COMPENSATION, spawn);
|
||||
TAB.getInstance().getCPUManager().runTaskLater(50, "compensating for 1.8.0 bugs", TabFeature.NAMETAGX, UsageType.V1_8_0_BUG_COMPENSATION, spawn);
|
||||
} else {
|
||||
spawn.run();
|
||||
}
|
||||
@@ -201,9 +201,9 @@ public class BukkitArmorStand implements ArmorStand {
|
||||
|
||||
@Override
|
||||
public void updateVisibility(boolean force) {
|
||||
boolean visible = getVisibility();
|
||||
if (this.visible != visible || force) {
|
||||
this.visible = visible;
|
||||
boolean visibility = getVisibility();
|
||||
if (visible != visibility || force) {
|
||||
visible = visibility;
|
||||
updateMetadata();
|
||||
}
|
||||
}
|
||||
@@ -214,7 +214,7 @@ public class BukkitArmorStand implements ArmorStand {
|
||||
* @param viewer - player to get location for
|
||||
* @return teleport packet
|
||||
*/
|
||||
private Object getTeleportPacket(TabPlayer viewer) {
|
||||
protected Object getTeleportPacket(TabPlayer viewer) {
|
||||
try {
|
||||
return ((BukkitPacketBuilder)TAB.getInstance().getPacketBuilder()).buildEntityTeleportPacket(entityId, getArmorStandLocationFor(viewer));
|
||||
} catch (Exception e) {
|
||||
@@ -226,7 +226,7 @@ public class BukkitArmorStand implements ArmorStand {
|
||||
* Returns destroy packet
|
||||
* @return destroy packet
|
||||
*/
|
||||
private Object getDestroyPacket() {
|
||||
protected Object getDestroyPacket() {
|
||||
try {
|
||||
return ((BukkitPacketBuilder)TAB.getInstance().getPacketBuilder()).buildEntityDestroyPacket(entityId);
|
||||
} catch (Exception e) {
|
||||
@@ -239,7 +239,7 @@ public class BukkitArmorStand implements ArmorStand {
|
||||
* @param dataWatcher - datawatcher
|
||||
* @return metadata packet
|
||||
*/
|
||||
private Object getMetadataPacket(DataWatcher dataWatcher) {
|
||||
protected Object getMetadataPacket(DataWatcher dataWatcher) {
|
||||
try {
|
||||
return ((BukkitPacketBuilder)TAB.getInstance().getPacketBuilder()).buildEntityMetadataPacket(entityId, dataWatcher);
|
||||
} catch (Exception e) {
|
||||
@@ -253,7 +253,7 @@ public class BukkitArmorStand implements ArmorStand {
|
||||
* @param dataWatcher - datawatcher
|
||||
* @return spawn packet
|
||||
*/
|
||||
private Object getSpawnPacket(Location loc, DataWatcher dataWatcher) {
|
||||
protected Object getSpawnPacket(Location loc, DataWatcher dataWatcher) {
|
||||
try {
|
||||
return ((BukkitPacketBuilder)TAB.getInstance().getPacketBuilder()).buildEntitySpawnPacket(entityId, uuid, EntityType.ARMOR_STAND, loc, dataWatcher);
|
||||
} catch (Exception e) {
|
||||
@@ -264,7 +264,7 @@ public class BukkitArmorStand implements ArmorStand {
|
||||
/**
|
||||
* Updates armor stand's metadata
|
||||
*/
|
||||
private void updateMetadata() {
|
||||
protected void updateMetadata() {
|
||||
for (TabPlayer viewer : getNearbyPlayers()) {
|
||||
viewer.sendPacket(getMetadataPacket(createDataWatcher(property.getFormat(viewer), viewer)), TabFeature.NAMETAGX);
|
||||
}
|
||||
@@ -274,9 +274,9 @@ public class BukkitArmorStand implements ArmorStand {
|
||||
* Returns general visibility rule for everyone with limited info
|
||||
* @return true if should be visible, false if not
|
||||
*/
|
||||
private boolean getVisibility() {
|
||||
if (((BukkitTabPlayer)owner).isDisguised() || (((NameTagX)TAB.getInstance().getFeatureManager().getFeature("nametagx")).playersOnBoats.contains(owner))) return false;
|
||||
if (TAB.getInstance().getConfiguration().armorStandsAlwaysVisible) return true;
|
||||
protected boolean getVisibility() {
|
||||
if (((BukkitTabPlayer)owner).isDisguised() || (((NameTagX)TAB.getInstance().getFeatureManager().getFeature("nametagx")).getPlayersOnBoats().contains(owner))) return false;
|
||||
if (TAB.getInstance().getConfiguration().isArmorStandsAlwaysVisible()) return true;
|
||||
return !player.hasPotionEffect(PotionEffectType.INVISIBILITY) && player.getGameMode() != GameMode.SPECTATOR && !owner.hasHiddenNametag() && property.get().length() > 0;
|
||||
}
|
||||
|
||||
@@ -284,14 +284,14 @@ public class BukkitArmorStand implements ArmorStand {
|
||||
* Returns general location where armor stand should be at time of calling
|
||||
* @return Location where armor stand should be for everyone
|
||||
*/
|
||||
private Location getLocation() {
|
||||
protected Location getLocation() {
|
||||
double x = player.getLocation().getX();
|
||||
double y = getY() + yOffset + 2;
|
||||
double z = player.getLocation().getZ();
|
||||
if (player.isSleeping()) {
|
||||
y -= 1.76;
|
||||
} else {
|
||||
if (ProtocolVersion.SERVER_VERSION.getMinorVersion() >= 9) {
|
||||
if (NMSStorage.getInstance().getMinorVersion() >= 9) {
|
||||
y -= (sneaking ? 0.45 : 0.18);
|
||||
} else {
|
||||
y -= (sneaking ? 0.30 : 0.18);
|
||||
@@ -304,33 +304,33 @@ public class BukkitArmorStand implements ArmorStand {
|
||||
* Returns Y where player is based on player's vehicle due to bukkit API bug
|
||||
* @return correct player's Y
|
||||
*/
|
||||
private double getY() {
|
||||
protected double getY() {
|
||||
//1.14+ server sided bug
|
||||
Entity vehicle = player.getVehicle();
|
||||
if (vehicle != null) {
|
||||
if (vehicle.getType().toString().contains("HORSE")) { //covering all 3 horse types
|
||||
return vehicle.getLocation().getY() + 0.85;
|
||||
}
|
||||
if (vehicle.getType() == EntityType.DONKEY) {
|
||||
if (vehicle.getType().toString().equals("DONKEY")) { //1.11+
|
||||
return vehicle.getLocation().getY() + 0.525;
|
||||
}
|
||||
if (vehicle.getType() == EntityType.PIG) {
|
||||
return vehicle.getLocation().getY() + 0.325;
|
||||
}
|
||||
if (vehicle.getType().toString().equals("STRIDER")) { //added in 1.16
|
||||
if (vehicle.getType().toString().equals("STRIDER")) { //1.16+
|
||||
return vehicle.getLocation().getY() + 1.15;
|
||||
}
|
||||
}
|
||||
//1.13+ swimming or 1.9+ flying with elytra
|
||||
if (isSwimming() || (ProtocolVersion.SERVER_VERSION.getMinorVersion() >= 9 && player.isGliding())) {
|
||||
if (isSwimming() || (NMSStorage.getInstance().getMinorVersion() >= 9 && player.isGliding())) {
|
||||
return player.getLocation().getY()-1.22;
|
||||
}
|
||||
return player.getLocation().getY();
|
||||
}
|
||||
|
||||
private boolean isSwimming() {
|
||||
if (ProtocolVersion.SERVER_VERSION.getMinorVersion() >= 14 && player.getPose() == Pose.SWIMMING) return true;
|
||||
return ProtocolVersion.SERVER_VERSION.getMinorVersion() == 13 && player.isSwimming();
|
||||
if (NMSStorage.getInstance().getMinorVersion() >= 14 && player.getPose() == Pose.SWIMMING) return true;
|
||||
return NMSStorage.getInstance().getMinorVersion() == 13 && player.isSwimming();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -349,7 +349,7 @@ public class BukkitArmorStand implements ArmorStand {
|
||||
* @param viewer - player to apply checks against
|
||||
* @return datawatcher for viewer
|
||||
*/
|
||||
private DataWatcher createDataWatcher(String displayName, TabPlayer viewer) {
|
||||
protected DataWatcher createDataWatcher(String displayName, TabPlayer viewer) {
|
||||
DataWatcher datawatcher = new DataWatcher();
|
||||
|
||||
byte flag = 32; //invisible
|
||||
@@ -357,13 +357,13 @@ public class BukkitArmorStand implements ArmorStand {
|
||||
datawatcher.helper().setEntityFlags(flag);
|
||||
datawatcher.helper().setCustomName(displayName, viewer.getVersion());
|
||||
|
||||
boolean visible;
|
||||
boolean visibility;
|
||||
if (isNameVisiblyEmpty(displayName) || !((Player) viewer.getPlayer()).canSee(player) || owner.hasHiddenNametag(viewer.getUniqueId())) {
|
||||
visible = false;
|
||||
visibility = false;
|
||||
} else {
|
||||
visible = this.visible;
|
||||
visibility = visible;
|
||||
}
|
||||
datawatcher.helper().setCustomNameVisible(visible);
|
||||
datawatcher.helper().setCustomNameVisible(visibility);
|
||||
|
||||
if (viewer.getVersion().getMinorVersion() > 8 || markerFor18x) datawatcher.helper().setArmorStandFlags((byte)16);
|
||||
return datawatcher;
|
||||
@@ -372,7 +372,7 @@ public class BukkitArmorStand implements ArmorStand {
|
||||
@Override
|
||||
public Set<TabPlayer> getNearbyPlayers(){
|
||||
synchronized (nearbyPlayers) {
|
||||
return new HashSet<TabPlayer>(nearbyPlayers);
|
||||
return new HashSet<>(nearbyPlayers);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -34,7 +34,7 @@ public class EventListener implements Listener {
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void onSneak(PlayerToggleSneakEvent e) {
|
||||
TabPlayer p = TAB.getInstance().getPlayer(e.getPlayer().getUniqueId());
|
||||
if (p == null || !p.isLoaded() || feature.isDisabledWorld(p.getWorldName()) || feature.isDisabledWorld(feature.disabledUnlimitedWorlds, p.getWorldName())) return;
|
||||
if (p == null || !p.isLoaded() || feature.isInDisabledWorld(p)) return;
|
||||
TAB.getInstance().getCPUManager().runMeasuredTask("processing PlayerToggleSneakEvent", TabFeature.NAMETAGX, UsageType.PLAYER_TOGGLE_SNEAK_EVENT, () -> {
|
||||
if (p.getArmorStandManager() != null) p.getArmorStandManager().sneak(e.isSneaking());
|
||||
});
|
||||
@@ -48,7 +48,7 @@ public class EventListener implements Listener {
|
||||
public void onRespawn(PlayerRespawnEvent e) {
|
||||
TAB.getInstance().getCPUManager().runMeasuredTask("processing PlayerRespawnEvent", TabFeature.NAMETAGX, UsageType.PLAYER_RESPAWN_EVENT, () -> {
|
||||
TabPlayer respawned = TAB.getInstance().getPlayer(e.getPlayer().getUniqueId());
|
||||
if (feature.isDisabledWorld(respawned.getWorldName()) || feature.isDisabledWorld(feature.disabledUnlimitedWorlds, respawned.getWorldName())) return;
|
||||
if (feature.isInDisabledWorld(respawned)) return;
|
||||
respawned.getArmorStandManager().teleport();
|
||||
});
|
||||
}
|
||||
|
||||
+111
-75
@@ -23,7 +23,7 @@ import me.neznamy.tab.api.ArmorStandManager;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.NMSStorage;
|
||||
import me.neznamy.tab.shared.Property;
|
||||
import me.neznamy.tab.shared.ProtocolVersion;
|
||||
import me.neznamy.tab.shared.PropertyUtils;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.cpu.TabFeature;
|
||||
import me.neznamy.tab.shared.cpu.UsageType;
|
||||
@@ -35,38 +35,40 @@ import me.neznamy.tab.shared.features.NameTag;
|
||||
public class NameTagX extends NameTag {
|
||||
|
||||
//config options
|
||||
public boolean markerFor18x;
|
||||
public boolean disableOnBoats;
|
||||
private boolean markerFor18x;
|
||||
private boolean disableOnBoats;
|
||||
private double spaceBetweenLines;
|
||||
|
||||
//list of worlds with unlimited nametag mode disabled
|
||||
protected List<String> disabledUnlimitedWorlds;
|
||||
|
||||
//list of defined dynamic lines
|
||||
public List<String> dynamicLines = Arrays.asList("belowname", "nametag", "abovename");
|
||||
private List<String> dynamicLines = Arrays.asList(PropertyUtils.BELOWNAME, PropertyUtils.NAMETAG, PropertyUtils.ABOVENAME);
|
||||
|
||||
//map of defined static lines
|
||||
public Map<String, Object> staticLines = new ConcurrentHashMap<String, Object>();
|
||||
private Map<String, Object> staticLines = new ConcurrentHashMap<>();
|
||||
|
||||
//entity id counter to pick unique entity IDs
|
||||
private int idCounter = 2000000000;
|
||||
|
||||
//player data by entityId, used for better performance
|
||||
public Map<Integer, TabPlayer> entityIdMap = new ConcurrentHashMap<Integer, TabPlayer>();
|
||||
private Map<Integer, TabPlayer> entityIdMap = new ConcurrentHashMap<>();
|
||||
|
||||
//map of vehicles carrying players
|
||||
public Map<Integer, List<Entity>> vehicles = new ConcurrentHashMap<Integer, List<Entity>>();
|
||||
private Map<Integer, List<Entity>> vehicles = new ConcurrentHashMap<>();
|
||||
|
||||
//bukkit event listener
|
||||
private EventListener eventListener;
|
||||
|
||||
//list of players currently on boats
|
||||
public List<TabPlayer> playersOnBoats = new ArrayList<TabPlayer>();
|
||||
private List<TabPlayer> playersOnBoats = new ArrayList<>();
|
||||
|
||||
//list of players currently in a vehicle
|
||||
private Map<TabPlayer, Entity> playersInVehicle = new ConcurrentHashMap<TabPlayer, Entity>();
|
||||
private Map<TabPlayer, Entity> playersInVehicle = new ConcurrentHashMap<>();
|
||||
|
||||
private Map<TabPlayer, Location> playerLocations = new ConcurrentHashMap<TabPlayer, Location>();
|
||||
private Map<TabPlayer, Location> playerLocations = new ConcurrentHashMap<>();
|
||||
|
||||
private Set<TabPlayer> playersInDisabledUnlimitedWorlds = new HashSet<>();
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters and loads config options
|
||||
@@ -76,16 +78,16 @@ public class NameTagX extends NameTag {
|
||||
*/
|
||||
public NameTagX(JavaPlugin plugin, NMSStorage nms, TAB tab) {
|
||||
super(tab);
|
||||
markerFor18x = tab.getConfiguration().config.getBoolean("unlimited-nametag-prefix-suffix-mode.use-marker-tag-for-1-8-x-clients", false);
|
||||
disableOnBoats = tab.getConfiguration().config.getBoolean("unlimited-nametag-prefix-suffix-mode.disable-on-boats", true);
|
||||
spaceBetweenLines = tab.getConfiguration().config.getDouble("unlimited-nametag-prefix-suffix-mode.space-between-lines", 0.22);
|
||||
disabledUnlimitedWorlds = tab.getConfiguration().config.getStringList("disable-features-in-worlds.unlimited-nametags", Arrays.asList("disabledworld"));
|
||||
if (tab.getConfiguration().premiumconfig != null) {
|
||||
List<String> realList = tab.getConfiguration().premiumconfig.getStringList("unlimited-nametag-mode-dynamic-lines", Arrays.asList("abovename", "nametag", "belowname", "another"));
|
||||
dynamicLines = new ArrayList<String>();
|
||||
markerFor18x = tab.getConfiguration().getConfig().getBoolean("unlimited-nametag-prefix-suffix-mode.use-marker-tag-for-1-8-x-clients", false);
|
||||
disableOnBoats = tab.getConfiguration().getConfig().getBoolean("unlimited-nametag-prefix-suffix-mode.disable-on-boats", true);
|
||||
spaceBetweenLines = tab.getConfiguration().getConfig().getDouble("unlimited-nametag-prefix-suffix-mode.space-between-lines", 0.22);
|
||||
disabledUnlimitedWorlds = tab.getConfiguration().getConfig().getStringList("disable-features-in-worlds.unlimited-nametags", Arrays.asList("disabledworld"));
|
||||
if (tab.getConfiguration().getPremiumConfig() != null) {
|
||||
List<String> realList = tab.getConfiguration().getPremiumConfig().getStringList("unlimited-nametag-mode-dynamic-lines", Arrays.asList(PropertyUtils.ABOVENAME, PropertyUtils.NAMETAG, PropertyUtils.BELOWNAME, "another"));
|
||||
dynamicLines = new ArrayList<>();
|
||||
dynamicLines.addAll(realList);
|
||||
Collections.reverse(dynamicLines);
|
||||
staticLines = tab.getConfiguration().premiumconfig.getConfigurationSection("unlimited-nametag-mode-static-lines");
|
||||
staticLines = tab.getConfiguration().getPremiumConfig().getConfigurationSection("unlimited-nametag-mode-static-lines");
|
||||
}
|
||||
refreshUsedPlaceholders();
|
||||
eventListener = new EventListener(this);
|
||||
@@ -99,9 +101,12 @@ public class NameTagX extends NameTag {
|
||||
public void load() {
|
||||
super.load();
|
||||
for (TabPlayer all : tab.getPlayers()) {
|
||||
entityIdMap.put(((Player) all.getPlayer()).getEntityId(), all);
|
||||
getEntityIdMap().put(((Player) all.getPlayer()).getEntityId(), all);
|
||||
loadArmorStands(all);
|
||||
if (isDisabledWorld(all.getWorldName()) || isDisabledWorld(disabledUnlimitedWorlds, all.getWorldName())) continue;
|
||||
if (isDisabledWorld(disabledUnlimitedWorlds, all.getWorldName())) {
|
||||
playersInDisabledUnlimitedWorlds.add(all);
|
||||
}
|
||||
if (isInDisabledWorld(all)) continue;
|
||||
loadPassengers(all);
|
||||
for (TabPlayer viewer : tab.getPlayers()) {
|
||||
spawnArmorStands(all, viewer, false);
|
||||
@@ -112,46 +117,49 @@ public class NameTagX extends NameTag {
|
||||
}
|
||||
|
||||
private void startVisibilityRefreshTask() {
|
||||
tab.getCPUManager().startRepeatingMeasuredTask(500, "refreshing nametag visibility", getFeatureType(), UsageType.REFRESHING_NAMETAG_VISIBILITY_AND_COLLISION, new Runnable() {
|
||||
public void run() {
|
||||
for (TabPlayer p : tab.getPlayers()) {
|
||||
if (!p.isLoaded() || isDisabledWorld(p.getWorldName()) || isDisabledWorld(disabledUnlimitedWorlds, p.getWorldName())) continue;
|
||||
p.getArmorStandManager().updateVisibility(false);
|
||||
if (!disableOnBoats) continue;
|
||||
boolean onBoat = ((Player)p.getPlayer()).getVehicle() != null && ((Player)p.getPlayer()).getVehicle().getType() == EntityType.BOAT;
|
||||
if (onBoat) {
|
||||
if (!playersOnBoats.contains(p)) {
|
||||
playersOnBoats.add(p);
|
||||
updateTeamData(p);
|
||||
}
|
||||
} else {
|
||||
if (playersOnBoats.contains(p)) {
|
||||
playersOnBoats.remove(p);
|
||||
updateTeamData(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
tab.getCPUManager().startRepeatingMeasuredTask(500, "refreshing nametag visibility", getFeatureType(), UsageType.REFRESHING_NAMETAG_VISIBILITY_AND_COLLISION, () -> {
|
||||
|
||||
for (TabPlayer p : tab.getPlayers()) {
|
||||
if (!p.isLoaded() || isInDisabledWorld(p)) continue;
|
||||
p.getArmorStandManager().updateVisibility(false);
|
||||
if (disableOnBoats) processBoats(p);
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void processBoats(TabPlayer p) {
|
||||
boolean onBoat = ((Player)p.getPlayer()).getVehicle() != null && ((Player)p.getPlayer()).getVehicle().getType() == EntityType.BOAT;
|
||||
if (onBoat) {
|
||||
if (!getPlayersOnBoats().contains(p)) {
|
||||
getPlayersOnBoats().add(p);
|
||||
updateTeamData(p);
|
||||
}
|
||||
} else {
|
||||
if (getPlayersOnBoats().contains(p)) {
|
||||
getPlayersOnBoats().remove(p);
|
||||
updateTeamData(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void startVehicleTickingTask() {
|
||||
tab.getCPUManager().startRepeatingMeasuredTask(100, "ticking vehicles", TabFeature.NAMETAGX, UsageType.TICKING_VEHICLES, () -> {
|
||||
|
||||
for (TabPlayer p : TAB.getInstance().getPlayers()) {
|
||||
if (!p.isLoaded()) continue;
|
||||
if (isDisabledWorld(p.getWorldName()) || isDisabledWorld(disabledUnlimitedWorlds, p.getWorldName())) {
|
||||
if (isInDisabledWorld(p)) {
|
||||
playersInVehicle.remove(p);
|
||||
playerLocations.remove(p);
|
||||
continue;
|
||||
}
|
||||
processVehicles(p);
|
||||
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);
|
||||
} else {
|
||||
processVehicles(p);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -166,13 +174,13 @@ public class NameTagX extends NameTag {
|
||||
Entity vehicle = ((Player)p.getPlayer()).getVehicle();
|
||||
if (playersInVehicle.containsKey(p) && vehicle == null) {
|
||||
//vehicle exit
|
||||
vehicles.remove(playersInVehicle.get(p).getEntityId());
|
||||
getVehicles().remove(playersInVehicle.get(p).getEntityId());
|
||||
p.getArmorStandManager().teleport();
|
||||
playersInVehicle.remove(p);
|
||||
}
|
||||
if (!playersInVehicle.containsKey(p) && vehicle != null) {
|
||||
//vehicle enter
|
||||
vehicles.put(vehicle.getEntityId(), getPassengers(vehicle));
|
||||
getVehicles().put(vehicle.getEntityId(), getPassengers(vehicle));
|
||||
p.getArmorStandManager().teleport();
|
||||
playersInVehicle.put(p, vehicle);
|
||||
}
|
||||
@@ -200,15 +208,19 @@ public class NameTagX extends NameTag {
|
||||
for (TabPlayer p : tab.getPlayers()) {
|
||||
if (p.getArmorStandManager() != null) p.getArmorStandManager().destroy();
|
||||
}
|
||||
entityIdMap.clear();
|
||||
getEntityIdMap().clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onJoin(TabPlayer connectedPlayer) {
|
||||
super.onJoin(connectedPlayer);
|
||||
entityIdMap.put(((Player) connectedPlayer.getPlayer()).getEntityId(), connectedPlayer);
|
||||
getEntityIdMap().put(((Player) connectedPlayer.getPlayer()).getEntityId(), connectedPlayer);
|
||||
loadArmorStands(connectedPlayer);
|
||||
if (isDisabledWorld(connectedPlayer.getWorldName()) || isDisabledWorld(disabledUnlimitedWorlds, connectedPlayer.getWorldName())) return;
|
||||
if (isDisabledWorld(disabledUnlimitedWorlds, connectedPlayer.getWorldName())) {
|
||||
playersInDisabledUnlimitedWorlds.add(connectedPlayer);
|
||||
return;
|
||||
}
|
||||
if (isInDisabledWorld(connectedPlayer)) return;
|
||||
loadPassengers(connectedPlayer);
|
||||
for (TabPlayer viewer : tab.getPlayers()) {
|
||||
spawnArmorStands(connectedPlayer, viewer, true);
|
||||
@@ -234,7 +246,7 @@ public class NameTagX extends NameTag {
|
||||
private void loadPassengers(TabPlayer p) {
|
||||
if (((Entity) p.getPlayer()).getVehicle() == null) return;
|
||||
Entity vehicle = ((Entity) p.getPlayer()).getVehicle();
|
||||
vehicles.put(vehicle.getEntityId(), getPassengers(vehicle));
|
||||
getVehicles().put(vehicle.getEntityId(), getPassengers(vehicle));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -243,15 +255,21 @@ public class NameTagX extends NameTag {
|
||||
for (TabPlayer all : tab.getPlayers()) {
|
||||
if (all.getArmorStandManager() != null) all.getArmorStandManager().unregisterPlayer(disconnectedPlayer);
|
||||
}
|
||||
entityIdMap.remove(((Player) disconnectedPlayer.getPlayer()).getEntityId());
|
||||
getEntityIdMap().remove(((Player) disconnectedPlayer.getPlayer()).getEntityId());
|
||||
playersInVehicle.remove(disconnectedPlayer);
|
||||
playerLocations.remove(disconnectedPlayer);
|
||||
playersInDisabledUnlimitedWorlds.remove(disconnectedPlayer);
|
||||
tab.getCPUManager().runTaskLater(100, "processing onQuit", getFeatureType(), UsageType.PLAYER_QUIT_EVENT, () -> disconnectedPlayer.getArmorStandManager().destroy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWorldChange(TabPlayer p, String from, String to) {
|
||||
super.onWorldChange(p, from, to);
|
||||
if (isDisabledWorld(disabledWorlds, p.getWorldName())) {
|
||||
playersInDisabledWorlds.add(p);
|
||||
} else {
|
||||
playersInDisabledWorlds.remove(p);
|
||||
}
|
||||
Set<TabPlayer> nearby = p.getArmorStandManager().getNearbyPlayers();
|
||||
p.getArmorStandManager().destroy();
|
||||
loadArmorStands(p);
|
||||
@@ -271,7 +289,7 @@ public class NameTagX extends NameTag {
|
||||
private void spawnArmorStands(TabPlayer owner, TabPlayer viewer, boolean sendMutually) {
|
||||
if (owner == viewer) return; //not displaying own armorstands
|
||||
if (((Player) viewer.getPlayer()).getWorld() != ((Player) owner.getPlayer()).getWorld()) return; //different world
|
||||
if (isDisabledWorld(owner.getWorldName()) || isDisabledWorld(disabledUnlimitedWorlds, owner.getWorldName())) return;
|
||||
if (isInDisabledWorld(owner)) return;
|
||||
if (getDistance(viewer, owner) <= 48) {
|
||||
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())
|
||||
@@ -285,17 +303,18 @@ public class NameTagX extends NameTag {
|
||||
*/
|
||||
public void loadArmorStands(TabPlayer pl) {
|
||||
pl.setArmorStandManager(new ArmorStandManager());
|
||||
pl.setProperty("nametag", pl.getProperty("tagprefix").getCurrentRawValue() + pl.getProperty("customtagname").getCurrentRawValue() + pl.getProperty("tagsuffix").getCurrentRawValue());
|
||||
double height = -spaceBetweenLines;
|
||||
pl.setProperty(PropertyUtils.NAMETAG, pl.getProperty(PropertyUtils.TAGPREFIX).getCurrentRawValue() + pl.getProperty(PropertyUtils.CUSTOMTAGNAME).getCurrentRawValue() + pl.getProperty(PropertyUtils.TAGSUFFIX).getCurrentRawValue());
|
||||
double height = 0;
|
||||
for (String line : dynamicLines) {
|
||||
Property p = pl.getProperty(line);
|
||||
if (p.getCurrentRawValue().length() == 0) continue;
|
||||
pl.getArmorStandManager().addArmorStand(line, new BukkitArmorStand(idCounter++, pl, p, height+=spaceBetweenLines, false));
|
||||
pl.getArmorStandManager().addArmorStand(line, new BukkitArmorStand(idCounter++, pl, p, height, false, markerFor18x));
|
||||
height += spaceBetweenLines;
|
||||
}
|
||||
for (Entry<String, Object> line : staticLines.entrySet()) {
|
||||
Property p = pl.getProperty(line.getKey());
|
||||
if (p.getCurrentRawValue().length() == 0) continue;
|
||||
pl.getArmorStandManager().addArmorStand(line.getKey(), new BukkitArmorStand(idCounter++, pl, p, Double.parseDouble(line.getValue().toString()), true));
|
||||
pl.getArmorStandManager().addArmorStand(line.getKey(), new BukkitArmorStand(idCounter++, pl, p, Double.parseDouble(line.getValue().toString()), true, markerFor18x));
|
||||
}
|
||||
fixArmorStandHeights(pl);
|
||||
}
|
||||
@@ -319,7 +338,7 @@ public class NameTagX extends NameTag {
|
||||
@Override
|
||||
public void refresh(TabPlayer refreshed, boolean force) {
|
||||
super.refresh(refreshed, force);
|
||||
if (isDisabledWorld(refreshed.getWorldName()) || isDisabledWorld(disabledUnlimitedWorlds, refreshed.getWorldName())) return;
|
||||
if (isInDisabledWorld(refreshed)) return;
|
||||
if (force) {
|
||||
refreshed.getArmorStandManager().destroy();
|
||||
loadArmorStands(refreshed);
|
||||
@@ -346,15 +365,16 @@ public class NameTagX extends NameTag {
|
||||
* Updates raw values of properties for specified player
|
||||
* @param p - player to update
|
||||
*/
|
||||
@Override
|
||||
public void updateProperties(TabPlayer p) {
|
||||
super.updateProperties(p);
|
||||
p.loadPropertyFromConfig("customtagname", p.getName());
|
||||
p.setProperty("nametag", p.getProperty("tagprefix").getCurrentRawValue() + p.getProperty("customtagname").getCurrentRawValue() + p.getProperty("tagsuffix").getCurrentRawValue());
|
||||
p.loadPropertyFromConfig(PropertyUtils.CUSTOMTAGNAME, p.getName());
|
||||
p.setProperty(PropertyUtils.NAMETAG, p.getProperty(PropertyUtils.TAGPREFIX).getCurrentRawValue() + p.getProperty(PropertyUtils.CUSTOMTAGNAME).getCurrentRawValue() + p.getProperty(PropertyUtils.TAGSUFFIX).getCurrentRawValue());
|
||||
for (String property : dynamicLines) {
|
||||
if (!property.equals("nametag")) p.loadPropertyFromConfig(property);
|
||||
if (!property.equals(PropertyUtils.NAMETAG)) p.loadPropertyFromConfig(property);
|
||||
}
|
||||
for (String property : staticLines.keySet()) {
|
||||
if (!property.equals("nametag")) p.loadPropertyFromConfig(property);
|
||||
if (!property.equals(PropertyUtils.NAMETAG)) p.loadPropertyFromConfig(property);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,30 +385,30 @@ public class NameTagX extends NameTag {
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public List<Entity> getPassengers(Entity vehicle){
|
||||
if (ProtocolVersion.SERVER_VERSION.getMinorVersion() >= 11) {
|
||||
if (NMSStorage.getInstance().getMinorVersion() >= 11) {
|
||||
return vehicle.getPassengers();
|
||||
} else {
|
||||
if (vehicle.getPassenger() != null) {
|
||||
return Arrays.asList(vehicle.getPassenger());
|
||||
} else {
|
||||
return new ArrayList<Entity>();
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshUsedPlaceholders() {
|
||||
usedPlaceholders = new HashSet<>(tab.getConfiguration().config.getUsedPlaceholderIdentifiersRecursive("tagprefix", "customtagname", "tagsuffix"));
|
||||
usedPlaceholders = new HashSet<>(tab.getConfiguration().getConfig().getUsedPlaceholderIdentifiersRecursive(PropertyUtils.TAGPREFIX, PropertyUtils.CUSTOMTAGNAME, PropertyUtils.TAGSUFFIX));
|
||||
for (String line : dynamicLines) {
|
||||
usedPlaceholders.addAll(tab.getConfiguration().config.getUsedPlaceholderIdentifiersRecursive(line));
|
||||
usedPlaceholders.addAll(tab.getConfiguration().getConfig().getUsedPlaceholderIdentifiersRecursive(line));
|
||||
}
|
||||
for (String line : staticLines.keySet()) {
|
||||
usedPlaceholders.addAll(tab.getConfiguration().config.getUsedPlaceholderIdentifiersRecursive(line));
|
||||
usedPlaceholders.addAll(tab.getConfiguration().getConfig().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()));
|
||||
usedPlaceholders.addAll(tab.getPlaceholderManager().getUsedPlaceholderIdentifiersRecursive(p.getProperty(PropertyUtils.TAGPREFIX).getCurrentRawValue(),
|
||||
p.getProperty(PropertyUtils.CUSTOMTAGNAME).getCurrentRawValue(), p.getProperty(PropertyUtils.TAGSUFFIX).getCurrentRawValue(),
|
||||
p.getProperty(PropertyUtils.ABOVENAME).getCurrentRawValue(), p.getProperty(PropertyUtils.BELOWNAME).getCurrentRawValue()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -400,6 +420,22 @@ public class NameTagX extends NameTag {
|
||||
@Override
|
||||
public boolean getTeamVisibility(TabPlayer p, TabPlayer viewer) {
|
||||
//only visible if player is on boat & config option is enabled and player is not invisible (1.8 bug) or feature is disabled
|
||||
return (playersOnBoats.contains(p) && !invisiblePlayers.contains(p.getName())) || isDisabledWorld(disabledUnlimitedWorlds, p.getWorldName());
|
||||
return (getPlayersOnBoats().contains(p) && !invisiblePlayers.contains(p.getName())) || isInDisabledWorld(p);
|
||||
}
|
||||
|
||||
public Map<Integer, TabPlayer> getEntityIdMap() {
|
||||
return entityIdMap;
|
||||
}
|
||||
|
||||
public Map<Integer, List<Entity>> getVehicles() {
|
||||
return vehicles;
|
||||
}
|
||||
|
||||
public List<TabPlayer> getPlayersOnBoats() {
|
||||
return playersOnBoats;
|
||||
}
|
||||
|
||||
public boolean isInDisabledWorld(TabPlayer p) {
|
||||
return playersInDisabledWorlds.contains(p) || isDisabledWorld(disabledUnlimitedWorlds, p.getWorldName());
|
||||
}
|
||||
}
|
||||
+43
-31
@@ -40,46 +40,46 @@ public class PacketListener implements RawPacketListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object onPacketReceive(TabPlayer sender, Object packet) throws Throwable {
|
||||
if (sender.getVersion().getMinorVersion() == 8 && nms.PacketPlayInUseEntity.isInstance(packet)) {
|
||||
int entityId = nms.PacketPlayInUseEntity_ENTITY.getInt(packet);
|
||||
public Object onPacketReceive(TabPlayer sender, Object packet) throws IllegalAccessException {
|
||||
if (sender.getVersion().getMinorVersion() == 8 && nms.getClass("PacketPlayInUseEntity").isInstance(packet)) {
|
||||
int entityId = nms.getField("PacketPlayInUseEntity_ENTITY").getInt(packet);
|
||||
TabPlayer attacked = null;
|
||||
for (TabPlayer all : tab.getPlayers()) {
|
||||
if (!all.isLoaded()) continue;
|
||||
if (all.getArmorStandManager().hasArmorStandWithID(entityId)) {
|
||||
if (all.isLoaded() && all.getArmorStandManager().hasArmorStandWithID(entityId)) {
|
||||
attacked = all;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (attacked != null && attacked != sender) {
|
||||
nms.PacketPlayInUseEntity_ENTITY.set(packet, ((Player) attacked.getPlayer()).getEntityId());
|
||||
nms.setField(packet, "PacketPlayInUseEntity_ENTITY", ((Player) attacked.getPlayer()).getEntityId());
|
||||
}
|
||||
}
|
||||
return packet;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void onPacketSend(TabPlayer receiver, Object packet) throws Throwable {
|
||||
public void onPacketSend(TabPlayer receiver, Object packet) throws IllegalAccessException {
|
||||
if (receiver.getVersion().getMinorVersion() < 8) return;
|
||||
//using bukkit player to check world due to old data on world change due to asynchronous processing & world name changing
|
||||
String world = ((Player)receiver.getPlayer()).getWorld().getName();
|
||||
if (!receiver.isLoaded() || nameTagX.isDisabledWorld(world) || nameTagX.isDisabledWorld(nameTagX.disabledUnlimitedWorlds, world)) return;
|
||||
if (nms.PacketPlayOutEntity.isInstance(packet) && !nms.PacketPlayOutEntityLook.isInstance(packet)) { //ignoring head rotation only packets
|
||||
onEntityMove(receiver, nms.PacketPlayOutEntity_ENTITYID.getInt(packet));
|
||||
}
|
||||
if (nms.PacketPlayOutEntityTeleport.isInstance(packet)) {
|
||||
onEntityMove(receiver, nms.PacketPlayOutEntityTeleport_ENTITYID.getInt(packet));
|
||||
}
|
||||
if (nms.PacketPlayOutNamedEntitySpawn.isInstance(packet)) {
|
||||
onEntitySpawn(receiver, nms.PacketPlayOutNamedEntitySpawn_ENTITYID.getInt(packet));
|
||||
}
|
||||
if (nms.PacketPlayOutEntityDestroy.isInstance(packet)) {
|
||||
if (nms.minorVersion >= 17) {
|
||||
onEntityDestroy(receiver, nms.PacketPlayOutEntityDestroy_ENTITIES.getInt(packet));
|
||||
} else {
|
||||
for (int entity : (int[]) nms.PacketPlayOutEntityDestroy_ENTITIES.get(packet)) {
|
||||
onEntityDestroy(receiver, entity);
|
||||
if (!receiver.isLoaded() || nameTagX.getPlayersInDisabledWorlds().contains(receiver) || nameTagX.isDisabledWorld(nameTagX.disabledUnlimitedWorlds, world)) return;
|
||||
if (nms.getClass("PacketPlayOutEntity").isInstance(packet) && !nms.getClass("PacketPlayOutEntityLook").isInstance(packet)) { //ignoring head rotation only packets
|
||||
onEntityMove(receiver, nms.getField("PacketPlayOutEntity_ENTITYID").getInt(packet));
|
||||
} else if (nms.getClass("PacketPlayOutEntityTeleport").isInstance(packet)) {
|
||||
onEntityMove(receiver, nms.getField("PacketPlayOutEntityTeleport_ENTITYID").getInt(packet));
|
||||
} else if (nms.getClass("PacketPlayOutNamedEntitySpawn").isInstance(packet)) {
|
||||
onEntitySpawn(receiver, nms.getField("PacketPlayOutNamedEntitySpawn_ENTITYID").getInt(packet));
|
||||
} else if (nms.getClass("PacketPlayOutEntityDestroy").isInstance(packet)) {
|
||||
if (nms.getMinorVersion() >= 17) {
|
||||
try {
|
||||
onEntityDestroy(receiver, (List<Integer>) nms.getField("PacketPlayOutEntityDestroy_ENTITIES").get(packet));
|
||||
} catch (ClassCastException e) {
|
||||
//1.17.0
|
||||
onEntityDestroy(receiver, nms.getField("PacketPlayOutEntityDestroy_ENTITIES").getInt(packet));
|
||||
}
|
||||
} else {
|
||||
onEntityDestroy(receiver, (int[]) nms.getField("PacketPlayOutEntityDestroy_ENTITIES").get(packet));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -89,16 +89,16 @@ public class PacketListener implements RawPacketListener {
|
||||
* @param receiver - packet receiver
|
||||
* @param entityId - entity that moved
|
||||
*/
|
||||
public void onEntityMove(TabPlayer receiver, int entityId) {
|
||||
TabPlayer pl = nameTagX.entityIdMap.get(entityId);
|
||||
private void onEntityMove(TabPlayer receiver, int entityId) {
|
||||
TabPlayer pl = nameTagX.getEntityIdMap().get(entityId);
|
||||
List<Entity> vehicleList;
|
||||
if (pl != null) {
|
||||
//player moved
|
||||
tab.getCPUManager().runMeasuredTask("processing EntityMove", getFeatureType(), UsageType.PACKET_ENTITY_MOVE, () -> pl.getArmorStandManager().teleport(receiver));
|
||||
} else if ((vehicleList = nameTagX.vehicles.get(entityId)) != null){
|
||||
} else if ((vehicleList = nameTagX.getVehicles().get(entityId)) != null){
|
||||
//a vehicle carrying something moved
|
||||
for (Entity entity : vehicleList) {
|
||||
TabPlayer passenger = nameTagX.entityIdMap.get(entity.getEntityId());
|
||||
TabPlayer passenger = nameTagX.getEntityIdMap().get(entity.getEntityId());
|
||||
if (passenger != null && passenger.getArmorStandManager() != null) {
|
||||
tab.getCPUManager().runMeasuredTask("processing EntityMove", getFeatureType(), UsageType.PACKET_ENTITY_MOVE, () -> passenger.getArmorStandManager().teleport(receiver));
|
||||
}
|
||||
@@ -106,15 +106,27 @@ public class PacketListener implements RawPacketListener {
|
||||
}
|
||||
}
|
||||
|
||||
public void onEntitySpawn(TabPlayer receiver, int entityId) {
|
||||
TabPlayer spawnedPlayer = nameTagX.entityIdMap.get(entityId);
|
||||
private void onEntitySpawn(TabPlayer receiver, int entityId) {
|
||||
TabPlayer spawnedPlayer = nameTagX.getEntityIdMap().get(entityId);
|
||||
if (spawnedPlayer != null && spawnedPlayer.isLoaded()) {
|
||||
tab.getCPUManager().runMeasuredTask("processing NamedEntitySpawn", getFeatureType(), UsageType.PACKET_NAMED_ENTITY_SPAWN, () -> spawnedPlayer.getArmorStandManager().spawn(receiver));
|
||||
}
|
||||
}
|
||||
|
||||
public void onEntityDestroy(TabPlayer receiver, int entity) {
|
||||
TabPlayer despawnedPlayer = nameTagX.entityIdMap.get(entity);
|
||||
private void onEntityDestroy(TabPlayer receiver, List<Integer> entities) {
|
||||
for (int entity : entities) {
|
||||
onEntityDestroy(receiver, entity);
|
||||
}
|
||||
}
|
||||
|
||||
private void onEntityDestroy(TabPlayer receiver, int... entities) {
|
||||
for (int entity : entities) {
|
||||
onEntityDestroy(receiver, entity);
|
||||
}
|
||||
}
|
||||
|
||||
private void onEntityDestroy(TabPlayer receiver, int entity) {
|
||||
TabPlayer despawnedPlayer = nameTagX.getEntityIdMap().get(entity);
|
||||
if (despawnedPlayer != null && despawnedPlayer.isLoaded())
|
||||
tab.getCPUManager().runMeasuredTask("processing EntityDestroy", getFeatureType(), UsageType.PACKET_ENTITY_DESTROY, () -> despawnedPlayer.getArmorStandManager().destroy(receiver));
|
||||
}
|
||||
|
||||
@@ -3,11 +3,14 @@ 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.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
@@ -15,223 +18,69 @@ import org.bukkit.Bukkit;
|
||||
import io.netty.channel.Channel;
|
||||
import me.neznamy.tab.platforms.bukkit.Main;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcherRegistry;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@SuppressWarnings("rawtypes")
|
||||
public class NMSStorage {
|
||||
|
||||
//instance of this class
|
||||
private static NMSStorage instance;
|
||||
|
||||
//data watcher registry
|
||||
public DataWatcherRegistry dataWatcherRegistry;
|
||||
private DataWatcherRegistry dataWatcherRegistry;
|
||||
|
||||
//server package, such as "v1_16_R3"
|
||||
private String serverPackage;
|
||||
|
||||
//server minor version such as "16"
|
||||
public int minorVersion;
|
||||
private 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;
|
||||
public Field CHANNEL;
|
||||
public Method getHandle;
|
||||
public Method getProfile;
|
||||
public Method sendPacket;
|
||||
|
||||
//chat
|
||||
public Class<Enum> EnumChatFormat;
|
||||
private Class<?> IChatBaseComponent;
|
||||
private Class<?> ChatBaseComponent;
|
||||
private Class<?> ChatSerializer;
|
||||
private Class<?> EnumClickAction;
|
||||
private Class<?> EnumHoverAction;
|
||||
private Class<?> ChatModifier;
|
||||
public Class<?> ChatComponentText;
|
||||
private Class<?> ChatClickable;
|
||||
private Class<?> ChatHoverable;
|
||||
private Class<?> ChatHexColor;
|
||||
public Constructor<?> newChatComponentText;
|
||||
public Constructor<?> newChatClickable;
|
||||
public Constructor<?> newChatHoverable;
|
||||
public Constructor<?> newChatModifier;
|
||||
public Field ChatBaseComponent_extra;
|
||||
public Field ChatBaseComponent_modifier;
|
||||
public Field ChatClickable_action;
|
||||
public Field ChatClickable_value;
|
||||
public Field ChatHexColor_name;
|
||||
public Field ChatHexColor_rgb;
|
||||
public Field ChatHoverable_action;
|
||||
public Field ChatHoverable_value;
|
||||
public Field ChatModifier_color;
|
||||
public Field ChatModifier_bold;
|
||||
public Field ChatModifier_italic;
|
||||
public Field ChatModifier_underlined;
|
||||
public Field ChatModifier_strikethrough;
|
||||
public Field ChatModifier_obfuscated;
|
||||
public Field ChatModifier_clickEvent;
|
||||
public Field ChatModifier_hoverEvent;
|
||||
public Field ChatComponentText_text;
|
||||
public Method ChatSerializer_DESERIALIZE;
|
||||
public Method EnumClickAction_a;
|
||||
public Method EnumHoverAction_a;
|
||||
public Method ChatHexColor_ofInt;
|
||||
public Method ChatHexColor_ofString;
|
||||
public Method ChatComponentText_addSibling;
|
||||
|
||||
//PacketPlayOutChat
|
||||
private Class<?> PacketPlayOutChat;
|
||||
public Class<Enum> ChatMessageType;
|
||||
public Constructor<?> newPacketPlayOutChat;
|
||||
|
||||
//PacketPlayOutPlayerListHeaderFooter
|
||||
public Class<?> PacketPlayOutPlayerListHeaderFooter;
|
||||
public Constructor<?> newPacketPlayOutPlayerListHeaderFooter;
|
||||
public Field PacketPlayOutPlayerListHeaderFooter_HEADER;
|
||||
public Field PacketPlayOutPlayerListHeaderFooter_FOOTER;
|
||||
|
||||
//PacketPlayOutScoreboardDisplayObjective
|
||||
public Class<?> PacketPlayOutScoreboardDisplayObjective;
|
||||
public Constructor<?> newPacketPlayOutScoreboardDisplayObjective;
|
||||
public Field PacketPlayOutScoreboardDisplayObjective_POSITION;
|
||||
public Field PacketPlayOutScoreboardDisplayObjective_OBJECTIVENAME;
|
||||
|
||||
//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
|
||||
private Class<?> PacketPlayOutScoreboardScore;
|
||||
private Class<?> ScoreboardScore;
|
||||
public Class<Enum> EnumScoreboardAction;
|
||||
public Constructor<?> newPacketPlayOutScoreboardScore;
|
||||
public Constructor<?> newPacketPlayOutScoreboardScore_String;
|
||||
public Constructor<?> newPacketPlayOutScoreboardScore_1_13;
|
||||
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_PLAYERS;
|
||||
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;
|
||||
private Class<?> PlayerInfoData;
|
||||
public Constructor<?> newPacketPlayOutPlayerInfo;
|
||||
public Constructor<?> newPlayerInfoData;
|
||||
public Field PacketPlayOutPlayerInfo_ACTION;
|
||||
public Field PacketPlayOutPlayerInfo_PLAYERS;
|
||||
public Method PlayerInfoData_getProfile;
|
||||
public Method PlayerInfoData_getLatency;
|
||||
public Method PlayerInfoData_getGamemode;
|
||||
public Method PlayerInfoData_getDisplayName;
|
||||
|
||||
public 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;
|
||||
|
||||
public Class<?> PacketPlayOutEntityTeleport;
|
||||
public Constructor<?> newPacketPlayOutEntityTeleport;
|
||||
public Field PacketPlayOutEntityTeleport_ENTITYID;
|
||||
public Field PacketPlayOutEntityTeleport_X;
|
||||
public Field PacketPlayOutEntityTeleport_Y;
|
||||
public Field PacketPlayOutEntityTeleport_Z;
|
||||
public Field PacketPlayOutEntityTeleport_YAW;
|
||||
public Field PacketPlayOutEntityTeleport_PITCH;
|
||||
|
||||
public Class<?> PacketPlayOutEntityMetadata;
|
||||
public Constructor<?> newPacketPlayOutEntityMetadata;
|
||||
public Field PacketPlayOutEntityMetadata_LIST;
|
||||
|
||||
public Class<?> PacketPlayOutSpawnEntityLiving;
|
||||
public Constructor<?> newPacketPlayOutSpawnEntityLiving;
|
||||
public Field PacketPlayOutSpawnEntityLiving_ENTITYID;
|
||||
public Field PacketPlayOutSpawnEntityLiving_UUID;
|
||||
public Field PacketPlayOutSpawnEntityLiving_ENTITYTYPE;
|
||||
public Field PacketPlayOutSpawnEntityLiving_X;
|
||||
public Field PacketPlayOutSpawnEntityLiving_Y;
|
||||
public Field PacketPlayOutSpawnEntityLiving_Z;
|
||||
public Field PacketPlayOutSpawnEntityLiving_YAW;
|
||||
public Field PacketPlayOutSpawnEntityLiving_PITCH;
|
||||
public Field PacketPlayOutSpawnEntityLiving_DATAWATCHER;
|
||||
|
||||
//DataWatcher
|
||||
private Class<?> DataWatcher;
|
||||
public Constructor<?> newDataWatcher;
|
||||
public Method DataWatcher_REGISTER;
|
||||
|
||||
private Class<?> DataWatcherItem;
|
||||
public Field DataWatcherItem_TYPE;
|
||||
public Field DataWatcherItem_VALUE;
|
||||
|
||||
private Class<?> DataWatcherObject;
|
||||
public Constructor<?> newDataWatcherObject;
|
||||
public Field DataWatcherObject_SLOT;
|
||||
public Field DataWatcherObject_SERIALIZER;
|
||||
|
||||
private Class<?> DataWatcherRegistry;
|
||||
private Class<?> DataWatcherSerializer;
|
||||
private Map<String, Class<?>> classes = new HashMap<>();
|
||||
private Map<String, Constructor<?>> constructors = new HashMap<>();
|
||||
private Map<String, Field> fields = new HashMap<>();
|
||||
private Map<String, Method> methods = new HashMap<>();
|
||||
private Map<String, Enum[]> enums = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Creates new instance, initializes required NMS classes and fields
|
||||
* @throws Exception - if something fails
|
||||
* @throws NoSuchFieldException
|
||||
* @throws SecurityException
|
||||
* @throws NoSuchMethodException
|
||||
* @throws ClassNotFoundException
|
||||
* @throws InvocationTargetException
|
||||
* @throws IllegalAccessException
|
||||
*/
|
||||
public NMSStorage() throws Exception {
|
||||
public NMSStorage() throws NoSuchFieldException, NoSuchMethodException, SecurityException, ClassNotFoundException, IllegalAccessException, InvocationTargetException {
|
||||
serverPackage = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
|
||||
minorVersion = Integer.parseInt(serverPackage.split("_")[1]);
|
||||
initializeClasses();
|
||||
initializeConstructors();
|
||||
initializeFields();
|
||||
initializeMethods();
|
||||
dataWatcherRegistry = new DataWatcherRegistry(this, DataWatcherRegistry);
|
||||
classes.put("EnumChatFormat", getNMSClass("net.minecraft.EnumChatFormat", "EnumChatFormat"));
|
||||
classes.put("EntityPlayer", getNMSClass("net.minecraft.server.level.EntityPlayer", "EntityPlayer"));
|
||||
classes.put("Entity", getNMSClass("net.minecraft.world.entity.Entity", "Entity"));
|
||||
classes.put("EntityLiving", getNMSClass("net.minecraft.world.entity.EntityLiving", "EntityLiving"));
|
||||
classes.put("Packet", getNMSClass("net.minecraft.network.protocol.Packet", "Packet"));
|
||||
classes.put("PlayerConnection", getNMSClass("net.minecraft.server.network.PlayerConnection", "PlayerConnection"));
|
||||
classes.put("NetworkManager", getNMSClass("net.minecraft.network.NetworkManager", "NetworkManager"));
|
||||
fields.put("PING", getField(getClass("EntityPlayer"), "ping", "latency", "e"));
|
||||
fields.put("PLAYER_CONNECTION", getFields(getClass("EntityPlayer"), getClass("PlayerConnection")).get(0));
|
||||
methods.put("getHandle", Class.forName("org.bukkit.craftbukkit." + serverPackage + ".entity.CraftPlayer").getMethod("getHandle"));
|
||||
methods.put("sendPacket", getMethod(getClass("PlayerConnection"), new String[]{"sendPacket", "func_147359_a"}, getClass("Packet")));
|
||||
if (minorVersion >= 7) {
|
||||
fields.put("NETWORK_MANAGER", getFields(getClass("PlayerConnection"), getClass("NetworkManager")).get(0));
|
||||
}
|
||||
if (minorVersion >= 8) {
|
||||
fields.put("CHANNEL", getFields(getClass("NetworkManager"), Channel.class).get(0));
|
||||
methods.put("getProfile", getClass("EntityPlayer").getMethod("getProfile"));
|
||||
}
|
||||
initializeChatComponents();
|
||||
initializeChatPacket();
|
||||
initializeDataWatcher();
|
||||
initializeEntitySpawnPacket();
|
||||
initializeEntityTeleportPacket();
|
||||
initializeHeaderFooterPacket();
|
||||
initializeOtherEntityPackets();
|
||||
initializePlayerInfoPacket();
|
||||
initializeScoreboardPackets();
|
||||
initializeEnums();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -250,301 +99,264 @@ public class NMSStorage {
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes required NMS classes
|
||||
* @throws Exception - if something fails
|
||||
*/
|
||||
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");
|
||||
|
||||
private void initializeEnums() throws IllegalAccessException, InvocationTargetException, NoSuchMethodException, SecurityException {
|
||||
for (String name : Arrays.asList("ChatMessageType", "EnumPlayerInfoAction", "EnumGamemode", "EnumScoreboardHealthDisplay", "EnumScoreboardAction",
|
||||
"PacketPlayOutScoreboardTeam_a", "EnumChatFormat", "EnumNameTagVisibility", "EnumTeamPush")) {
|
||||
if (classes.containsKey(name)) enums.put(name, (Enum[]) getClass(name).getMethod("values").invoke(null));
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeChatComponents() throws ClassNotFoundException, NoSuchMethodException, SecurityException {
|
||||
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");
|
||||
classes.put("ChatBaseComponent", getNMSClass("net.minecraft.network.chat.ChatBaseComponent", "ChatBaseComponent"));
|
||||
classes.put("ChatClickable", getNMSClass("net.minecraft.network.chat.ChatClickable", "ChatClickable"));
|
||||
classes.put("ChatComponentText", getNMSClass("net.minecraft.network.chat.ChatComponentText", "ChatComponentText"));
|
||||
classes.put("ChatHoverable", getNMSClass("net.minecraft.network.chat.ChatHoverable", "ChatHoverable"));
|
||||
classes.put("ChatModifier", getNMSClass("net.minecraft.network.chat.ChatModifier", "ChatModifier"));
|
||||
classes.put("ChatSerializer", getNMSClass("net.minecraft.network.chat.IChatBaseComponent$ChatSerializer", "IChatBaseComponent$ChatSerializer", "ChatSerializer"));
|
||||
classes.put("EnumClickAction", getNMSClass("net.minecraft.network.chat.ChatClickable$EnumClickAction", "ChatClickable$EnumClickAction", "EnumClickAction"));
|
||||
classes.put("EnumHoverAction", getNMSClass("net.minecraft.network.chat.ChatHoverable$EnumHoverAction", "ChatHoverable$EnumHoverAction", "EnumHoverAction"));
|
||||
classes.put("IChatBaseComponent", getNMSClass("net.minecraft.network.chat.IChatBaseComponent", "IChatBaseComponent"));
|
||||
constructors.put("ChatComponentText", getClass("ChatComponentText").getConstructor(String.class));
|
||||
constructors.put("ChatClickable", getClass("ChatClickable").getConstructor(getClass("EnumClickAction"), String.class));
|
||||
constructors.put("ChatHoverable", getClass("ChatHoverable").getConstructors()[0]);
|
||||
fields.put("ChatBaseComponent_extra", getFields(getClass("ChatBaseComponent"), List.class).get(0));
|
||||
fields.put("ChatBaseComponent_modifier", getFields(getClass("ChatBaseComponent"), getClass("ChatModifier")).get(0));
|
||||
fields.put("ChatComponentText_text", getFields(getClass("ChatComponentText"), String.class).get(0));
|
||||
fields.put("ChatClickable_action", getFields(getClass("ChatClickable"), getClass("EnumClickAction")).get(0));
|
||||
fields.put("ChatClickable_value", getFields(getClass("ChatClickable"), String.class).get(0));
|
||||
fields.put("ChatHoverable_action", getFields(getClass("ChatHoverable"), getClass("EnumHoverAction")).get(0));
|
||||
List<Field> booleans = getFields(getClass("ChatModifier"), Boolean.class);
|
||||
fields.put("ChatModifier_bold", booleans.get(0));
|
||||
fields.put("ChatModifier_italic", booleans.get(1));
|
||||
fields.put("ChatModifier_underlined", booleans.get(2));
|
||||
fields.put("ChatModifier_strikethrough", booleans.get(3));
|
||||
fields.put("ChatModifier_obfuscated", booleans.get(4));
|
||||
fields.put("ChatModifier_clickEvent", getFields(getClass("ChatModifier"), getClass("ChatClickable")).get(0));
|
||||
fields.put("ChatModifier_hoverEvent", getFields(getClass("ChatModifier"), getClass("ChatHoverable")).get(0));
|
||||
methods.put("ChatComponentText_addSibling", getMethod(getClass("ChatComponentText"), new String[]{"addSibling", "a", "func_150257_a"}, getClass("IChatBaseComponent"))); //v1.7.R4+, v1.7.R3-
|
||||
methods.put("ChatSerializer_DESERIALIZE", getMethod(getClass("ChatSerializer"), new String[]{"a", "func_150699_a"}, String.class));
|
||||
methods.put("EnumClickAction_a", getMethod(getClass("EnumClickAction"), new String[]{"a", "func_150672_a"}, String.class));
|
||||
methods.put("EnumHoverAction_a", getMethod(getClass("EnumHoverAction"), new String[]{"a", "func_150684_a"}, String.class));
|
||||
}
|
||||
|
||||
if (minorVersion >= 8) {
|
||||
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("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 >= 16) {
|
||||
classes.put("ChatHexColor", getNMSClass("net.minecraft.network.chat.ChatHexColor", "ChatHexColor"));
|
||||
constructors.put("ChatModifier", getConstructor(getClass("ChatModifier"), 10));
|
||||
List<Field> list = getFields(getClass("ChatHexColor"), String.class);
|
||||
fields.put("ChatHexColor_name", list.get(list.size()-1));
|
||||
fields.put("ChatHexColor_rgb", getFields(getClass("ChatHexColor"), int.class).get(0));
|
||||
fields.put("ChatHoverable_value", getFields(getClass("ChatHoverable"), Object.class).get(0));
|
||||
fields.put("ChatModifier_color", getFields(getClass("ChatModifier"), getClass("ChatHexColor")).get(0));
|
||||
methods.put("ChatHexColor_ofInt", getClass("ChatHexColor").getMethod("a", int.class));
|
||||
methods.put("ChatHexColor_ofString", getClass("ChatHexColor").getMethod("a", String.class));
|
||||
} else if (minorVersion >= 7) {
|
||||
constructors.put("ChatModifier", getClass("ChatModifier").getConstructor());
|
||||
fields.put("ChatHoverable_value", getFields(getClass("ChatHoverable"), getClass("IChatBaseComponent")).get(0));
|
||||
fields.put("ChatModifier_color", getFields(getClass("ChatModifier"), getClass("EnumChatFormat")).get(0));
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeChatPacket() throws ClassNotFoundException, NoSuchMethodException, SecurityException {
|
||||
classes.put("PacketPlayOutChat", getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutChat", "PacketPlayOutChat", "Packet3Chat"));
|
||||
if (minorVersion >= 12) {
|
||||
ChatMessageType = (Class<Enum>) getNMSClass("net.minecraft.network.chat.ChatMessageType", "ChatMessageType");
|
||||
classes.put("ChatMessageType", getNMSClass("net.minecraft.network.chat.ChatMessageType", "ChatMessageType"));
|
||||
}
|
||||
if (minorVersion >= 16) {
|
||||
ChatHexColor = getNMSClass("net.minecraft.network.chat.ChatHexColor", "ChatHexColor");
|
||||
}
|
||||
if (minorVersion >= 17) {
|
||||
PacketPlayOutScoreboardTeam_a = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutScoreboardTeam$a");
|
||||
constructors.put("PacketPlayOutChat", getClass("PacketPlayOutChat").getConstructor(getClass("IChatBaseComponent"), getClass("ChatMessageType"), UUID.class));
|
||||
} else if (minorVersion >= 12) {
|
||||
constructors.put("PacketPlayOutChat", getClass("PacketPlayOutChat").getConstructor(getClass("IChatBaseComponent"), getClass("ChatMessageType")));
|
||||
} else if (minorVersion >= 8) {
|
||||
constructors.put("PacketPlayOutChat", getClass("PacketPlayOutChat").getConstructor(getClass("IChatBaseComponent"), byte.class));
|
||||
} else if (minorVersion >= 7){
|
||||
constructors.put("PacketPlayOutChat", getClass("PacketPlayOutChat").getConstructor(getClass("IChatBaseComponent")));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes required NMS constructors
|
||||
* @throws Exception - if something fails
|
||||
*/
|
||||
private void initializeConstructors() throws Exception {
|
||||
newDataWatcher = DataWatcher.getConstructors()[0];
|
||||
newPacketPlayOutEntityMetadata = PacketPlayOutEntityMetadata.getConstructor(int.class, DataWatcher, boolean.class);
|
||||
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);
|
||||
|
||||
private void initializeDataWatcher() throws ClassNotFoundException, NoSuchMethodException, SecurityException {
|
||||
classes.put("DataWatcher", getNMSClass("net.minecraft.network.syncher.DataWatcher", "DataWatcher"));
|
||||
classes.put("DataWatcherItem", getNMSClass("net.minecraft.network.syncher.DataWatcher$Item", "DataWatcher$Item", "DataWatcher$WatchableObject", "WatchableObject"));
|
||||
if (minorVersion >= 7) {
|
||||
newChatComponentText = ChatComponentText.getConstructor(String.class);
|
||||
newChatClickable = ChatClickable.getConstructor(EnumClickAction, String.class);
|
||||
newChatHoverable = ChatHoverable.getConstructors()[0];
|
||||
}
|
||||
if (minorVersion >= 8) {
|
||||
newPacketPlayOutPlayerListHeaderFooter = PacketPlayOutPlayerListHeaderFooter.getConstructors()[0];
|
||||
newPacketPlayOutPlayerInfo = PacketPlayOutPlayerInfo.getConstructor(EnumPlayerInfoAction, Array.newInstance(EntityPlayer, 0).getClass());
|
||||
newPlayerInfoData = PlayerInfoData.getConstructors()[0];
|
||||
constructors.put("DataWatcher", getClass("DataWatcher").getConstructor(getClass("Entity")));
|
||||
} else {
|
||||
constructors.put("DataWatcher", getClass("DataWatcher").getConstructor());
|
||||
}
|
||||
if (minorVersion >= 9) {
|
||||
newDataWatcherObject = DataWatcherObject.getConstructors()[0];
|
||||
}
|
||||
if (minorVersion >= 13) {
|
||||
newPacketPlayOutScoreboardObjective = PacketPlayOutScoreboardObjective.getConstructor(ScoreboardObjective, int.class);
|
||||
newPacketPlayOutScoreboardScore_1_13 = PacketPlayOutScoreboardScore.getConstructor(EnumScoreboardAction, String.class, String.class, int.class);
|
||||
classes.put("DataWatcherObject", getNMSClass("net.minecraft.network.syncher.DataWatcherObject", "DataWatcherObject"));
|
||||
classes.put("DataWatcherRegistry", getNMSClass("net.minecraft.network.syncher.DataWatcherRegistry", "DataWatcherRegistry"));
|
||||
classes.put("DataWatcherSerializer", getNMSClass("net.minecraft.network.syncher.DataWatcherSerializer", "DataWatcherSerializer"));
|
||||
constructors.put("DataWatcherObject", getClass("DataWatcherObject").getConstructor(int.class, getClass("DataWatcherSerializer")));
|
||||
fields.put("DataWatcherItem_TYPE", getFields(getClass("DataWatcherItem"), getClass("DataWatcherObject")).get(0));
|
||||
fields.put("DataWatcherItem_VALUE", getFields(getClass("DataWatcherItem"), Object.class).get(0));
|
||||
fields.put("DataWatcherObject_SLOT", getFields(getClass("DataWatcherObject"), int.class).get(0));
|
||||
fields.put("DataWatcherObject_SERIALIZER", getFields(getClass("DataWatcherObject"), getClass("DataWatcherSerializer")).get(0));
|
||||
methods.put("DataWatcher_REGISTER", getClass("DataWatcher").getMethod("register", getClass("DataWatcherObject"), Object.class));
|
||||
} else {
|
||||
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) {
|
||||
newChatModifier = getConstructor(ChatModifier, 10);
|
||||
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);
|
||||
fields.put("DataWatcherItem_TYPE", getFields(getClass("DataWatcherItem"), int.class).get(1));
|
||||
fields.put("DataWatcherItem_VALUE", getFields(getClass("DataWatcherItem"), Object.class).get(0));
|
||||
methods.put("DataWatcher_REGISTER", getMethod(getClass("DataWatcher"), new String[]{"a", "func_75682_a"}, int.class, Object.class));
|
||||
}
|
||||
dataWatcherRegistry = new DataWatcherRegistry(this, getClass("DataWatcherRegistry"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes required NMS fields
|
||||
* @throws Exception - if something fails
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
if (minorVersion >= 8) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
private void initializeEntitySpawnPacket() throws ClassNotFoundException, NoSuchMethodException, SecurityException {
|
||||
classes.put("PacketPlayOutSpawnEntityLiving", getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutSpawnEntityLiving", "PacketPlayOutSpawnEntityLiving", "Packet24MobSpawn"));
|
||||
constructors.put("PacketPlayOutSpawnEntityLiving", getClass("PacketPlayOutSpawnEntityLiving").getConstructor(getClass("EntityLiving")));
|
||||
fields.put("PacketPlayOutSpawnEntityLiving_ENTITYID", getFields(getClass("PacketPlayOutSpawnEntityLiving"), int.class).get(0));
|
||||
fields.put("PacketPlayOutSpawnEntityLiving_ENTITYTYPE", getFields(getClass("PacketPlayOutSpawnEntityLiving"), int.class).get(1));
|
||||
fields.put("PacketPlayOutSpawnEntityLiving_YAW", getFields(getClass("PacketPlayOutSpawnEntityLiving"), byte.class).get(0));
|
||||
fields.put("PacketPlayOutSpawnEntityLiving_PITCH", getFields(getClass("PacketPlayOutSpawnEntityLiving"), byte.class).get(0));
|
||||
if (minorVersion >= 9) {
|
||||
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);
|
||||
fields.put("PacketPlayOutSpawnEntityLiving_UUID", getFields(getClass("PacketPlayOutSpawnEntityLiving"), UUID.class).get(0));
|
||||
fields.put("PacketPlayOutSpawnEntityLiving_X", getFields(getClass("PacketPlayOutSpawnEntityLiving"), double.class).get(0));
|
||||
fields.put("PacketPlayOutSpawnEntityLiving_Y", getFields(getClass("PacketPlayOutSpawnEntityLiving"), double.class).get(1));
|
||||
fields.put("PacketPlayOutSpawnEntityLiving_Z", getFields(getClass("PacketPlayOutSpawnEntityLiving"), double.class).get(2));
|
||||
} else {
|
||||
//1.8-
|
||||
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);
|
||||
fields.put("PacketPlayOutSpawnEntityLiving_X", getFields(getClass("PacketPlayOutSpawnEntityLiving"), int.class).get(2));
|
||||
fields.put("PacketPlayOutSpawnEntityLiving_Y", getFields(getClass("PacketPlayOutSpawnEntityLiving"), int.class).get(3));
|
||||
fields.put("PacketPlayOutSpawnEntityLiving_Z", getFields(getClass("PacketPlayOutSpawnEntityLiving"), int.class).get(4));
|
||||
}
|
||||
|
||||
if (minorVersion >= 13) {
|
||||
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+
|
||||
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 {
|
||||
PING = getField(EntityPlayer, "ping");
|
||||
fields.put("PacketPlayOutSpawnEntityLiving_DATAWATCHER", getFields(getClass("PacketPlayOutSpawnEntityLiving"), getClass("DataWatcher")).get(0));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes required NMS methods
|
||||
* @throws Exception - if something fails
|
||||
*/
|
||||
private void initializeMethods() throws Exception {
|
||||
getHandle = Class.forName("org.bukkit.craftbukkit." + serverPackage + ".entity.CraftPlayer").getMethod("getHandle");
|
||||
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) {
|
||||
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");
|
||||
}
|
||||
|
||||
private void initializeEntityTeleportPacket() throws NoSuchMethodException, SecurityException, ClassNotFoundException {
|
||||
classes.put("PacketPlayOutEntityTeleport", getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutEntityTeleport", "PacketPlayOutEntityTeleport", "Packet34EntityTeleport"));
|
||||
constructors.put("PacketPlayOutEntityTeleport", getClass("PacketPlayOutEntityTeleport").getConstructor(getClass("Entity")));
|
||||
fields.put("PacketPlayOutEntityTeleport_ENTITYID", getFields(getClass("PacketPlayOutEntityTeleport"), int.class).get(0));
|
||||
fields.put("PacketPlayOutEntityTeleport_YAW", getFields(getClass("PacketPlayOutEntityTeleport"), byte.class).get(0));
|
||||
fields.put("PacketPlayOutEntityTeleport_PITCH", getFields(getClass("PacketPlayOutEntityTeleport"), byte.class).get(1));
|
||||
if (minorVersion >= 9) {
|
||||
ScoreboardTeam_setCollisionRule = ScoreboardTeam.getMethod("setCollisionRule", EnumTeamPush);
|
||||
DataWatcher_REGISTER = DataWatcher.getMethod("register", DataWatcherObject, Object.class);
|
||||
fields.put("PacketPlayOutEntityTeleport_X", getFields(getClass("PacketPlayOutEntityTeleport"), double.class).get(0));
|
||||
fields.put("PacketPlayOutEntityTeleport_Y", getFields(getClass("PacketPlayOutEntityTeleport"), double.class).get(1));
|
||||
fields.put("PacketPlayOutEntityTeleport_Z", getFields(getClass("PacketPlayOutEntityTeleport"), double.class).get(2));
|
||||
} else {
|
||||
DataWatcher_REGISTER = getMethod(DataWatcher, new String[]{"a", "func_75682_a"}, int.class, Object.class);
|
||||
fields.put("PacketPlayOutEntityTeleport_X", getFields(getClass("PacketPlayOutEntityTeleport"), int.class).get(1));
|
||||
fields.put("PacketPlayOutEntityTeleport_Y", getFields(getClass("PacketPlayOutEntityTeleport"), int.class).get(2));
|
||||
fields.put("PacketPlayOutEntityTeleport_Z", getFields(getClass("PacketPlayOutEntityTeleport"), int.class).get(3));
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
private void initializeHeaderFooterPacket() throws ClassNotFoundException, NoSuchMethodException, SecurityException {
|
||||
if (minorVersion >= 8) {
|
||||
classes.put("PacketPlayOutPlayerListHeaderFooter", getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutPlayerListHeaderFooter", "PacketPlayOutPlayerListHeaderFooter"));
|
||||
fields.put("PacketPlayOutPlayerListHeaderFooter_HEADER", getFields(getClass("PacketPlayOutPlayerListHeaderFooter"), getClass("IChatBaseComponent")).get(0));
|
||||
fields.put("PacketPlayOutPlayerListHeaderFooter_FOOTER", getFields(getClass("PacketPlayOutPlayerListHeaderFooter"), getClass("IChatBaseComponent")).get(1));
|
||||
if (minorVersion >= 17) {
|
||||
constructors.put("PacketPlayOutPlayerListHeaderFooter", getClass("PacketPlayOutPlayerListHeaderFooter").getConstructor(getClass("IChatBaseComponent"), getClass("IChatBaseComponent")));
|
||||
} else {
|
||||
constructors.put("PacketPlayOutPlayerListHeaderFooter", getClass("PacketPlayOutPlayerListHeaderFooter").getConstructor());
|
||||
}
|
||||
}
|
||||
if (minorVersion >= 16) {
|
||||
ChatHexColor_ofInt = ChatHexColor.getMethod("a", int.class);
|
||||
ChatHexColor_ofString = ChatHexColor.getMethod("a", String.class);
|
||||
}
|
||||
|
||||
private void initializeOtherEntityPackets() throws ClassNotFoundException, NoSuchMethodException {
|
||||
classes.put("PacketPlayInUseEntity", getNMSClass("net.minecraft.network.protocol.game.PacketPlayInUseEntity", "PacketPlayInUseEntity", "Packet7UseEntity"));
|
||||
classes.put("PacketPlayOutEntity", getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutEntity", "PacketPlayOutEntity", "Packet30Entity"));
|
||||
classes.put("PacketPlayOutEntityDestroy", getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutEntityDestroy", "PacketPlayOutEntityDestroy", "Packet29DestroyEntity"));
|
||||
classes.put("PacketPlayOutEntityLook", getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutEntity$PacketPlayOutEntityLook", "PacketPlayOutEntity$PacketPlayOutEntityLook", "PacketPlayOutEntityLook", "Packet32EntityLook"));
|
||||
classes.put("PacketPlayOutEntityMetadata", getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutEntityMetadata", "PacketPlayOutEntityMetadata", "Packet40EntityMetadata"));
|
||||
classes.put("PacketPlayOutNamedEntitySpawn", getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutNamedEntitySpawn", "PacketPlayOutNamedEntitySpawn", "Packet20NamedEntitySpawn"));
|
||||
constructors.put("PacketPlayOutEntityMetadata", getClass("PacketPlayOutEntityMetadata").getConstructor(int.class, getClass("DataWatcher"), boolean.class));
|
||||
fields.put("PacketPlayOutEntity_ENTITYID", getFields(getClass("PacketPlayOutEntity"), int.class).get(0));
|
||||
fields.put("PacketPlayOutEntityDestroy_ENTITIES", getClass("PacketPlayOutEntityDestroy").getDeclaredFields()[0]);
|
||||
fields.get("PacketPlayOutEntityDestroy_ENTITIES").setAccessible(true);
|
||||
fields.put("PacketPlayOutEntityMetadata_LIST", getFields(getClass("PacketPlayOutEntityMetadata"), List.class).get(0));
|
||||
fields.put("PacketPlayOutNamedEntitySpawn_ENTITYID", getFields(getClass("PacketPlayOutNamedEntitySpawn"), int.class).get(0));
|
||||
if (minorVersion >= 7) {
|
||||
classes.put("EnumEntityUseAction", getNMSClass("net.minecraft.network.protocol.game.PacketPlayInUseEntity$EnumEntityUseAction", "PacketPlayInUseEntity$EnumEntityUseAction", "EnumEntityUseAction"));
|
||||
fields.put("PacketPlayInUseEntity_ENTITY", getFields(getClass("PacketPlayInUseEntity"), int.class).get(0));
|
||||
fields.put("PacketPlayInUseEntity_ACTION", getFields(getClass("PacketPlayInUseEntity"), getClass("EnumEntityUseAction")).get(0));
|
||||
}
|
||||
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);
|
||||
classes.put("PacketPlayInUseEntity$d", Class.forName("net.minecraft.network.protocol.game.PacketPlayInUseEntity$d"));
|
||||
}
|
||||
try {
|
||||
constructors.put("PacketPlayOutEntityDestroy", getClass("PacketPlayOutEntityDestroy").getConstructor(int[].class));
|
||||
} catch (NoSuchMethodException e) {
|
||||
//1.17.0
|
||||
constructors.put("PacketPlayOutEntityDestroy", getClass("PacketPlayOutEntityDestroy").getConstructor(int.class));
|
||||
}
|
||||
}
|
||||
|
||||
private void initializePlayerInfoPacket() throws ClassNotFoundException, NoSuchMethodException, SecurityException {
|
||||
if (minorVersion >= 8) {
|
||||
classes.put("PacketPlayOutPlayerInfo", getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo", "PacketPlayOutPlayerInfo"));
|
||||
classes.put("EnumPlayerInfoAction", getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo$EnumPlayerInfoAction", "PacketPlayOutPlayerInfo$EnumPlayerInfoAction", "EnumPlayerInfoAction"));
|
||||
classes.put("PlayerInfoData", getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo$PlayerInfoData", "PacketPlayOutPlayerInfo$PlayerInfoData", "PlayerInfoData"));
|
||||
classes.put("EnumGamemode", getNMSClass("net.minecraft.world.level.EnumGamemode", "EnumGamemode", "WorldSettings$EnumGamemode"));
|
||||
constructors.put("PacketPlayOutPlayerInfo", getClass("PacketPlayOutPlayerInfo").getConstructor(getClass("EnumPlayerInfoAction"), Array.newInstance(getClass("EntityPlayer"), 0).getClass()));
|
||||
constructors.put("PlayerInfoData", getClass("PlayerInfoData").getConstructors()[0]);
|
||||
fields.put("PacketPlayOutPlayerInfo_ACTION", getFields(getClass("PacketPlayOutPlayerInfo"), getClass("EnumPlayerInfoAction")).get(0));
|
||||
fields.put("PacketPlayOutPlayerInfo_PLAYERS", getFields(getClass("PacketPlayOutPlayerInfo"), List.class).get(0));
|
||||
methods.put("PlayerInfoData_getProfile", getClass("PlayerInfoData").getMethod("a"));
|
||||
methods.put("PlayerInfoData_getLatency", getClass("PlayerInfoData").getMethod("b"));
|
||||
methods.put("PlayerInfoData_getGamemode", getClass("PlayerInfoData").getMethod("c"));
|
||||
methods.put("PlayerInfoData_getDisplayName", getClass("PlayerInfoData").getMethod("d"));
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeScoreboardPackets() throws ClassNotFoundException, NoSuchMethodException, SecurityException {
|
||||
classes.put("PacketPlayOutScoreboardDisplayObjective", getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutScoreboardDisplayObjective", "PacketPlayOutScoreboardDisplayObjective", "Packet208SetScoreboardDisplayObjective"));
|
||||
classes.put("PacketPlayOutScoreboardObjective", getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutScoreboardObjective", "PacketPlayOutScoreboardObjective", "Packet206SetScoreboardObjective"));
|
||||
classes.put("PacketPlayOutScoreboardScore", getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutScoreboardScore", "PacketPlayOutScoreboardScore", "Packet207SetScoreboardScore"));
|
||||
classes.put("PacketPlayOutScoreboardTeam", getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutScoreboardTeam", "PacketPlayOutScoreboardTeam", "Packet209SetScoreboardTeam"));
|
||||
classes.put("Scoreboard", getNMSClass("net.minecraft.world.scores.Scoreboard", "Scoreboard"));
|
||||
classes.put("ScoreboardObjective", getNMSClass("net.minecraft.world.scores.ScoreboardObjective", "ScoreboardObjective"));
|
||||
classes.put("ScoreboardTeam", getNMSClass("net.minecraft.world.scores.ScoreboardTeam", "ScoreboardTeam"));
|
||||
classes.put("ScoreboardScore", getNMSClass("net.minecraft.world.scores.ScoreboardScore", "ScoreboardScore"));
|
||||
classes.put("IScoreboardCriteria", getNMSClass("net.minecraft.world.scores.criteria.IScoreboardCriteria", "IScoreboardCriteria"));
|
||||
constructors.put("ScoreboardObjective", getClass("ScoreboardObjective").getConstructors()[0]);
|
||||
constructors.put("Scoreboard", getClass("Scoreboard").getConstructor());
|
||||
constructors.put("ScoreboardTeam", getClass("ScoreboardTeam").getConstructor(getClass("Scoreboard"), String.class));
|
||||
constructors.put("ScoreboardScore", getClass("ScoreboardScore").getConstructor(getClass("Scoreboard"), getClass("ScoreboardObjective"), String.class));
|
||||
constructors.put("PacketPlayOutScoreboardDisplayObjective", getClass("PacketPlayOutScoreboardDisplayObjective").getConstructor(int.class, getClass("ScoreboardObjective")));
|
||||
fields.put("PacketPlayOutScoreboardDisplayObjective_POSITION", getFields(getClass("PacketPlayOutScoreboardDisplayObjective"), int.class).get(0));
|
||||
fields.put("PacketPlayOutScoreboardDisplayObjective_OBJECTIVENAME", getFields(getClass("PacketPlayOutScoreboardDisplayObjective"), String.class).get(0));
|
||||
fields.put("PacketPlayOutScoreboardObjective_OBJECTIVENAME", getFields(getClass("PacketPlayOutScoreboardObjective"), String.class).get(0));
|
||||
List<Field> list = getFields(getClass("PacketPlayOutScoreboardObjective"), int.class);
|
||||
fields.put("PacketPlayOutScoreboardObjective_METHOD", list.get(list.size()-1));
|
||||
fields.put("PacketPlayOutScoreboardTeam_NAME", getFields(getClass("PacketPlayOutScoreboardTeam"), String.class).get(0));
|
||||
fields.put("PacketPlayOutScoreboardTeam_PLAYERS", getFields(getClass("PacketPlayOutScoreboardTeam"), Collection.class).get(0));
|
||||
methods.put("ScoreboardTeam_getPlayerNameSet", getMethod(getClass("ScoreboardTeam"), new String[]{"getPlayerNameSet", "func_96670_d"}));
|
||||
methods.put("ScoreboardScore_setScore", getMethod(getClass("ScoreboardScore"), new String[]{"setScore", "func_96647_c"}, int.class));
|
||||
if (minorVersion >= 8) {
|
||||
classes.put("EnumScoreboardHealthDisplay", getNMSClass("net.minecraft.world.scores.criteria.IScoreboardCriteria$EnumScoreboardHealthDisplay", "IScoreboardCriteria$EnumScoreboardHealthDisplay", "EnumScoreboardHealthDisplay"));
|
||||
classes.put("EnumScoreboardAction", getNMSClass("net.minecraft.server.ScoreboardServer$Action", "ScoreboardServer$Action", "PacketPlayOutScoreboardScore$EnumScoreboardAction", "EnumScoreboardAction"));
|
||||
classes.put("EnumNameTagVisibility", getNMSClass("net.minecraft.world.scores.ScoreboardTeamBase$EnumNameTagVisibility", "ScoreboardTeamBase$EnumNameTagVisibility", "EnumNameTagVisibility"));
|
||||
fields.put("PacketPlayOutScoreboardObjective_RENDERTYPE", getFields(getClass("PacketPlayOutScoreboardObjective"), getClass("EnumScoreboardHealthDisplay")).get(0));
|
||||
methods.put("ScoreboardTeam_setNameTagVisibility", getMethod(getClass("ScoreboardTeam"), new String[]{"setNameTagVisibility", "a"}, getClass("EnumNameTagVisibility")));
|
||||
}
|
||||
if (minorVersion >= 9) {
|
||||
classes.put("EnumTeamPush", getNMSClass("net.minecraft.world.scores.ScoreboardTeamBase$EnumTeamPush", "ScoreboardTeamBase$EnumTeamPush"));
|
||||
methods.put("ScoreboardTeam_setCollisionRule", getClass("ScoreboardTeam").getMethod("setCollisionRule", getClass("EnumTeamPush")));
|
||||
}
|
||||
if (minorVersion >= 13) {
|
||||
constructors.put("PacketPlayOutScoreboardObjective", getClass("PacketPlayOutScoreboardObjective").getConstructor(getClass("ScoreboardObjective"), int.class));
|
||||
constructors.put("PacketPlayOutScoreboardScore_1_13", getClass("PacketPlayOutScoreboardScore").getConstructor(getClass("EnumScoreboardAction"), String.class, String.class, int.class));
|
||||
fields.put("PacketPlayOutScoreboardObjective_DISPLAYNAME", getFields(getClass("PacketPlayOutScoreboardObjective"), getClass("IChatBaseComponent")).get(0));
|
||||
methods.put("ScoreboardTeam_setPrefix", getClass("ScoreboardTeam").getMethod("setPrefix", getClass("IChatBaseComponent")));
|
||||
methods.put("ScoreboardTeam_setSuffix", getClass("ScoreboardTeam").getMethod("setSuffix", getClass("IChatBaseComponent")));
|
||||
methods.put("ScoreboardTeam_setColor", getClass("ScoreboardTeam").getMethod("setColor", getClass("EnumChatFormat")));
|
||||
} else {
|
||||
constructors.put("PacketPlayOutScoreboardObjective", getClass("PacketPlayOutScoreboardObjective").getConstructor());
|
||||
constructors.put("PacketPlayOutScoreboardScore_String", getClass("PacketPlayOutScoreboardScore").getConstructor(String.class));
|
||||
fields.put("PacketPlayOutScoreboardObjective_DISPLAYNAME", getFields(getClass("PacketPlayOutScoreboardObjective"), String.class).get(1));
|
||||
methods.put("ScoreboardTeam_setPrefix", getMethod(getClass("ScoreboardTeam"), new String[]{"setPrefix", "func_96666_b"}, String.class));
|
||||
methods.put("ScoreboardTeam_setSuffix", getMethod(getClass("ScoreboardTeam"), new String[]{"setSuffix", "func_96662_c"}, String.class));
|
||||
if (minorVersion >= 8) {
|
||||
constructors.put("PacketPlayOutScoreboardScore", getClass("PacketPlayOutScoreboardScore").getConstructor(getClass("ScoreboardScore")));
|
||||
} else {
|
||||
constructors.put("PacketPlayOutScoreboardScore", getClass("PacketPlayOutScoreboardScore").getConstructor(getClass("ScoreboardScore"), int.class));
|
||||
}
|
||||
}
|
||||
if (minorVersion >= 17) {
|
||||
classes.put("PacketPlayOutScoreboardTeam_a", Class.forName("net.minecraft.network.protocol.game.PacketPlayOutScoreboardTeam$a"));
|
||||
methods.put("PacketPlayOutScoreboardTeam_of", getClass("PacketPlayOutScoreboardTeam").getMethod("a", getClass("ScoreboardTeam")));
|
||||
methods.put("PacketPlayOutScoreboardTeam_ofBoolean", getClass("PacketPlayOutScoreboardTeam").getMethod("a", getClass("ScoreboardTeam"), boolean.class));
|
||||
methods.put("PacketPlayOutScoreboardTeam_ofString", getClass("PacketPlayOutScoreboardTeam").getMethod("a", getClass("ScoreboardTeam"), String.class, getClass("PacketPlayOutScoreboardTeam_a")));
|
||||
} else {
|
||||
constructors.put("PacketPlayOutScoreboardTeam", getClass("PacketPlayOutScoreboardTeam").getConstructor(getClass("ScoreboardTeam"), int.class));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -553,10 +365,11 @@ public class NMSStorage {
|
||||
* Useful for modded servers which code I can not access
|
||||
* @param clazz - class to show methods of
|
||||
*/
|
||||
public void showMethods(Class<?> clazz) {
|
||||
System.out.println("--- " + clazz.getSimpleName() + " ---");
|
||||
@SuppressWarnings("unused")
|
||||
private void showMethods(Class<?> clazz) {
|
||||
TAB.getInstance().getPlatform().sendConsoleMessage("--- " + clazz.getSimpleName() + " ---", false);
|
||||
for (Method m : clazz.getMethods()) {
|
||||
System.out.println(m.getReturnType().getName() + " " + m.getName() + "(" + Arrays.toString(m.getParameterTypes()) + ")");
|
||||
TAB.getInstance().getPlatform().sendConsoleMessage(m.getReturnType().getName() + " " + m.getName() + "(" + Arrays.toString(m.getParameterTypes()) + ")", false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -566,11 +379,12 @@ public class NMSStorage {
|
||||
* @return class for specified name(s)
|
||||
* @throws ClassNotFoundException if class does not exist
|
||||
*/
|
||||
public Class<?> getNMSClass(String... names) throws ClassNotFoundException {
|
||||
private Class<?> getNMSClass(String... names) throws ClassNotFoundException {
|
||||
for (String name : names) {
|
||||
try {
|
||||
return getNMSClass(name);
|
||||
} catch (ClassNotFoundException e) {
|
||||
//not the first class name in array
|
||||
}
|
||||
}
|
||||
throw new ClassNotFoundException("No class found with possible names " + Arrays.toString(names));
|
||||
@@ -611,6 +425,7 @@ public class NMSStorage {
|
||||
try {
|
||||
return clazz.getMethod(name, parameterTypes);
|
||||
} catch (Exception e) {
|
||||
//not the first method in array
|
||||
}
|
||||
}
|
||||
throw new NoSuchMethodException("No method found with possible names " + Arrays.toString(names) + " in class " + clazz.getName());
|
||||
@@ -624,10 +439,12 @@ public class NMSStorage {
|
||||
*/
|
||||
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>();
|
||||
List<Field> list = new ArrayList<>();
|
||||
for (Field field : clazz.getDeclaredFields()) {
|
||||
field.setAccessible(true);
|
||||
if (field.getType() == type) list.add(field);
|
||||
if (field.getType() == type) {
|
||||
field.setAccessible(true);
|
||||
list.add(field);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
@@ -661,4 +478,47 @@ public class NMSStorage {
|
||||
}
|
||||
throw new NoSuchMethodException("No constructor found in class " + clazz.getName() + " with " + parameterCount + " parameters");
|
||||
}
|
||||
|
||||
private Field getField(Class<?> clazz, String... potentialNames) throws NoSuchFieldException {
|
||||
for (String name : potentialNames) {
|
||||
try {
|
||||
return getField(clazz, name);
|
||||
} catch (NoSuchFieldException e) {
|
||||
//not the first field name from array
|
||||
}
|
||||
}
|
||||
throw new NoSuchFieldException("No field found in class " + clazz.getName() + " with potential names " + Arrays.toString(potentialNames));
|
||||
}
|
||||
|
||||
public int getMinorVersion() {
|
||||
return minorVersion;
|
||||
}
|
||||
|
||||
public Class<?> getClass(String name){
|
||||
return classes.get(name);
|
||||
}
|
||||
|
||||
public Constructor getConstructor(String name){
|
||||
return constructors.get(name);
|
||||
}
|
||||
|
||||
public Field getField(String name){
|
||||
return fields.get(name);
|
||||
}
|
||||
|
||||
public Method getMethod(String name) {
|
||||
return methods.get(name);
|
||||
}
|
||||
|
||||
public Enum[] getEnum(String name) {
|
||||
return enums.get(name);
|
||||
}
|
||||
|
||||
public void setField(Object obj, String field, Object value) throws IllegalAccessException {
|
||||
fields.get(field).set(obj, value);
|
||||
}
|
||||
|
||||
public DataWatcherRegistry getDataWatcherRegistry() {
|
||||
return dataWatcherRegistry;
|
||||
}
|
||||
}
|
||||
+20
-14
@@ -1,5 +1,6 @@
|
||||
package me.neznamy.tab.platforms.bukkit.nms.datawatcher;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -12,7 +13,7 @@ import me.neznamy.tab.platforms.bukkit.nms.NMSStorage;
|
||||
public class DataWatcher {
|
||||
|
||||
//datawatcher data
|
||||
private Map<Integer, DataWatcherItem> dataValues = new HashMap<Integer, DataWatcherItem>();
|
||||
private Map<Integer, DataWatcherItem> dataValues = new HashMap<>();
|
||||
|
||||
//a helper for easier data write
|
||||
private DataWatcherHelper helper = new DataWatcherHelper(this);
|
||||
@@ -23,7 +24,7 @@ public class DataWatcher {
|
||||
* @param value - value
|
||||
*/
|
||||
public void setValue(DataWatcherObject type, Object value){
|
||||
dataValues.put(type.position, new DataWatcherItem(type, value));
|
||||
dataValues.put(type.getPosition(), new DataWatcherItem(type, value));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -54,24 +55,26 @@ public class DataWatcher {
|
||||
/**
|
||||
* Converts the class into an instance of NMS.DataWatcher
|
||||
* @return an instance of NMS.DataWatcher with same data
|
||||
* @throws Exception - if something fails
|
||||
* @throws InvocationTargetException
|
||||
* @throws IllegalAccessException
|
||||
* @throws InstantiationException
|
||||
*/
|
||||
public Object toNMS() throws Exception {
|
||||
public Object toNMS() throws InstantiationException, IllegalAccessException, InvocationTargetException {
|
||||
NMSStorage nms = NMSStorage.getInstance();
|
||||
Object nmsWatcher;
|
||||
if (nms.newDataWatcher.getParameterCount() == 1) {
|
||||
nmsWatcher = nms.newDataWatcher.newInstance(new Object[] {null});
|
||||
if (nms.getMinorVersion() >= 7) {
|
||||
nmsWatcher = nms.getConstructor("DataWatcher").newInstance(new Object[] {null});
|
||||
} else {
|
||||
nmsWatcher = nms.newDataWatcher.newInstance();
|
||||
nmsWatcher = nms.getConstructor("DataWatcher").newInstance();
|
||||
}
|
||||
for (DataWatcherItem item : dataValues.values()) {
|
||||
Object position;
|
||||
if (nms.minorVersion >= 9) {
|
||||
position = nms.newDataWatcherObject.newInstance(item.type.position, item.type.classType);
|
||||
if (nms.getMinorVersion() >= 9) {
|
||||
position = nms.getConstructor("DataWatcherObject").newInstance(item.getType().getPosition(), item.getType().getClassType());
|
||||
} else {
|
||||
position = item.type.position;
|
||||
position = item.getType().getPosition();
|
||||
}
|
||||
nms.DataWatcher_REGISTER.invoke(nmsWatcher, position, item.value);
|
||||
nms.getMethod("DataWatcher_REGISTER").invoke(nmsWatcher, position, item.getValue());
|
||||
}
|
||||
return nmsWatcher;
|
||||
}
|
||||
@@ -80,16 +83,19 @@ public class DataWatcher {
|
||||
* Reads NMS data watcher and returns and instance of this class with same data
|
||||
* @param nmsWatcher - NMS datawatcher to read
|
||||
* @return an instance of this class with same values
|
||||
* @throws Exception - if something fails
|
||||
* @throws SecurityException
|
||||
* @throws NoSuchMethodException
|
||||
* @throws InvocationTargetException
|
||||
* @throws IllegalAccessException
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static DataWatcher fromNMS(Object nmsWatcher) throws Exception{
|
||||
public static DataWatcher fromNMS(Object nmsWatcher) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException, SecurityException{
|
||||
DataWatcher watcher = new DataWatcher();
|
||||
List<Object> items = (List<Object>) nmsWatcher.getClass().getMethod("c").invoke(nmsWatcher);
|
||||
if (items != null) {
|
||||
for (Object watchableObject : items) {
|
||||
DataWatcherItem w = DataWatcherItem.fromNMS(watchableObject);
|
||||
watcher.setValue(w.type, w.value);
|
||||
watcher.setValue(w.getType(), w.getValue());
|
||||
}
|
||||
}
|
||||
return watcher;
|
||||
|
||||
+22
-22
@@ -14,7 +14,7 @@ import me.neznamy.tab.shared.packets.IChatBaseComponent;
|
||||
public class DataWatcherHelper {
|
||||
|
||||
//position of armor stand flags
|
||||
private final int ARMOR_STAND_BYTEFLAGS_POSITION = getArmorStandFlagsPosition();
|
||||
private final int armorStandFlagsPosition = getArmorStandFlagsPosition();
|
||||
|
||||
//original datawatcher to write to
|
||||
private DataWatcher data;
|
||||
@@ -28,7 +28,7 @@ public class DataWatcherHelper {
|
||||
*/
|
||||
public DataWatcherHelper(DataWatcher data) {
|
||||
this.data = data;
|
||||
this.registry = NMSStorage.getInstance().dataWatcherRegistry;
|
||||
this.registry = NMSStorage.getInstance().getDataWatcherRegistry();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -36,16 +36,16 @@ public class DataWatcherHelper {
|
||||
* @return armor stand flags position based on server version
|
||||
*/
|
||||
private int getArmorStandFlagsPosition() {
|
||||
if (NMSStorage.getInstance().minorVersion >= 17) {
|
||||
if (NMSStorage.getInstance().getMinorVersion() >= 17) {
|
||||
//1.17.x
|
||||
return 15;
|
||||
} else if (NMSStorage.getInstance().minorVersion >= 15) {
|
||||
} else if (NMSStorage.getInstance().getMinorVersion() >= 15) {
|
||||
//1.15.x, 1.16.x
|
||||
return 14;
|
||||
} else if (NMSStorage.getInstance().minorVersion >= 14) {
|
||||
} else if (NMSStorage.getInstance().getMinorVersion() >= 14) {
|
||||
//1.14.x
|
||||
return 13;
|
||||
} else if (NMSStorage.getInstance().minorVersion >= 10) {
|
||||
} else if (NMSStorage.getInstance().getMinorVersion() >= 10) {
|
||||
//1.10.x - 1.13.x
|
||||
return 11;
|
||||
} else {
|
||||
@@ -59,7 +59,7 @@ public class DataWatcherHelper {
|
||||
* @param flags - flags to write
|
||||
*/
|
||||
public void setEntityFlags(byte flags) {
|
||||
data.setValue(new DataWatcherObject(0, registry.Byte), flags);
|
||||
data.setValue(new DataWatcherObject(0, registry.getByte()), flags);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,21 +68,21 @@ public class DataWatcherHelper {
|
||||
* @param clientVersion - client version
|
||||
*/
|
||||
public void setCustomName(String customName, ProtocolVersion clientVersion) {
|
||||
if (NMSStorage.getInstance().minorVersion >= 13) {
|
||||
if (NMSStorage.getInstance().getMinorVersion() >= 13) {
|
||||
try {
|
||||
data.setValue(new DataWatcherObject(2, registry.Optional_IChatBaseComponent), Optional.ofNullable(((BukkitPacketBuilder)TAB.getInstance().getPacketBuilder()).toNMSComponent(IChatBaseComponent.optimizedComponent(customName), clientVersion)));
|
||||
data.setValue(new DataWatcherObject(2, registry.getOptionalComponent()), 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 (NMSStorage.getInstance().minorVersion >= 8){
|
||||
data.setValue(new DataWatcherObject(2, registry.String), customName);
|
||||
} else if (NMSStorage.getInstance().getMinorVersion() >= 8){
|
||||
data.setValue(new DataWatcherObject(2, registry.getString()), customName);
|
||||
} else {
|
||||
//name length is limited to 64 characters on <1.8
|
||||
String cutName = (customName.length() > 64 ? customName.substring(0, 64) : customName);
|
||||
data.setValue(new DataWatcherObject(10, registry.String), cutName);
|
||||
if (NMSStorage.getInstance().minorVersion >= 6){
|
||||
data.setValue(new DataWatcherObject(10, registry.String), cutName);
|
||||
if (NMSStorage.getInstance().getMinorVersion() >= 6){
|
||||
data.setValue(new DataWatcherObject(10, registry.getString()), cutName);
|
||||
} else {
|
||||
data.setValue(new DataWatcherObject(5, registry.String), cutName);
|
||||
data.setValue(new DataWatcherObject(5, registry.getString()), cutName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,10 +93,10 @@ public class DataWatcherHelper {
|
||||
* @param visible - if visible or not
|
||||
*/
|
||||
public void setCustomNameVisible(boolean visible) {
|
||||
if (NMSStorage.getInstance().minorVersion >= 9) {
|
||||
data.setValue(new DataWatcherObject(3, registry.Boolean), visible);
|
||||
if (NMSStorage.getInstance().getMinorVersion() >= 9) {
|
||||
data.setValue(new DataWatcherObject(3, registry.getBoolean()), visible);
|
||||
} else {
|
||||
data.setValue(new DataWatcherObject(3, registry.Byte), (byte)(visible?1:0));
|
||||
data.setValue(new DataWatcherObject(3, registry.getByte()), (byte)(visible?1:0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,10 +105,10 @@ public class DataWatcherHelper {
|
||||
* @param health - health of entity
|
||||
*/
|
||||
public void setHealth(float health) {
|
||||
if (NMSStorage.getInstance().minorVersion >= 6) {
|
||||
data.setValue(new DataWatcherObject(6, registry.Float), health);
|
||||
if (NMSStorage.getInstance().getMinorVersion() >= 6) {
|
||||
data.setValue(new DataWatcherObject(6, registry.getFloat()), health);
|
||||
} else {
|
||||
data.setValue(new DataWatcherObject(16, registry.Integer), (int)health);
|
||||
data.setValue(new DataWatcherObject(16, registry.getInteger()), (int)health);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,6 +117,6 @@ public class DataWatcherHelper {
|
||||
* @param flags - flags to write
|
||||
*/
|
||||
public void setArmorStandFlags(byte flags) {
|
||||
data.setValue(new DataWatcherObject(ARMOR_STAND_BYTEFLAGS_POSITION, registry.Byte), flags);
|
||||
data.setValue(new DataWatcherObject(armorStandFlagsPosition, registry.getByte()), flags);
|
||||
}
|
||||
}
|
||||
+16
-8
@@ -5,10 +5,10 @@ import me.neznamy.tab.platforms.bukkit.nms.NMSStorage;
|
||||
public class DataWatcherItem {
|
||||
|
||||
//type of value (position + data type (1.9+))
|
||||
public DataWatcherObject type;
|
||||
private DataWatcherObject type;
|
||||
|
||||
//actual data value
|
||||
public Object value;
|
||||
private Object value;
|
||||
|
||||
/**
|
||||
* Constructs new instance of the object with given parameters
|
||||
@@ -24,15 +24,23 @@ public class DataWatcherItem {
|
||||
* Returns and instance of this class from given NMS item
|
||||
* @param nmsItem - NMS item
|
||||
* @return instance of this class with same data
|
||||
* @throws Exception - if something fails
|
||||
* @throws IllegalAccessException
|
||||
*/
|
||||
public static DataWatcherItem fromNMS(Object nmsItem) throws Exception {
|
||||
public static DataWatcherItem fromNMS(Object nmsItem) throws IllegalAccessException {
|
||||
NMSStorage nms = NMSStorage.getInstance();
|
||||
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));
|
||||
if (NMSStorage.getInstance().getMinorVersion() >= 9) {
|
||||
Object nmsObject = nms.getField("DataWatcherItem_TYPE").get(nmsItem);
|
||||
return new DataWatcherItem(new DataWatcherObject(nms.getField("DataWatcherObject_SLOT").getInt(nmsObject), nms.getField("DataWatcherObject_SERIALIZER").get(nmsObject)), nms.getField("DataWatcherItem_VALUE").get(nmsItem));
|
||||
} else {
|
||||
return new DataWatcherItem(new DataWatcherObject(nms.DataWatcherItem_TYPE.getInt(nmsItem), null), nms.DataWatcherItem_VALUE.get(nmsItem));
|
||||
return new DataWatcherItem(new DataWatcherObject(nms.getField("DataWatcherItem_TYPE").getInt(nmsItem), null), nms.getField("DataWatcherItem_VALUE").get(nmsItem));
|
||||
}
|
||||
}
|
||||
|
||||
public DataWatcherObject getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
+10
-2
@@ -6,10 +6,10 @@ package me.neznamy.tab.platforms.bukkit.nms.datawatcher;
|
||||
public class DataWatcherObject {
|
||||
|
||||
//position in datawatcher
|
||||
public int position;
|
||||
private int position;
|
||||
|
||||
//value class type used since 1.9
|
||||
public Object classType;
|
||||
private Object classType;
|
||||
|
||||
/**
|
||||
* Constructs a new instance of this class with given parameters
|
||||
@@ -20,4 +20,12 @@ public class DataWatcherObject {
|
||||
this.position = position;
|
||||
this.classType = classType;
|
||||
}
|
||||
|
||||
public int getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public Object getClassType() {
|
||||
return classType;
|
||||
}
|
||||
}
|
||||
+41
-18
@@ -13,28 +13,28 @@ import me.neznamy.tab.platforms.bukkit.nms.NMSStorage;
|
||||
public class DataWatcherRegistry {
|
||||
|
||||
//used registry types
|
||||
public Object Byte;
|
||||
public Object Integer;
|
||||
public Object Float;
|
||||
public Object String;
|
||||
public Object Optional_IChatBaseComponent;
|
||||
public Object Boolean;
|
||||
private Object registryByte;
|
||||
private Object registryInteger;
|
||||
private Object registryFloat;
|
||||
private Object registryString;
|
||||
private Object registryOptionalComponent;
|
||||
private Object registryBoolean;
|
||||
|
||||
/**
|
||||
* Initializes required NMS classes and fields
|
||||
*/
|
||||
public DataWatcherRegistry(NMSStorage nms, Class<?> registry) {
|
||||
if (nms.minorVersion >= 9) {
|
||||
if (nms.getMinorVersion() >= 9) {
|
||||
Map<String, Object> fields = getStaticFields(registry);
|
||||
Byte = fields.get("a");
|
||||
Integer = fields.get("b");
|
||||
Float = fields.get("c");
|
||||
String = fields.get("d");
|
||||
if (nms.minorVersion >= 13) {
|
||||
Optional_IChatBaseComponent = fields.get("f");
|
||||
Boolean = fields.get("i");
|
||||
registryByte = fields.get("a");
|
||||
registryInteger = fields.get("b");
|
||||
registryFloat = fields.get("c");
|
||||
registryString = fields.get("d");
|
||||
if (nms.getMinorVersion() >= 13) {
|
||||
registryOptionalComponent = fields.get("f");
|
||||
registryBoolean = fields.get("i");
|
||||
} else {
|
||||
Boolean = fields.get("h");
|
||||
registryBoolean = fields.get("h");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,18 +45,41 @@ public class DataWatcherRegistry {
|
||||
* @return map of values
|
||||
*/
|
||||
private Map<String, Object> getStaticFields(Class<?> clazz){
|
||||
Map<String, Object> fields = new HashMap<String, Object>();
|
||||
Map<String, Object> fields = new HashMap<>();
|
||||
if (clazz == null) return fields;
|
||||
for (Field field : clazz.getDeclaredFields()) {
|
||||
field.setAccessible(true);
|
||||
if (Modifier.isStatic(field.getModifiers())) {
|
||||
try {
|
||||
fields.put(field.getName(), field.get(null));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
//this will never happen
|
||||
}
|
||||
}
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
|
||||
public Object getBoolean() {
|
||||
return registryBoolean;
|
||||
}
|
||||
|
||||
public Object getByte() {
|
||||
return registryByte;
|
||||
}
|
||||
|
||||
public Object getFloat() {
|
||||
return registryFloat;
|
||||
}
|
||||
|
||||
public Object getInteger() {
|
||||
return registryInteger;
|
||||
}
|
||||
|
||||
public Object getString() {
|
||||
return registryString;
|
||||
}
|
||||
|
||||
public Object getOptionalComponent() {
|
||||
return registryOptionalComponent;
|
||||
}
|
||||
}
|
||||
@@ -177,7 +177,7 @@ disable-features-in-worlds:
|
||||
- disabledworld
|
||||
|
||||
placeholderapi-refresh-intervals:
|
||||
default-refresh-interval: 100
|
||||
default-refresh-interval: 500
|
||||
server:
|
||||
"%server_uptime%": 1000
|
||||
"%server_tps_1_colored%": 1000
|
||||
@@ -244,4 +244,7 @@ invisible-nametags: false
|
||||
#faking ping of players
|
||||
ping-spoof:
|
||||
enabled: false
|
||||
value: 0
|
||||
value: 0
|
||||
|
||||
#unlocks extra console messages
|
||||
debug: false
|
||||
@@ -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, ProtocolSupport]
|
||||
softdepend: [PlaceholderAPI, Vault, UltraPermissions, LuckPerms, Essentials, LibsDisguises, ProtocolSupport, ViaVersion]
|
||||
website: "https://www.spigotmc.org/resources/57806/"
|
||||
description: ${project.parent.description}
|
||||
commands:
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>me.neznamy</groupId>
|
||||
<artifactId>TAB</artifactId>
|
||||
<version>2.9.0</version>
|
||||
<version>2.9.2</version>
|
||||
</parent>
|
||||
<artifactId>bungeecord</artifactId>
|
||||
|
||||
|
||||
+10
-3
@@ -1,6 +1,7 @@
|
||||
package me.neznamy.tab.platforms.bungeecord;
|
||||
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.features.PluginMessageHandler;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.event.ChatEvent;
|
||||
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
|
||||
@@ -14,6 +15,12 @@ import net.md_5.bungee.event.EventPriority;
|
||||
*/
|
||||
public class BungeeEventListener implements Listener {
|
||||
|
||||
private PluginMessageHandler plm;
|
||||
|
||||
public BungeeEventListener(PluginMessageHandler plm) {
|
||||
this.plm = plm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect event listener to forward the event to all features
|
||||
* @param e - disconnect event
|
||||
@@ -32,12 +39,12 @@ public class BungeeEventListener implements Listener {
|
||||
public void onSwitch(ServerSwitchEvent e){
|
||||
if (TAB.getInstance().isDisabled()) return;
|
||||
try {
|
||||
if (!TAB.getInstance().data.containsKey(e.getPlayer().getUniqueId())) {
|
||||
TAB.getInstance().getFeatureManager().onJoin(new BungeeTabPlayer(e.getPlayer()));
|
||||
if (TAB.getInstance().getPlayer(e.getPlayer().getUniqueId()) == null) {
|
||||
TAB.getInstance().getFeatureManager().onJoin(new BungeeTabPlayer(e.getPlayer(), plm));
|
||||
} else {
|
||||
TAB.getInstance().getFeatureManager().onWorldChange(e.getPlayer().getUniqueId(), e.getPlayer().getServer().getInfo().getName());
|
||||
}
|
||||
} catch (Throwable ex){
|
||||
} catch (Exception ex){
|
||||
TAB.getInstance().getErrorManager().criticalError("An error occurred when player joined/changed server", ex);
|
||||
}
|
||||
}
|
||||
|
||||
+29
-29
@@ -38,85 +38,85 @@ public class BungeePacketBuilder implements PacketBuilder {
|
||||
@Override
|
||||
public Object build(PacketPlayOutBoss packet, ProtocolVersion clientVersion) {
|
||||
if (clientVersion.getMinorVersion() < 9) return null;
|
||||
BossBar bungeePacket = new BossBar(packet.id, packet.operation.ordinal());
|
||||
bungeePacket.setHealth(packet.pct);
|
||||
bungeePacket.setTitle(packet.name == null ? null : IChatBaseComponent.optimizedComponent(packet.name).toString(clientVersion));
|
||||
bungeePacket.setColor(packet.color == null ? 0 : packet.color.ordinal());
|
||||
bungeePacket.setDivision(packet.overlay == null ? 0: packet.overlay.ordinal());
|
||||
BossBar bungeePacket = new BossBar(packet.getId(), packet.getOperation().ordinal());
|
||||
bungeePacket.setHealth(packet.getPct());
|
||||
bungeePacket.setTitle(packet.getName() == null ? null : IChatBaseComponent.optimizedComponent(packet.getName()).toString(clientVersion));
|
||||
bungeePacket.setColor(packet.getColor() == null ? 0 : packet.getColor().ordinal());
|
||||
bungeePacket.setDivision(packet.getOverlay() == null ? 0: packet.getOverlay().ordinal());
|
||||
bungeePacket.setFlags(packet.getFlags());
|
||||
return bungeePacket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object build(PacketPlayOutChat packet, ProtocolVersion clientVersion) {
|
||||
return new Chat(packet.message.toString(clientVersion), (byte) packet.type.ordinal());
|
||||
return new Chat(packet.getMessage().toString(clientVersion), (byte) packet.getType().ordinal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object build(PacketPlayOutPlayerInfo packet, ProtocolVersion clientVersion) {
|
||||
List<Item> items = new ArrayList<Item>();
|
||||
for (PlayerInfoData data : packet.entries) {
|
||||
List<Item> items = new ArrayList<>();
|
||||
for (PlayerInfoData data : packet.getEntries()) {
|
||||
Item item = new Item();
|
||||
if (data.displayName != null) {
|
||||
if (clientVersion.getNetworkId() >= ProtocolVersion.v1_8.getNetworkId()) {
|
||||
item.setDisplayName(data.displayName.toString(clientVersion));
|
||||
if (data.getDisplayName() != null) {
|
||||
if (clientVersion.getMinorVersion() >= 8) {
|
||||
item.setDisplayName(data.getDisplayName().toString(clientVersion));
|
||||
} else {
|
||||
item.setDisplayName(data.displayName.toLegacyText());
|
||||
item.setDisplayName(data.getDisplayName().toLegacyText());
|
||||
}
|
||||
} else if (clientVersion.getNetworkId() < ProtocolVersion.v1_8.getNetworkId()) {
|
||||
item.setDisplayName(data.name); //avoiding NPE, 1.7 client requires this, 1.8 added a leading boolean
|
||||
} else if (clientVersion.getMinorVersion() < 8) {
|
||||
item.setDisplayName(data.getName()); //avoiding NPE, 1.7 client requires this, 1.8 added a leading boolean
|
||||
}
|
||||
if (data.gameMode != null) item.setGamemode(data.gameMode.ordinal()-1);
|
||||
item.setPing(data.latency);
|
||||
if (data.skin != null) {
|
||||
item.setProperties((String[][]) data.skin);
|
||||
if (data.getGameMode() != null) item.setGamemode(data.getGameMode().ordinal()-1);
|
||||
item.setPing(data.getLatency());
|
||||
if (data.getSkin() != null) {
|
||||
item.setProperties((String[][]) data.getSkin());
|
||||
} else {
|
||||
item.setProperties(new String[0][0]);
|
||||
}
|
||||
item.setUsername(data.name);
|
||||
item.setUuid(data.uniqueId);
|
||||
item.setUsername(data.getName());
|
||||
item.setUuid(data.getUniqueId());
|
||||
items.add(item);
|
||||
}
|
||||
PlayerListItem bungeePacket = new PlayerListItem();
|
||||
bungeePacket.setAction(PlayerListItem.Action.valueOf(packet.action.toString().replace("GAME_MODE", "GAMEMODE")));
|
||||
bungeePacket.setAction(PlayerListItem.Action.valueOf(packet.getAction().toString().replace("GAME_MODE", "GAMEMODE")));
|
||||
bungeePacket.setItems(items.toArray(new Item[0]));
|
||||
return bungeePacket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object build(PacketPlayOutPlayerListHeaderFooter packet, ProtocolVersion clientVersion) {
|
||||
return new PlayerListHeaderFooter(packet.header.toString(clientVersion, true), packet.footer.toString(clientVersion, true));
|
||||
return new PlayerListHeaderFooter(packet.getHeader().toString(clientVersion, true), packet.getFooter().toString(clientVersion, true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object build(PacketPlayOutScoreboardDisplayObjective packet, ProtocolVersion clientVersion) {
|
||||
return new ScoreboardDisplay((byte)packet.slot, packet.objectiveName);
|
||||
return new ScoreboardDisplay((byte)packet.getSlot(), packet.getObjectiveName());
|
||||
}
|
||||
|
||||
@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 new ScoreboardObjective(packet.getObjectiveName(), jsonOrCut(packet.getDisplayName(), clientVersion, 32), packet.getRenderType() == null ? null : HealthDisplay.valueOf(packet.getRenderType().toString()), (byte)packet.getMethod());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object build(PacketPlayOutScoreboardScore packet, ProtocolVersion clientVersion) {
|
||||
return new ScoreboardScore(packet.player, (byte) packet.action.ordinal(), packet.objectiveName, packet.score);
|
||||
return new ScoreboardScore(packet.getPlayer(), (byte) packet.getAction().ordinal(), packet.getObjectiveName(), packet.getScore());
|
||||
}
|
||||
|
||||
@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();
|
||||
color = (packet.getColor() != null ? packet.getColor() : EnumChatFormat.lastColorsOf(packet.getPlayerPrefix())).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 new Team(packet.getName(), (byte)packet.getMethod(), jsonOrCut(packet.getName(), clientVersion, 16), jsonOrCut(packet.getPlayerPrefix(), clientVersion, 16), jsonOrCut(packet.getPlayerSuffix(), clientVersion, 16),
|
||||
packet.getNametagVisibility(), packet.getCollisionRule(), color, (byte)packet.getOptions(), packet.getPlayers().toArray(new String[0]));
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketPlayOutPlayerInfo readPlayerInfo(Object bungeePacket, ProtocolVersion clientVersion) {
|
||||
PlayerListItem item = (PlayerListItem) bungeePacket;
|
||||
List<PlayerInfoData> listData = new ArrayList<PlayerInfoData>();
|
||||
List<PlayerInfoData> listData = new ArrayList<>();
|
||||
for (Item i : item.getItems()) {
|
||||
listData.add(new PlayerInfoData(i.getUsername(), i.getUuid(), i.getProperties(), i.getPing(), EnumGamemode.values()[i.getGamemode()+1], IChatBaseComponent.fromString(i.getDisplayName())));
|
||||
}
|
||||
|
||||
+49
-63
@@ -1,7 +1,11 @@
|
||||
package me.neznamy.tab.platforms.bungeecord;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
@@ -15,6 +19,7 @@ import me.neznamy.tab.shared.cpu.TabFeature;
|
||||
import me.neznamy.tab.shared.cpu.UsageType;
|
||||
import me.neznamy.tab.shared.features.PipelineInjector;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.protocol.DefinedPacket;
|
||||
import net.md_5.bungee.protocol.packet.Login;
|
||||
import net.md_5.bungee.protocol.packet.PlayerListItem;
|
||||
import net.md_5.bungee.protocol.packet.ScoreboardDisplay;
|
||||
@@ -24,7 +29,10 @@ import net.md_5.bungee.protocol.packet.Team;
|
||||
public class BungeePipelineInjector extends PipelineInjector {
|
||||
|
||||
//handler to inject before
|
||||
private final String INJECT_POSITION = "inbound-boss";
|
||||
private static final String INJECT_POSITION = "inbound-boss";
|
||||
|
||||
//packets that must be deserialized and bungeecord does not do it automatically
|
||||
private Map<Class<? extends DefinedPacket>, Supplier<DefinedPacket>> extraPackets = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameter
|
||||
@@ -32,6 +40,9 @@ public class BungeePipelineInjector extends PipelineInjector {
|
||||
*/
|
||||
public BungeePipelineInjector(TAB tab) {
|
||||
super(tab);
|
||||
extraPackets.put(Team.class, Team::new);
|
||||
extraPackets.put(ScoreboardDisplay.class, ScoreboardDisplay::new);
|
||||
extraPackets.put(ScoreboardObjective.class, ScoreboardObjective::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -50,25 +61,6 @@ public class BungeePipelineInjector extends PipelineInjector {
|
||||
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){
|
||||
long time = System.nanoTime();
|
||||
if (packet.getPlayers() == null) return;
|
||||
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]));
|
||||
tab.getCPUManager().addTime(TabFeature.NAMETAGS, UsageType.ANTI_OVERRIDE, System.nanoTime()-time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom channel duplex handler override
|
||||
@@ -87,39 +79,20 @@ public class BungeePipelineInjector extends PipelineInjector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ChannelHandlerContext context, Object packet, ChannelPromise channelPromise) throws Exception {
|
||||
public void write(ChannelHandlerContext context, Object packet, ChannelPromise channelPromise) {
|
||||
long time = System.nanoTime();
|
||||
Object modifiedPacket = packet instanceof ByteBuf ? deserialize((ByteBuf) packet) : packet;
|
||||
tab.getCPUManager().addTime(TabFeature.PACKET_DESERIALIZING, UsageType.PACKET_READING_OUT, System.nanoTime()-time);
|
||||
try {
|
||||
if (packet instanceof PlayerListItem) {
|
||||
super.write(context, tab.getFeatureManager().onPacketPlayOutPlayerInfo(player, packet), channelPromise);
|
||||
if (modifiedPacket instanceof PlayerListItem) {
|
||||
super.write(context, tab.getFeatureManager().onPacketPlayOutPlayerInfo(player, modifiedPacket), channelPromise);
|
||||
return;
|
||||
}
|
||||
Object modifiedPacket = packet;
|
||||
long time = System.nanoTime();
|
||||
if (packet instanceof ByteBuf) {
|
||||
modifiedPacket = deserialize((ByteBuf) packet);
|
||||
}
|
||||
tab.getCPUManager().addTime(TabFeature.PACKET_DESERIALIZING, UsageType.PACKET_READING_OUT, System.nanoTime()-time);
|
||||
if (tab.getFeatureManager().isFeatureEnabled("nametag16") && antiOverrideTeams) {
|
||||
time = System.nanoTime();
|
||||
if (modifiedPacket instanceof Team) {
|
||||
modifyPlayers((Team) modifiedPacket);
|
||||
tab.getCPUManager().addTime(TabFeature.NAMETAGS, UsageType.ANTI_OVERRIDE, System.nanoTime()-time);
|
||||
super.write(context, modifiedPacket, channelPromise);
|
||||
return;
|
||||
}
|
||||
//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 + 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);
|
||||
return;
|
||||
}
|
||||
buf.readerIndex(marker);
|
||||
}*/
|
||||
tab.getCPUManager().addTime(TabFeature.NAMETAGS, UsageType.ANTI_OVERRIDE, System.nanoTime()-time);
|
||||
}
|
||||
if (modifiedPacket instanceof ScoreboardDisplay && antiOverrideObjectives && tab.getFeatureManager().onDisplayObjective(player, modifiedPacket)) {
|
||||
@@ -138,7 +111,30 @@ public class BungeePipelineInjector extends PipelineInjector {
|
||||
} catch (Throwable e){
|
||||
tab.getErrorManager().printError("An error occurred when analyzing packets for player " + player.getName() + " with client version " + player.getVersion().getFriendlyName(), e);
|
||||
}
|
||||
super.write(context, packet, channelPromise);
|
||||
try {
|
||||
super.write(context, modifiedPacket, channelPromise);
|
||||
} catch (Throwable e) {
|
||||
tab.getErrorManager().printError("Failed to forward packet " + modifiedPacket.getClass().getSimpleName() + " to " + player.getName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all real players from packet if the packet doesn't come from TAB
|
||||
* @param packet - packet to modify
|
||||
*/
|
||||
private void modifyPlayers(Team packet){
|
||||
long time = System.nanoTime();
|
||||
if (packet.getPlayers() == null) return;
|
||||
Collection<String> col = Lists.newArrayList(packet.getPlayers());
|
||||
for (TabPlayer p : tab.getPlayers()) {
|
||||
if (col.contains(p.getName()) && !tab.getFeatureManager().getNameTagFeature().getPlayersInDisabledWorlds().contains(p) &&
|
||||
!p.hasTeamHandlingPaused() && !packet.getName().equals(p.getTeamName())) {
|
||||
logTeamOverride(packet.getName(), p.getName());
|
||||
col.remove(p.getName());
|
||||
}
|
||||
}
|
||||
packet.setPlayers(col.toArray(new String[0]));
|
||||
tab.getCPUManager().addTime(TabFeature.NAMETAGS, UsageType.ANTI_OVERRIDE, System.nanoTime()-time);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,23 +146,13 @@ public class BungeePipelineInjector extends PipelineInjector {
|
||||
private Object deserialize(ByteBuf buf) {
|
||||
int marker = buf.readerIndex();
|
||||
int packetId = buf.readByte();
|
||||
if (packetId == ((BungeeTabPlayer)player).getPacketId(Team.class)) {
|
||||
Team team = new Team();
|
||||
team.read(buf, null, ((ProxiedPlayer)player.getPlayer()).getPendingConnection().getVersion());
|
||||
buf.release();
|
||||
return team;
|
||||
}
|
||||
if (packetId == ((BungeeTabPlayer)player).getPacketId(ScoreboardDisplay.class)) {
|
||||
ScoreboardDisplay display = new ScoreboardDisplay();
|
||||
display.read(buf, null, ((ProxiedPlayer)player.getPlayer()).getPendingConnection().getVersion());
|
||||
buf.release();
|
||||
return display;
|
||||
}
|
||||
if (packetId == ((BungeeTabPlayer)player).getPacketId(ScoreboardObjective.class)) {
|
||||
ScoreboardObjective objective = new ScoreboardObjective();
|
||||
objective.read(buf, null, ((ProxiedPlayer)player.getPlayer()).getPendingConnection().getVersion());
|
||||
buf.release();
|
||||
return objective;
|
||||
for (Entry<Class<? extends DefinedPacket>, Supplier<DefinedPacket>> e : extraPackets.entrySet()) {
|
||||
if (packetId == ((BungeeTabPlayer)player).getPacketId(e.getKey())) {
|
||||
DefinedPacket packet = e.getValue().get();
|
||||
packet.read(buf, null, ((ProxiedPlayer)player.getPlayer()).getPendingConnection().getVersion());
|
||||
buf.release();
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
buf.readerIndex(marker);
|
||||
return buf;
|
||||
|
||||
+3
-22
@@ -1,15 +1,14 @@
|
||||
package me.neznamy.tab.platforms.bungeecord;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
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;
|
||||
import me.neznamy.tab.shared.proxy.ProxyPlaceholderRegistry;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.config.ServerInfo;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
@@ -17,29 +16,11 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
/**
|
||||
* Bungeecord registry to register bungeecord-only placeholders
|
||||
*/
|
||||
public class BungeePlaceholderRegistry implements PlaceholderRegistry {
|
||||
public class BungeePlaceholderRegistry extends ProxyPlaceholderRegistry {
|
||||
|
||||
@Override
|
||||
public List<Placeholder> registerPlaceholders() {
|
||||
List<Placeholder> placeholders = new ArrayList<Placeholder>();
|
||||
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);
|
||||
}
|
||||
});
|
||||
List<Placeholder> placeholders = super.registerPlaceholders();
|
||||
placeholders.add(new PlayerPlaceholder("%displayname%", 500) {
|
||||
public String get(TabPlayer p) {
|
||||
return ((ProxiedPlayer) p.getPlayer()).getDisplayName();
|
||||
|
||||
@@ -2,15 +2,13 @@ package me.neznamy.tab.platforms.bungeecord;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
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.PluginMessageHandler;
|
||||
import me.neznamy.tab.shared.features.SpectatorFix;
|
||||
import me.neznamy.tab.shared.features.TabObjective;
|
||||
import me.neznamy.tab.shared.features.scoreboard.ScoreboardManager;
|
||||
@@ -18,8 +16,8 @@ import me.neznamy.tab.shared.permission.LuckPerms;
|
||||
import me.neznamy.tab.shared.permission.PermissionPlugin;
|
||||
import me.neznamy.tab.shared.permission.UltraPermissions;
|
||||
import me.neznamy.tab.shared.permission.VaultBridge;
|
||||
import me.neznamy.tab.shared.placeholders.PlayerPlaceholder;
|
||||
import me.neznamy.tab.shared.placeholders.UniversalPlaceholderRegistry;
|
||||
import me.neznamy.tab.shared.proxy.ProxyPlatform;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
@@ -27,7 +25,7 @@ import net.md_5.bungee.api.plugin.Plugin;
|
||||
/**
|
||||
* Bungeecord implementation of Platform
|
||||
*/
|
||||
public class BungeePlatform implements Platform {
|
||||
public class BungeePlatform extends ProxyPlatform {
|
||||
|
||||
//instance of plugin
|
||||
private Plugin plugin;
|
||||
@@ -36,40 +34,41 @@ public class BungeePlatform implements Platform {
|
||||
* Constructs new instance with given parameter
|
||||
* @param plugin - main class
|
||||
*/
|
||||
public BungeePlatform(Plugin plugin) {
|
||||
public BungeePlatform(Plugin plugin, PluginMessageHandler plm) {
|
||||
super(plm);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionPlugin detectPermissionPlugin() {
|
||||
if (TAB.getInstance().getConfiguration().bukkitPermissions) {
|
||||
return new VaultBridge(Main.plm);
|
||||
if (TAB.getInstance().getConfiguration().isBukkitPermissions()) {
|
||||
return new VaultBridge(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());
|
||||
} else {
|
||||
return new VaultBridge(Main.plm);
|
||||
return new VaultBridge(plm);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadFeatures() throws Exception{
|
||||
public void loadFeatures() throws IllegalAccessException {
|
||||
TAB tab = TAB.getInstance();
|
||||
tab.getPlaceholderManager().addRegistry(new BungeePlaceholderRegistry());
|
||||
tab.getPlaceholderManager().addRegistry(new UniversalPlaceholderRegistry());
|
||||
tab.getPlaceholderManager().registerPlaceholders();
|
||||
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));
|
||||
if (tab.getConfiguration().isPipelineInjection()) tab.getFeatureManager().registerFeature("injection", new BungeePipelineInjector(tab));
|
||||
if (tab.getConfiguration().getConfig().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));
|
||||
if (tab.getConfiguration().getConfig().getBoolean("ping-spoof.enabled", false)) tab.getFeatureManager().registerFeature("pingspoof", new PingSpoof());
|
||||
if (tab.getConfiguration().getConfig().getString("yellow-number-in-tablist", "%ping%").length() > 0) tab.getFeatureManager().registerFeature("tabobjective", new TabObjective(tab));
|
||||
if (tab.getConfiguration().getConfig().getBoolean("do-not-move-spectators", false)) tab.getFeatureManager().registerFeature("spectatorfix", new SpectatorFix());
|
||||
if (tab.getConfiguration().getConfig().getBoolean("classic-vanilla-belowname.enabled", true)) tab.getFeatureManager().registerFeature("belowname", new BelowName(tab));
|
||||
if (tab.getConfiguration().getPremiumConfig() != null && tab.getConfiguration().getPremiumConfig().getBoolean("scoreboard.enabled", false)) tab.getFeatureManager().registerFeature("scoreboard", new ScoreboardManager(tab));
|
||||
if (tab.getConfiguration().getConfig().getBoolean("global-playerlist.enabled", false)) tab.getFeatureManager().registerFeature("globalplayerlist", new GlobalPlayerlist(tab));
|
||||
for (ProxiedPlayer p : ProxyServer.getInstance().getPlayers()) {
|
||||
tab.addPlayer(new BungeeTabPlayer(p));
|
||||
tab.addPlayer(new BungeeTabPlayer(p, plm));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,27 +78,6 @@ public class BungeePlatform implements Platform {
|
||||
ProxyServer.getInstance().getConsole().sendMessage(translateColors ? message.replace('&', '\u00a7') : message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerUnknownPlaceholder(String identifier) {
|
||||
if (identifier.startsWith("%rel_")) return;
|
||||
if (identifier.contains("_")) {
|
||||
String plugin = identifier.split("_")[0].replace("%", "").toLowerCase();
|
||||
if (plugin.equals("some")) return;
|
||||
TAB.getInstance().debug("Detected used PlaceholderAPI placeholder " + identifier);
|
||||
PlaceholderManager pl = TAB.getInstance().getPlaceholderManager();
|
||||
int refresh = pl.defaultRefresh;
|
||||
if (pl.playerPlaceholderRefreshIntervals.containsKey(identifier)) refresh = pl.playerPlaceholderRefreshIntervals.get(identifier);
|
||||
if (pl.serverPlaceholderRefreshIntervals.containsKey(identifier)) refresh = pl.serverPlaceholderRefreshIntervals.get(identifier);
|
||||
TAB.getInstance().getPlaceholderManager().registerPlaceholder(new PlayerPlaceholder(identifier, TAB.getInstance().getErrorManager().fixPlaceholderInterval(identifier, refresh)){
|
||||
public String get(TabPlayer p) {
|
||||
Main.plm.requestPlaceholder(p, identifier);
|
||||
return lastValue.get(p.getName());
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerVersion() {
|
||||
return ProxyServer.getInstance().getVersion();
|
||||
|
||||
@@ -4,9 +4,10 @@ import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
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 me.neznamy.tab.shared.features.PluginMessageHandler;
|
||||
import me.neznamy.tab.shared.proxy.ProxyTabPlayer;
|
||||
import net.md_5.bungee.UserConnection;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
@@ -19,7 +20,7 @@ import net.md_5.bungee.protocol.Protocol;
|
||||
/**
|
||||
* TabPlayer for BungeeCord
|
||||
*/
|
||||
public class BungeeTabPlayer extends ITabPlayer {
|
||||
public class BungeeTabPlayer extends ProxyTabPlayer {
|
||||
|
||||
//bungee internals to get player channel
|
||||
private static Field wrapperField;
|
||||
@@ -36,7 +37,8 @@ public class BungeeTabPlayer extends ITabPlayer {
|
||||
directionData = f.get(Protocol.GAME);
|
||||
getId = directionData.getClass().getDeclaredMethod("getId", Class.class, int.class);
|
||||
getId.setAccessible(true);
|
||||
(wrapperField = InitialHandler.class.getDeclaredField("ch")).setAccessible(true);
|
||||
wrapperField = InitialHandler.class.getDeclaredField("ch");
|
||||
wrapperField.setAccessible(true);
|
||||
} catch (Exception e) {
|
||||
TAB.getInstance().getErrorManager().criticalError("Failed to initialize fields for packet analysis", e);
|
||||
}
|
||||
@@ -48,9 +50,10 @@ public class BungeeTabPlayer extends ITabPlayer {
|
||||
/**
|
||||
* Constructs new instance for given player
|
||||
* @param p - velocity player
|
||||
* @throws Exception - if reflection fails
|
||||
* @throws IllegalAccessException
|
||||
*/
|
||||
public BungeeTabPlayer(ProxiedPlayer p) throws Exception {
|
||||
public BungeeTabPlayer(ProxiedPlayer p, PluginMessageHandler plm) throws IllegalAccessException {
|
||||
super (plm);
|
||||
player = p;
|
||||
if (p.getServer() != null) {
|
||||
world = p.getServer().getInfo().getName();
|
||||
@@ -64,13 +67,7 @@ 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));
|
||||
}
|
||||
public boolean hasPermission0(String permission) {
|
||||
return player.hasPermission(permission);
|
||||
}
|
||||
|
||||
@@ -125,23 +122,7 @@ public class BungeeTabPlayer extends ITabPlayer {
|
||||
@Override
|
||||
public boolean isVanished() {
|
||||
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
|
||||
public boolean isDisguised() {
|
||||
Main.plm.requestAttribute(this, "disguised");
|
||||
if (!attributes.containsKey("disguised")) return false;
|
||||
return Boolean.parseBoolean(attributes.get("disguised"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasInvisibilityPotion() {
|
||||
Main.plm.requestAttribute(this, "invisible");
|
||||
if (!attributes.containsKey("invisible")) return false;
|
||||
return Boolean.parseBoolean(attributes.get("invisible"));
|
||||
return super.isVanished();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -21,9 +21,6 @@ import net.md_5.bungee.api.plugin.TabExecutor;
|
||||
*/
|
||||
public class Main extends Plugin {
|
||||
|
||||
//plugin message handler
|
||||
public static PluginMessageHandler plm;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void onEnable(){
|
||||
@@ -31,12 +28,11 @@ public class Main extends Plugin {
|
||||
ProxyServer.getInstance().getConsole().sendMessage("\u00a7c[TAB] The plugin requires BungeeCord build #1330 and up to work. Get it at https://ci.md-5.net/job/BungeeCord/");
|
||||
return;
|
||||
}
|
||||
ProtocolVersion.SERVER_VERSION = ProtocolVersion.values()[1];
|
||||
TAB.setInstance(new TAB(new BungeePlatform(this), new BungeePacketBuilder()));
|
||||
getProxy().getPluginManager().registerListener(this, new BungeeEventListener());
|
||||
PluginMessageHandler plm = new BungeePluginMessageHandler(this);
|
||||
TAB.setInstance(new TAB(new BungeePlatform(this, plm), new BungeePacketBuilder(), ProtocolVersion.values()[1]));
|
||||
getProxy().getPluginManager().registerListener(this, new BungeeEventListener(plm));
|
||||
if (getProxy().getPluginManager().getPlugin("PremiumVanish") != null) getProxy().getPluginManager().registerListener(this, new PremiumVanishListener());
|
||||
getProxy().getPluginManager().registerCommand(this, new BTABCommand());
|
||||
plm = new BungeePluginMessageHandler(this);
|
||||
TAB.getInstance().load();
|
||||
Metrics metrics = new Metrics(this, 10535);
|
||||
metrics.addCustomChart(new SimplePie("permission_system", () -> TAB.getInstance().getPermissionPlugin().getName()));
|
||||
@@ -61,7 +57,7 @@ public class Main extends Plugin {
|
||||
public void onDisable() {
|
||||
if (TAB.getInstance() != null) TAB.getInstance().unload();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* TAB command for bungeecord
|
||||
*/
|
||||
@@ -78,7 +74,7 @@ public class Main extends Plugin {
|
||||
@Override
|
||||
public void execute(CommandSender sender, String[] args) {
|
||||
if (TAB.getInstance().isDisabled()) {
|
||||
for (String message : TAB.getInstance().disabledCommand.execute(args, sender.hasPermission("tab.reload"), sender.hasPermission("tab.admin"))) {
|
||||
for (String message : TAB.getInstance().getDisabledCommand().execute(args, sender.hasPermission("tab.reload"), sender.hasPermission("tab.admin"))) {
|
||||
sender.sendMessage(message.replace('&', '\u00a7'));
|
||||
}
|
||||
} else {
|
||||
@@ -87,7 +83,7 @@ public class Main extends Plugin {
|
||||
p = TAB.getInstance().getPlayer(((ProxiedPlayer)sender).getUniqueId());
|
||||
if (p == null) return; //player not loaded correctly
|
||||
}
|
||||
TAB.getInstance().command.execute(p, args);
|
||||
TAB.getInstance().getCommand().execute(p, args);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,9 +92,9 @@ public class Main extends Plugin {
|
||||
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
|
||||
if (p == null) return new ArrayList<>(); //player not loaded correctly
|
||||
}
|
||||
return TAB.getInstance().command.complete(p, args);
|
||||
return TAB.getInstance().getCommand().complete(p, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -30,7 +30,7 @@ public class PremiumVanishListener implements Listener {
|
||||
for (TabPlayer all : TAB.getInstance().getPlayers()) {
|
||||
boolean perm = all.hasPermission("tab.seevanished");
|
||||
if (all == vanished || perm) {
|
||||
if (perm && list.vanishedAsSpectators) {
|
||||
if (perm && list.isVanishedAsSpectators()) {
|
||||
all.sendCustomPacket(new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.UPDATE_GAME_MODE, new PlayerInfoData(vanished.getUniqueId(), EnumGamemode.SPECTATOR)), TabFeature.GLOBAL_PLAYERLIST);
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -170,7 +170,7 @@ disable-features-in-servers:
|
||||
- disabledserver
|
||||
|
||||
placeholderapi-refresh-intervals:
|
||||
default-refresh-interval: 100
|
||||
default-refresh-interval: 500
|
||||
server:
|
||||
"%server_uptime%": 1000
|
||||
"%server_tps_1_colored%": 1000
|
||||
@@ -211,4 +211,7 @@ invisible-nametags: false
|
||||
#faking ping of players
|
||||
ping-spoof:
|
||||
enabled: false
|
||||
value: 0
|
||||
value: 0
|
||||
|
||||
#unlocks extra console messages
|
||||
debug: false
|
||||
+7
-6
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>me.neznamy</groupId>
|
||||
<artifactId>TAB</artifactId>
|
||||
<version>2.9.0</version>
|
||||
<version>2.9.2</version>
|
||||
</parent>
|
||||
<artifactId>jar</artifactId>
|
||||
<build>
|
||||
@@ -21,17 +21,18 @@
|
||||
<includes>
|
||||
<include>com.googlecode.json-simple:json-simple</include>
|
||||
<include>com.github.NEZNAMY:YamlAssist</include>
|
||||
<include>com.github.NEZNAMY:VelocityPacketInjector</include>
|
||||
<include>org.bstats:bstats-base</include>
|
||||
<include>org.bstats:bstats-bungeecord</include>
|
||||
<include>org.bstats:bstats-velocity</include>
|
||||
<include>org.bstats:*</include>
|
||||
<include>me.neznamy:*</include>
|
||||
</includes>
|
||||
</artifactSet>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>org.bstats</pattern>
|
||||
<shadedPattern>me.neznamy.tab.platforms</shadedPattern>
|
||||
<shadedPattern>me.neznamy.tab.libs.org.bstats</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.json.simple</pattern>
|
||||
<shadedPattern>me.neznamy.tab.libs.org.json.simple</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>me.neznamy</groupId>
|
||||
<artifactId>TAB</artifactId>
|
||||
<version>2.9.0</version>
|
||||
<version>2.9.2</version>
|
||||
<packaging>pom</packaging>
|
||||
<description>An all-in-one solution that works</description>
|
||||
<modules>
|
||||
@@ -19,6 +19,10 @@
|
||||
<project.build.outputEncoding>UTF-8</project.build.outputEncoding>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<sonar.projectKey>NEZNAMY_TAB</sonar.projectKey>
|
||||
<sonar.moduleKey>${project.artifactId}</sonar.moduleKey>
|
||||
<sonar.organization>neznamy</sonar.organization>
|
||||
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
|
||||
</properties>
|
||||
<build>
|
||||
<resources>
|
||||
|
||||
+2
-2
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>me.neznamy</groupId>
|
||||
<artifactId>TAB</artifactId>
|
||||
<version>2.9.0</version>
|
||||
<version>2.9.2</version>
|
||||
</parent>
|
||||
<artifactId>shared</artifactId>
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.16.5-R0.1-SNAPSHOT</version>
|
||||
<version>1.17-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
|
||||
@@ -58,7 +58,7 @@ public class ArmorStandManager {
|
||||
*/
|
||||
public void teleport() {
|
||||
synchronized (armorStands) {
|
||||
armorStands.values().forEach(a -> a.teleport());
|
||||
armorStands.values().forEach(ArmorStand::teleport);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ public class ArmorStandManager {
|
||||
*/
|
||||
public void refresh() {
|
||||
synchronized (armorStands) {
|
||||
armorStands.values().forEach(a -> a.refresh());
|
||||
armorStands.values().forEach(ArmorStand::refresh);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ public class ArmorStandManager {
|
||||
*/
|
||||
public void destroy() {
|
||||
synchronized (armorStands) {
|
||||
armorStands.values().forEach(a -> a.destroy());
|
||||
armorStands.values().forEach(ArmorStand::destroy);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ public class ArmorStandManager {
|
||||
* @return list of nearby players
|
||||
*/
|
||||
public Set<TabPlayer> getNearbyPlayers(){
|
||||
if (armorStands.values().size() == 0) return new HashSet<>(); //not initialized yet
|
||||
if (armorStands.isEmpty()) return new HashSet<>(); //not initialized yet
|
||||
synchronized (armorStands) {
|
||||
return armorStands.values().iterator().next().getNearbyPlayers();
|
||||
}
|
||||
|
||||
@@ -5,12 +5,15 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
import me.neznamy.tab.api.bossbar.BarColor;
|
||||
import me.neznamy.tab.api.bossbar.BarStyle;
|
||||
import me.neznamy.tab.api.bossbar.BossBar;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.features.PlaceholderManager;
|
||||
import me.neznamy.tab.shared.features.bossbar.BossBarLine;
|
||||
import me.neznamy.tab.shared.features.scoreboard.ScoreboardImpl;
|
||||
import me.neznamy.tab.shared.features.scoreboard.ScoreboardManager;
|
||||
import me.neznamy.tab.shared.permission.PermissionPlugin;
|
||||
import me.neznamy.tab.shared.placeholders.Placeholder;
|
||||
@@ -25,7 +28,10 @@ import me.neznamy.tab.shared.placeholders.conditions.simple.SimpleCondition;
|
||||
public class TABAPI {
|
||||
|
||||
//placeholders registered via API
|
||||
public static Map<String, Placeholder> APIPlaceholders = new HashMap<String, Placeholder>();
|
||||
private static final Map<String, Placeholder> apiPlaceholders = new HashMap<>();
|
||||
|
||||
private TABAPI() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns player object from given UUID
|
||||
@@ -60,8 +66,8 @@ public class TABAPI {
|
||||
*/
|
||||
public static void enableUnlimitedNameTagModePermanently() {
|
||||
if (isUnlimitedNameTagModeEnabled()) return;
|
||||
TAB.getInstance().getConfiguration().config.set("change-nametag-prefix-suffix", true);
|
||||
TAB.getInstance().getConfiguration().config.set("unlimited-nametag-prefix-suffix-mode.enabled", true);
|
||||
TAB.getInstance().getConfiguration().getConfig().set("change-nametag-prefix-suffix", true);
|
||||
TAB.getInstance().getConfiguration().getConfig().set("unlimited-nametag-prefix-suffix-mode.enabled", true);
|
||||
TAB.getInstance().unload();
|
||||
TAB.getInstance().load();
|
||||
}
|
||||
@@ -73,10 +79,11 @@ public class TABAPI {
|
||||
* @see registerServerConstant
|
||||
*/
|
||||
public static void registerPlayerPlaceholder(PlayerPlaceholder placeholder) {
|
||||
APIPlaceholders.put(placeholder.getIdentifier(), placeholder);
|
||||
Preconditions.checkNotNull(placeholder, "placeholder");
|
||||
apiPlaceholders.put(placeholder.getIdentifier(), placeholder);
|
||||
PlaceholderManager pl = TAB.getInstance().getPlaceholderManager();
|
||||
pl.registerPlaceholder(placeholder);
|
||||
pl.allUsedPlaceholderIdentifiers.add(placeholder.getIdentifier());
|
||||
pl.getAllUsedPlaceholderIdentifiers().add(placeholder.getIdentifier());
|
||||
pl.refreshPlaceholderUsage();
|
||||
}
|
||||
|
||||
@@ -87,10 +94,11 @@ public class TABAPI {
|
||||
* @see registerServerConstant
|
||||
*/
|
||||
public static void registerServerPlaceholder(ServerPlaceholder placeholder) {
|
||||
APIPlaceholders.put(placeholder.getIdentifier(), placeholder);
|
||||
Preconditions.checkNotNull(placeholder, "placeholder");
|
||||
apiPlaceholders.put(placeholder.getIdentifier(), placeholder);
|
||||
PlaceholderManager pl = TAB.getInstance().getPlaceholderManager();
|
||||
pl.registerPlaceholder(placeholder);
|
||||
pl.allUsedPlaceholderIdentifiers.add(placeholder.getIdentifier());
|
||||
pl.getAllUsedPlaceholderIdentifiers().add(placeholder.getIdentifier());
|
||||
pl.refreshPlaceholderUsage();
|
||||
}
|
||||
|
||||
@@ -99,10 +107,11 @@ public class TABAPI {
|
||||
* @param placeholder - Placeholder handler
|
||||
*/
|
||||
public static void registerRelationalPlaceholder(RelationalPlaceholder placeholder) {
|
||||
APIPlaceholders.put(placeholder.getIdentifier(), placeholder);
|
||||
Preconditions.checkNotNull(placeholder, "placeholder");
|
||||
apiPlaceholders.put(placeholder.getIdentifier(), placeholder);
|
||||
PlaceholderManager pl = TAB.getInstance().getPlaceholderManager();
|
||||
pl.registerPlaceholder(placeholder);
|
||||
pl.allUsedPlaceholderIdentifiers.add(placeholder.getIdentifier());
|
||||
pl.getAllUsedPlaceholderIdentifiers().add(placeholder.getIdentifier());
|
||||
pl.refreshPlaceholderUsage();
|
||||
}
|
||||
|
||||
@@ -119,8 +128,8 @@ public class TABAPI {
|
||||
}
|
||||
ScoreboardManager sbm = (ScoreboardManager) TAB.getInstance().getFeatureManager().getFeature("scoreboard");
|
||||
if (sbm == null) throw new IllegalStateException("Scoreboard feature is not enabled");
|
||||
Scoreboard sb = new me.neznamy.tab.shared.features.scoreboard.Scoreboard(sbm, name, title, lines);
|
||||
sbm.APIscoreboards.add(sb);
|
||||
Scoreboard sb = new ScoreboardImpl(sbm, name, title, lines);
|
||||
sbm.getApiScoreboards().add(sb);
|
||||
return sb;
|
||||
}
|
||||
|
||||
@@ -158,7 +167,7 @@ public class TABAPI {
|
||||
me.neznamy.tab.shared.features.bossbar.BossBar feature = (me.neznamy.tab.shared.features.bossbar.BossBar) TAB.getInstance().getFeatureManager().getFeature("bossbar");
|
||||
if (feature == null) throw new IllegalStateException("Bossbar feature is not enabled");
|
||||
BossBar bar = new BossBarLine(name, null, color, style, title, progress);
|
||||
feature.lines.put(bar.getName(), (BossBarLine) bar);
|
||||
feature.getLines().put(bar.getName(), (BossBarLine) bar);
|
||||
return bar;
|
||||
}
|
||||
|
||||
@@ -167,7 +176,7 @@ public class TABAPI {
|
||||
* @return placeholders registered via API
|
||||
*/
|
||||
public static Map<String, Placeholder> getAPIPlaceholders(){
|
||||
return APIPlaceholders;
|
||||
return apiPlaceholders;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -178,6 +187,6 @@ public class TABAPI {
|
||||
* @return true if it was registered, false if it already was registered before
|
||||
*/
|
||||
public static boolean registerSubCondition(String identifier, Class<? extends SimpleCondition> clazz) {
|
||||
return SimpleCondition.conditionTypes.put(identifier, clazz) == null;
|
||||
return SimpleCondition.getConditionTypes().put(identifier, clazz) == null;
|
||||
}
|
||||
}
|
||||
@@ -15,8 +15,8 @@ public class BukkitTABLoadEvent extends Event {
|
||||
public HandlerList getHandlers(){
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList(){
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package me.neznamy.tab.api.event;
|
||||
|
||||
/**
|
||||
* Velocity event that is called each time TAB fully loads. This includes server startup, reload,
|
||||
* /tab reload and /plugman reload tab
|
||||
*/
|
||||
public class VelocityTABLoadEvent {
|
||||
|
||||
}
|
||||
@@ -25,15 +25,15 @@ public class ErrorManager {
|
||||
private final SimpleDateFormat dateformat = new SimpleDateFormat("dd.MM.yyyy - HH:mm:ss - ");
|
||||
|
||||
//one time messages already sent into console so they are not sent again
|
||||
private Set<String> oneTimeMessages = new HashSet<String>();
|
||||
private Set<String> oneTimeMessages = new HashSet<>();
|
||||
|
||||
//amount of logged startup warns
|
||||
private int startupWarns = 0;
|
||||
|
||||
//error logs
|
||||
public File errorLog;
|
||||
public File papiErrorLog;
|
||||
public File antiOverrideLog;
|
||||
private File errorLog;
|
||||
private File papiErrorLog;
|
||||
private File antiOverrideLog;
|
||||
|
||||
//plugin instance
|
||||
private TAB tab;
|
||||
@@ -47,8 +47,8 @@ public class ErrorManager {
|
||||
errorLog = new File(tab.getPlatform().getDataFolder(), "errors.log");
|
||||
papiErrorLog = new File(tab.getPlatform().getDataFolder(), "PlaceholderAPI.errors.log");
|
||||
antiOverrideLog = new File(tab.getPlatform().getDataFolder(), "anti-override.log");
|
||||
if (errorLog.exists() && errorLog.length() > 10) {
|
||||
startupWarn("File &e" + errorLog.getPath() + "&c exists and is not empty. Take a look at the error messages and try to resolve them. After you do, delete the file.");
|
||||
if (getErrorLog().exists() && getErrorLog().length() > 10) {
|
||||
startupWarn("File &e" + getErrorLog().getPath() + "&c exists and is not empty. Take a look at the error messages and try to resolve them. After you do, delete the file.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ public class ErrorManager {
|
||||
* @param intoConsoleToo - if the message should be printed into console as well
|
||||
*/
|
||||
public void printError(String message, Throwable t, boolean intoConsoleToo) {
|
||||
printError(message, t, intoConsoleToo, errorLog);
|
||||
printError(message, t, intoConsoleToo, getErrorLog());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,22 +106,30 @@ public class ErrorManager {
|
||||
try {
|
||||
if (!createFile(file)) return;
|
||||
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.replace('\u00a7', '&'), intoConsoleToo);
|
||||
}
|
||||
if (error != null) {
|
||||
write(buf, "&c", error.getClass().getName() + ": " + error.getMessage(), intoConsoleToo);
|
||||
for (StackTraceElement ste : error.getStackTrace()) {
|
||||
write(buf, "&c at ", ste.toString(), intoConsoleToo);
|
||||
try (BufferedWriter buf = new BufferedWriter(new FileWriter(file, true))){
|
||||
if (message != null) {
|
||||
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);
|
||||
for (StackTraceElement ste : error.getStackTrace()) {
|
||||
write(buf, "&c at ", ste.toString(), intoConsoleToo);
|
||||
}
|
||||
}
|
||||
}
|
||||
buf.close();
|
||||
} catch (Throwable ex) {
|
||||
} catch (Exception ex) {
|
||||
tab.getPlatform().sendConsoleMessage("&c[TAB] An error occurred when printing error message into file", true);
|
||||
ex.printStackTrace();
|
||||
tab.getPlatform().sendConsoleMessage(ex.getClass().getName() + ": " + ex.getMessage(), true);
|
||||
for (StackTraceElement e : ex.getStackTrace()) {
|
||||
tab.getPlatform().sendConsoleMessage("\t" + e.toString(), true);
|
||||
}
|
||||
tab.getPlatform().sendConsoleMessage("&c[TAB] Original error: " + message, true);
|
||||
if (error != null) error.printStackTrace();
|
||||
if (error != null) {
|
||||
tab.getPlatform().sendConsoleMessage(error.getClass().getName() + ": " + error.getMessage(), true);
|
||||
for (StackTraceElement e : error.getStackTrace()) {
|
||||
tab.getPlatform().sendConsoleMessage("\t" + e.toString(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,8 +142,7 @@ public class ErrorManager {
|
||||
private boolean createFile(File file) {
|
||||
if (file.exists()) return true;
|
||||
try {
|
||||
file.createNewFile();
|
||||
return true;
|
||||
return file.createNewFile();
|
||||
} catch (IOException e) {
|
||||
tab.getPlatform().sendConsoleMessage("&c[TAB] Failed to create file " + file.getPath() + ": " + e.getMessage(), true);
|
||||
return false;
|
||||
@@ -151,7 +158,7 @@ public class ErrorManager {
|
||||
*/
|
||||
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);
|
||||
if (tab.isDebugMode() || forceConsole) tab.getPlatform().sendConsoleMessage(prefix.replace('&', '\u00a7') + message, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -221,12 +228,8 @@ public class ErrorManager {
|
||||
if (string == null || string.length() == 0) return 0; //preventing error message on bungee with papi placeholders due to them not being initialized yet
|
||||
try {
|
||||
return (int) Math.round(Double.parseDouble(string));
|
||||
} catch (Throwable e) {
|
||||
if (string.contains("%")) {
|
||||
return oneTimeConsoleError(defaultValue, "Value \"" + string + "\" used in " + place + " still has unparsed placeholders! Did you forget to download an expansion ?");
|
||||
} else {
|
||||
return oneTimeConsoleError(defaultValue, place + " only accepts numeric values! (Attempted to use \"" + string + "\")");
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
return oneTimeConsoleError(defaultValue, formatNumberError(place, string));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,12 +243,8 @@ public class ErrorManager {
|
||||
public float parseFloat(String string, float defaultValue, String place) {
|
||||
try {
|
||||
return Float.parseFloat(string);
|
||||
} catch (Throwable e) {
|
||||
if (string.contains("%")) {
|
||||
return oneTimeConsoleError(defaultValue, "Value \"" + string + "\" used in " + place + " still has unparsed placeholders! Did you forget to download an expansion ?");
|
||||
} else {
|
||||
return oneTimeConsoleError(defaultValue, place + " only accepts numeric values! (Attempted to use \"" + string + "\")");
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
return oneTimeConsoleError(defaultValue, formatNumberError(place, string));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,14 +259,14 @@ public class ErrorManager {
|
||||
if (string == null || string.length() == 0) return 0; //preventing error message on bungee with papi placeholders due to them not being initialized yet
|
||||
try {
|
||||
return Double.parseDouble(string);
|
||||
} catch (Throwable e) {
|
||||
if (string.contains("%")) {
|
||||
return oneTimeConsoleError(defaultValue, "Value \"" + string + "\" used in " + place + " still has unparsed placeholders! Did you forget to download an expansion ?");
|
||||
} else {
|
||||
return oneTimeConsoleError(defaultValue, place + " only accepts numeric values! (Attempted to use \"" + string + "\")");
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
return oneTimeConsoleError(defaultValue, formatNumberError(place, string));
|
||||
}
|
||||
}
|
||||
|
||||
private String formatNumberError(String place, String value) {
|
||||
return String.format("%s only accepts numeric values! (Attempted to use \"%s\")", place, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses bar color in given string, returns second argument if string is not valid
|
||||
@@ -279,12 +278,8 @@ public class ErrorManager {
|
||||
public BarColor parseColor(String string, BarColor defaultValue, String place) {
|
||||
try {
|
||||
return BarColor.valueOf(string);
|
||||
} catch (Throwable e) {
|
||||
if (string.contains("%")) {
|
||||
return oneTimeConsoleError(defaultValue, "Value \"" + string + "\" used in " + place + " still has unparsed placeholders! Did you forget to download an expansion ?");
|
||||
} else {
|
||||
return oneTimeConsoleError(defaultValue, place + " only accepts one of the defined colors! (Attempted to use \"" + string + "\")");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return oneTimeConsoleError(defaultValue, String.format("%s only accepts one of the defined colors! (Attempted to use \"%s\")", place, string));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -298,12 +293,8 @@ public class ErrorManager {
|
||||
public BarStyle parseStyle(String string, BarStyle defaultValue, String place) {
|
||||
try {
|
||||
return BarStyle.valueOf(string);
|
||||
} catch (Throwable e) {
|
||||
if (string.contains("%")) {
|
||||
return oneTimeConsoleError(defaultValue, "Value \"" + string + "\" used in " + place + " still has unparsed placeholders! Did you forget to download an expansion ?");
|
||||
} else {
|
||||
return oneTimeConsoleError(defaultValue, place + " only accepts one of the defined styles! (Attempted to use \"" + string + "\")");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return oneTimeConsoleError(defaultValue, String.format("%s only accepts one of the defined styles! (Attempted to use \"%s\")", place, string));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -417,4 +408,16 @@ public class ErrorManager {
|
||||
return new SimpleDateFormat(defaultValue);
|
||||
}
|
||||
}
|
||||
|
||||
public File getAntiOverrideLog() {
|
||||
return antiOverrideLog;
|
||||
}
|
||||
|
||||
public File getErrorLog() {
|
||||
return errorLog;
|
||||
}
|
||||
|
||||
public File getPapiErrorLog() {
|
||||
return papiErrorLog;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package me.neznamy.tab.shared;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.ConcurrentModificationException;
|
||||
@@ -34,7 +35,7 @@ import me.neznamy.tab.shared.packets.PacketPlayOutScoreboardObjective;
|
||||
public class FeatureManager {
|
||||
|
||||
//list of registered features
|
||||
private Map<String, Feature> features = new LinkedHashMap<String, Feature>();
|
||||
private Map<String, Feature> features = new LinkedHashMap<>();
|
||||
|
||||
//tab instance
|
||||
private TAB tab;
|
||||
@@ -150,11 +151,12 @@ public class FeatureManager {
|
||||
* @param receiver - packet receiver
|
||||
* @param packet - an instance of custom packet class PacketPlayOutPlayerInfo
|
||||
* @return altered packet or null if packet should be cancelled
|
||||
* @throws Exception
|
||||
* @throws InvocationTargetException
|
||||
* @throws IllegalAccessException
|
||||
*/
|
||||
public Object onPacketPlayOutPlayerInfo(TabPlayer receiver, Object packet) throws Exception {
|
||||
public Object onPacketPlayOutPlayerInfo(TabPlayer receiver, Object packet) throws IllegalAccessException, InvocationTargetException {
|
||||
if (receiver.getVersion().getMinorVersion() < 8) return packet;
|
||||
List<PlayerInfoPacketListener> listeners = new ArrayList<PlayerInfoPacketListener>();
|
||||
List<PlayerInfoPacketListener> listeners = new ArrayList<>();
|
||||
for (Feature f : getAllFeatures()) {
|
||||
if (f instanceof PlayerInfoPacketListener) listeners.add((PlayerInfoPacketListener) f);
|
||||
}
|
||||
@@ -269,7 +271,7 @@ public class FeatureManager {
|
||||
long time = System.nanoTime();
|
||||
try {
|
||||
if (newPacket != null) newPacket = ((RawPacketListener)f).onPacketReceive(receiver, newPacket);
|
||||
} catch (Throwable e) {
|
||||
} catch (IllegalAccessException e) {
|
||||
tab.getErrorManager().printError("Feature " + f.getFeatureType() + " failed to read packet", e);
|
||||
}
|
||||
tab.getCPUManager().addTime(f.getFeatureType(), UsageType.PACKET_READING_IN, System.nanoTime()-time);
|
||||
@@ -289,7 +291,7 @@ public class FeatureManager {
|
||||
long time = System.nanoTime();
|
||||
try {
|
||||
((RawPacketListener)f).onPacketSend(receiver, packet);
|
||||
} catch (Throwable e) {
|
||||
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException | SecurityException | InstantiationException e) {
|
||||
tab.getErrorManager().printError("Feature " + f.getFeatureType() + " failed to read packet", e);
|
||||
}
|
||||
tab.getCPUManager().addTime(f.getFeatureType(), UsageType.PACKET_READING_OUT, System.nanoTime()-time);
|
||||
@@ -314,9 +316,9 @@ public class FeatureManager {
|
||||
* @param packetReceiver - player who received the packet
|
||||
* @param packet - the packet
|
||||
* @return true if packet should be cancelled, false if not
|
||||
* @throws Exception - if something fails
|
||||
* @throws IllegalAccessException
|
||||
*/
|
||||
public boolean onDisplayObjective(TabPlayer packetReceiver, Object packet) throws Exception {
|
||||
public boolean onDisplayObjective(TabPlayer packetReceiver, Object packet) throws IllegalAccessException {
|
||||
long time = System.nanoTime();
|
||||
PacketPlayOutScoreboardDisplayObjective display = tab.getPacketBuilder().readDisplayObjective(packet, packetReceiver.getVersion());
|
||||
tab.getCPUManager().addTime(TabFeature.PACKET_DESERIALIZING, UsageType.PACKET_DISPLAY_OBJECTIVE, System.nanoTime()-time);
|
||||
@@ -333,8 +335,9 @@ public class FeatureManager {
|
||||
/**
|
||||
* Calls onObjective on all featurs that implement ObjectivePacketListener and measures how long it took them to process
|
||||
* @param packetReceiver - player who received the packet
|
||||
* @throws IllegalAccessException
|
||||
*/
|
||||
public void onObjective(TabPlayer packetReceiver, Object packet) throws Exception {
|
||||
public void onObjective(TabPlayer packetReceiver, Object packet) throws IllegalAccessException {
|
||||
long time = System.nanoTime();
|
||||
PacketPlayOutScoreboardObjective display = tab.getPacketBuilder().readObjective(packet, packetReceiver.getVersion());
|
||||
tab.getCPUManager().addTime(TabFeature.PACKET_DESERIALIZING, UsageType.PACKET_OBJECTIVE, System.nanoTime()-time);
|
||||
|
||||
@@ -3,7 +3,9 @@ package me.neznamy.tab.shared;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -22,6 +24,7 @@ import me.neznamy.tab.shared.features.scoreboard.ScoreboardManager;
|
||||
import me.neznamy.tab.shared.packets.IChatBaseComponent;
|
||||
import me.neznamy.tab.shared.packets.PacketPlayOutChat;
|
||||
import me.neznamy.tab.shared.packets.UniversalPacketPlayOut;
|
||||
import me.neznamy.tab.shared.packets.PacketPlayOutChat.ChatMessageType;
|
||||
|
||||
/**
|
||||
* The core class for player
|
||||
@@ -31,23 +34,23 @@ public abstract class ITabPlayer implements TabPlayer {
|
||||
protected String name;
|
||||
protected UUID uniqueId;
|
||||
protected String world;
|
||||
private String permissionGroup = "<null>";
|
||||
private String permissionGroup = GroupRefresher.DEFAULT_GROUP;
|
||||
private String teamName;
|
||||
private String teamNameNote;
|
||||
private String forcedTeamName;
|
||||
|
||||
private Map<String, Property> properties = new HashMap<String, Property>();
|
||||
private Map<String, Property> properties = new HashMap<>();
|
||||
private ArmorStandManager armorStandManager;
|
||||
protected ProtocolVersion version = ProtocolVersion.SERVER_VERSION;
|
||||
protected ProtocolVersion version = TAB.getInstance().getServerVersion();
|
||||
protected Channel channel;
|
||||
private boolean bossbarVisible;
|
||||
|
||||
private boolean previewingNametag;
|
||||
private Set<BossBar> activeBossBars = new HashSet<BossBar>();
|
||||
private Set<BossBar> activeBossBars = new HashSet<>();
|
||||
private Boolean forcedCollision;
|
||||
private boolean onJoinFinished;
|
||||
private boolean hiddenNametag;
|
||||
private Set<UUID> hiddenNametagFor = new HashSet<UUID>();
|
||||
private Set<UUID> hiddenNametagFor = new HashSet<>();
|
||||
|
||||
private Scoreboard activeScoreboard;
|
||||
private boolean scoreboardVisible;
|
||||
@@ -55,7 +58,7 @@ public abstract class ITabPlayer implements TabPlayer {
|
||||
private String otherPluginScoreboard;
|
||||
private boolean teamHandlingPaused;
|
||||
|
||||
protected Map<String, String> attributes = new HashMap<String, String>();
|
||||
protected Map<String, String> attributes = new HashMap<>();
|
||||
|
||||
protected void init() {
|
||||
setGroup(((GroupRefresher)TAB.getInstance().getFeatureManager().getFeature("group")).detectPermissionGroup(this), false);
|
||||
@@ -80,12 +83,12 @@ public abstract class ITabPlayer implements TabPlayer {
|
||||
} else {
|
||||
component = new IChatBaseComponent(message);
|
||||
}
|
||||
sendCustomPacket(new PacketPlayOutChat(component));
|
||||
sendCustomPacket(new PacketPlayOutChat(component, ChatMessageType.CHAT));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(IChatBaseComponent message) {
|
||||
sendCustomPacket(new PacketPlayOutChat(message));
|
||||
sendCustomPacket(new PacketPlayOutChat(message, ChatMessageType.CHAT));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -110,7 +113,7 @@ public abstract class ITabPlayer implements TabPlayer {
|
||||
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);
|
||||
setProperty(PropertyUtils.NAMETAG,getProperty(PropertyUtils.TAGPREFIX).getCurrentRawValue() + getProperty(PropertyUtils.CUSTOMTAGNAME).getCurrentRawValue() + getProperty(PropertyUtils.TAGSUFFIX).getCurrentRawValue(), null);
|
||||
}
|
||||
TAB.getInstance().getPlaceholderManager().checkForRegistration(value);
|
||||
forceRefresh();
|
||||
@@ -119,9 +122,9 @@ public abstract class ITabPlayer implements TabPlayer {
|
||||
@Override
|
||||
public void setValuePermanently(EnumProperty type, String 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);
|
||||
((PlayerCommand)TAB.getInstance().getCommand().getSubcommands().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);
|
||||
setProperty(PropertyUtils.NAMETAG, getProperty(PropertyUtils.TAGPREFIX).getCurrentRawValue() + getProperty(PropertyUtils.CUSTOMTAGNAME).getCurrentRawValue() + getProperty(PropertyUtils.TAGSUFFIX).getCurrentRawValue(), null);
|
||||
}
|
||||
Property pr = getProperty(type.toString());
|
||||
if (pr == null) return;
|
||||
@@ -132,7 +135,8 @@ public abstract class ITabPlayer implements TabPlayer {
|
||||
|
||||
@Override
|
||||
public String getTemporaryValue(EnumProperty type) {
|
||||
return getProperty(type.toString()).getTemporaryValue();
|
||||
Property pr = getProperty(type.toString());
|
||||
return pr == null ? null : pr.getTemporaryValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -183,8 +187,8 @@ public abstract class ITabPlayer implements TabPlayer {
|
||||
activeScoreboard.unregister(this);
|
||||
activeScoreboard = null;
|
||||
}
|
||||
forcedScoreboard = (Scoreboard) scoreboard;
|
||||
((Scoreboard)scoreboard).register(this);
|
||||
forcedScoreboard = scoreboard;
|
||||
scoreboard.register(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -251,10 +255,10 @@ public abstract class ITabPlayer implements TabPlayer {
|
||||
if (armorStandManager == null) throw new IllegalStateException("Unlimited nametag mode is not enabled");
|
||||
if (previewingNametag) {
|
||||
armorStandManager.destroy(this);
|
||||
sendMessage(TAB.getInstance().getConfiguration().translation.getString("preview-off"), true);
|
||||
sendMessage(TAB.getInstance().getConfiguration().getTranslation().getString("preview-off"), true);
|
||||
} else {
|
||||
armorStandManager.spawn(this);
|
||||
sendMessage(TAB.getInstance().getConfiguration().translation.getString("preview-on"), true);
|
||||
sendMessage(TAB.getInstance().getConfiguration().getTranslation().getString("preview-on"), true);
|
||||
}
|
||||
previewingNametag = !previewingNametag;
|
||||
}
|
||||
@@ -295,20 +299,20 @@ public abstract class ITabPlayer implements TabPlayer {
|
||||
if (feature == null) return;
|
||||
if (hasBossbarVisible()) {
|
||||
feature.detectBossBarsAndSend(this);
|
||||
if (sendToggleMessage) sendMessage(TAB.getInstance().getConfiguration().translation.getString("bossbar-toggle-on"), true);
|
||||
if (feature.remember_toggle_choice) {
|
||||
feature.bossbar_off_players.remove(getName());
|
||||
TAB.getInstance().getConfiguration().playerdata.set("bossbar-off", feature.bossbar_off_players);
|
||||
if (sendToggleMessage) sendMessage(TAB.getInstance().getConfiguration().getTranslation().getString("bossbar-toggle-on"), true);
|
||||
if (feature.isRememberToggleChoice()) {
|
||||
feature.getBossbarOffPlayers().remove(getName());
|
||||
TAB.getInstance().getConfiguration().getPlayerDataFile().set("bossbar-off", feature.getBossbarOffPlayers());
|
||||
}
|
||||
} else {
|
||||
for (BossBar line : getActiveBossBars().toArray(new BossBar[0])) {
|
||||
removeBossBar(line);
|
||||
}
|
||||
getActiveBossBars().clear();
|
||||
if (sendToggleMessage) sendMessage(TAB.getInstance().getConfiguration().translation.getString("bossbar-toggle-off"), true);
|
||||
if (feature.remember_toggle_choice && !feature.bossbar_off_players.contains(getName())) {
|
||||
feature.bossbar_off_players.add(getName());
|
||||
TAB.getInstance().getConfiguration().playerdata.set("bossbar-off", feature.bossbar_off_players);
|
||||
if (sendToggleMessage) sendMessage(TAB.getInstance().getConfiguration().getTranslation().getString("bossbar-toggle-off"), true);
|
||||
if (feature.isRememberToggleChoice() && !feature.getBossbarOffPlayers().contains(getName())) {
|
||||
feature.getBossbarOffPlayers().add(getName());
|
||||
TAB.getInstance().getConfiguration().getPlayerDataFile().set("bossbar-off", feature.getBossbarOffPlayers());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -331,39 +335,22 @@ public abstract class ITabPlayer implements TabPlayer {
|
||||
@Override
|
||||
public void loadPropertyFromConfig(String property, String ifNotSet) {
|
||||
String playerGroupFromConfig = permissionGroup.replace(".", "@#@");
|
||||
String worldGroup = TAB.getInstance().getConfiguration().getWorldGroupOf(getWorldName());
|
||||
String worldGroup = TAB.getInstance().getConfiguration().getWorldGroupOf(TAB.getInstance().getConfiguration().getConfig().getConfigurationSection("per-" + TAB.getInstance().getPlatform().getSeparatorType() + "-settings").keySet(), getWorldName());
|
||||
String value;
|
||||
if ((value = TAB.getInstance().getConfiguration().config.getString("per-" + TAB.getInstance().getPlatform().getSeparatorType() + "-settings." + worldGroup + ".Users." + getName() + "." + property)) != null) {
|
||||
setProperty(property, value, "Player: " + getName() + ", " + TAB.getInstance().getPlatform().getSeparatorType() + ": " + worldGroup);
|
||||
return;
|
||||
}
|
||||
if ((value = TAB.getInstance().getConfiguration().config.getString("per-" + TAB.getInstance().getPlatform().getSeparatorType() + "-settings." + worldGroup + ".Users." + getUniqueId().toString() + "." + property)) != null) {
|
||||
setProperty(property, value, "PlayerUUID: " + getName() + ", " + TAB.getInstance().getPlatform().getSeparatorType() + ": " + worldGroup);
|
||||
return;
|
||||
}
|
||||
if ((value = TAB.getInstance().getConfiguration().config.getString("Users." + getName() + "." + property)) != null) {
|
||||
setProperty(property, value, "Player: " + getName());
|
||||
return;
|
||||
}
|
||||
if ((value = TAB.getInstance().getConfiguration().config.getString("Users." + getUniqueId().toString() + "." + property)) != null) {
|
||||
setProperty(property, value, "PlayerUUID: " + getName());
|
||||
return;
|
||||
}
|
||||
if ((value = TAB.getInstance().getConfiguration().config.getString("per-" + TAB.getInstance().getPlatform().getSeparatorType() + "-settings." + worldGroup + ".Groups." + playerGroupFromConfig + "." + property)) != null) {
|
||||
setProperty(property, value, "Group: " + permissionGroup + ", " + TAB.getInstance().getPlatform().getSeparatorType() + ": " + worldGroup);
|
||||
return;
|
||||
}
|
||||
if ((value = TAB.getInstance().getConfiguration().config.getString("per-" + TAB.getInstance().getPlatform().getSeparatorType() + "-settings." + worldGroup + ".Groups._OTHER_." + property)) != null) {
|
||||
setProperty(property, value, "Group: _OTHER_," + TAB.getInstance().getPlatform().getSeparatorType() + ": " + worldGroup);
|
||||
return;
|
||||
}
|
||||
if ((value = TAB.getInstance().getConfiguration().config.getString("Groups." + playerGroupFromConfig + "." + property)) != null) {
|
||||
setProperty(property, value, "Group: " + permissionGroup);
|
||||
return;
|
||||
}
|
||||
if ((value = TAB.getInstance().getConfiguration().config.getString("Groups._OTHER_." + property)) != null) {
|
||||
setProperty(property, value, "Group: _OTHER_");
|
||||
return;
|
||||
Map<String, String> priorities = new LinkedHashMap<>();
|
||||
priorities.put("per-" + TAB.getInstance().getPlatform().getSeparatorType() + "-settings." + worldGroup + ".Users." + getName() + "." + property, "Player: " + getName() + ", " + TAB.getInstance().getPlatform().getSeparatorType() + ": " + worldGroup);
|
||||
priorities.put("per-" + TAB.getInstance().getPlatform().getSeparatorType() + "-settings." + worldGroup + ".Users." + getUniqueId().toString() + "." + property, "PlayerUUID: " + getName() + ", " + TAB.getInstance().getPlatform().getSeparatorType() + ": " + worldGroup);
|
||||
priorities.put("Users." + getName() + "." + property, "Player: " + getName());
|
||||
priorities.put("Users." + getUniqueId().toString() + "." + property, "PlayerUUID: " + getName());
|
||||
priorities.put("per-" + TAB.getInstance().getPlatform().getSeparatorType() + "-settings." + worldGroup + ".Groups." + playerGroupFromConfig + "." + property, "Group: " + permissionGroup + ", " + TAB.getInstance().getPlatform().getSeparatorType() + ": " + worldGroup);
|
||||
priorities.put("per-" + TAB.getInstance().getPlatform().getSeparatorType() + "-settings." + worldGroup + ".Groups._OTHER_." + property, "Group: _OTHER_," + TAB.getInstance().getPlatform().getSeparatorType() + ": " + worldGroup);
|
||||
priorities.put("Groups." + playerGroupFromConfig + "." + property, "Group: " + permissionGroup);
|
||||
priorities.put("Groups._OTHER_." + property, "Group: _OTHER_");
|
||||
for (Entry<String, String> entry : priorities.entrySet()) {
|
||||
if ((value = TAB.getInstance().getConfiguration().getConfig().getString(entry.getKey())) != null) {
|
||||
setProperty(property, value, entry.getValue());
|
||||
return;
|
||||
}
|
||||
}
|
||||
setProperty(property, ifNotSet, "None");
|
||||
}
|
||||
@@ -416,31 +403,31 @@ public abstract class ITabPlayer implements TabPlayer {
|
||||
if (visible) {
|
||||
scoreboardManager.sendHighestScoreboard(this);
|
||||
if (sendToggleMessage) {
|
||||
sendMessage(scoreboardManager.scoreboard_on, true);
|
||||
sendMessage(scoreboardManager.getScoreboardOn(), true);
|
||||
}
|
||||
if (scoreboardManager.remember_toggle_choice) {
|
||||
if (scoreboardManager.hiddenByDefault) {
|
||||
scoreboardManager.sb_off_players.add(getName());
|
||||
if (scoreboardManager.isRememberToggleChoice()) {
|
||||
if (scoreboardManager.isHiddenByDefault()) {
|
||||
scoreboardManager.getSbOffPlayers().add(getName());
|
||||
} else {
|
||||
scoreboardManager.sb_off_players.remove(getName());
|
||||
scoreboardManager.getSbOffPlayers().remove(getName());
|
||||
}
|
||||
synchronized (scoreboardManager.sb_off_players){
|
||||
TAB.getInstance().getConfiguration().playerdata.set("scoreboard-off", new ArrayList<>(scoreboardManager.sb_off_players));
|
||||
synchronized (scoreboardManager.getSbOffPlayers()){
|
||||
TAB.getInstance().getConfiguration().getPlayerDataFile().set("scoreboard-off", new ArrayList<>(scoreboardManager.getSbOffPlayers()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
scoreboardManager.unregisterScoreboard(this, true);
|
||||
if (sendToggleMessage) {
|
||||
sendMessage(scoreboardManager.scoreboard_off, true);
|
||||
sendMessage(scoreboardManager.getScoreboardOff(), true);
|
||||
}
|
||||
if (scoreboardManager.remember_toggle_choice) {
|
||||
if (scoreboardManager.hiddenByDefault) {
|
||||
scoreboardManager.sb_off_players.remove(getName());
|
||||
if (scoreboardManager.isRememberToggleChoice()) {
|
||||
if (scoreboardManager.isHiddenByDefault()) {
|
||||
scoreboardManager.getSbOffPlayers().remove(getName());
|
||||
} else {
|
||||
scoreboardManager.sb_off_players.add(getName());
|
||||
scoreboardManager.getSbOffPlayers().add(getName());
|
||||
}
|
||||
synchronized (scoreboardManager.sb_off_players){
|
||||
TAB.getInstance().getConfiguration().playerdata.set("scoreboard-off", new ArrayList<>(scoreboardManager.sb_off_players));
|
||||
synchronized (scoreboardManager.getSbOffPlayers()){
|
||||
TAB.getInstance().getConfiguration().getPlayerDataFile().set("scoreboard-off", new ArrayList<>(scoreboardManager.getSbOffPlayers()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,9 @@ import me.neznamy.tab.shared.packets.PacketPlayOutScoreboardTeam;
|
||||
*/
|
||||
public class PacketAPI {
|
||||
|
||||
private PacketAPI() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers scoreboard team with given properties but sends unregister packet first unless disabled to avoid bungeecord kick
|
||||
* @param to - player to send the packet to
|
||||
@@ -27,10 +30,10 @@ public class PacketAPI {
|
||||
* @param color - color field (1.13+)
|
||||
*/
|
||||
public static synchronized void registerScoreboardTeam(TabPlayer to, String teamName, String prefix, String suffix, boolean enumNameTagVisibility, boolean enumTeamPush, Collection<String> players, EnumChatFormat color, TabFeature feature) {
|
||||
if (to.getVersion().getMinorVersion() >= 8 && TAB.getInstance().getConfiguration().unregisterBeforeRegister && TAB.getInstance().getPlatform().getSeparatorType().equals("world")) {
|
||||
to.sendCustomPacket(new PacketPlayOutScoreboardTeam(teamName).setTeamOptions(69), feature);
|
||||
if (to.getVersion().getMinorVersion() >= 8 && TAB.getInstance().getConfiguration().isUnregisterBeforeRegister() && TAB.getInstance().getPlatform().getSeparatorType().equals("world")) {
|
||||
to.sendCustomPacket(new PacketPlayOutScoreboardTeam(teamName), feature);
|
||||
}
|
||||
to.sendCustomPacket(new PacketPlayOutScoreboardTeam(teamName, prefix, suffix, enumNameTagVisibility?"always":"never", enumTeamPush?"always":"never", players, 69).setColor(color), feature);
|
||||
to.sendCustomPacket(new PacketPlayOutScoreboardTeam(teamName, prefix, suffix, enumNameTagVisibility?"always":"never", enumTeamPush?"always":"never", players, 0).setColor(color), feature);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -42,7 +45,7 @@ public class PacketAPI {
|
||||
* @param displayType - display type of the value (only supported in Playerlist)
|
||||
*/
|
||||
public static synchronized void registerScoreboardObjective(TabPlayer to, String objectiveName, String title, int position, EnumScoreboardHealthDisplay displayType, TabFeature feature) {
|
||||
if (to.getVersion().getMinorVersion() >= 8 && TAB.getInstance().getConfiguration().unregisterBeforeRegister && TAB.getInstance().getPlatform().getSeparatorType().equals("world")) {
|
||||
if (to.getVersion().getMinorVersion() >= 8 && TAB.getInstance().getConfiguration().isUnregisterBeforeRegister() && TAB.getInstance().getPlatform().getSeparatorType().equals("world")) {
|
||||
to.sendCustomPacket(new PacketPlayOutScoreboardObjective(objectiveName), feature);
|
||||
}
|
||||
to.sendCustomPacket(new PacketPlayOutScoreboardObjective(0, objectiveName, title, displayType), feature);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package me.neznamy.tab.shared;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Map;
|
||||
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
@@ -32,9 +33,12 @@ public interface Platform {
|
||||
|
||||
/**
|
||||
* Loads features from config
|
||||
* @throws Exception - if something fails
|
||||
* @throws IllegalAccessException
|
||||
* @throws SecurityException
|
||||
* @throws NoSuchMethodException
|
||||
* @throws InvocationTargetException
|
||||
*/
|
||||
public void loadFeatures() throws Exception;
|
||||
public void loadFeatures() throws IllegalAccessException, InvocationTargetException, NoSuchMethodException, SecurityException;
|
||||
|
||||
/**
|
||||
* Sends a message into console
|
||||
@@ -155,17 +159,17 @@ 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().removeGhostPlayers) tab.getFeatureManager().registerFeature("ghostplayerfix", new GhostPlayerFix());
|
||||
if (ProtocolVersion.SERVER_VERSION.getMinorVersion() >= 8 && tab.getConfiguration().config.getBoolean("change-tablist-prefix-suffix", true)) {
|
||||
if (tab.getConfiguration().getConfig().getBoolean("enable-header-footer", true)) tab.getFeatureManager().registerFeature("headerfooter", new HeaderFooter(tab));
|
||||
if (tab.getConfiguration().isRemoveGhostPlayers()) tab.getFeatureManager().registerFeature("ghostplayerfix", new GhostPlayerFix());
|
||||
if (TAB.getInstance().getServerVersion().getMinorVersion() >= 8 && tab.getConfiguration().getConfig().getBoolean("change-tablist-prefix-suffix", true)) {
|
||||
Playerlist playerlist = new Playerlist(tab);
|
||||
tab.getFeatureManager().registerFeature("playerlist", playerlist);
|
||||
if (tab.getConfiguration().premiumconfig != null && tab.getConfiguration().premiumconfig.getBoolean("align-tabsuffix-on-the-right", false)) tab.getFeatureManager().registerFeature("alignedsuffix", new AlignedSuffix(playerlist, tab));
|
||||
if (tab.getConfiguration().getPremiumConfig() != null && tab.getConfiguration().getPremiumConfig().getBoolean("align-tabsuffix-on-the-right", false)) tab.getFeatureManager().registerFeature("alignedsuffix", new AlignedSuffix(playerlist, tab));
|
||||
}
|
||||
tab.getFeatureManager().registerFeature("group", new GroupRefresher(tab));
|
||||
tab.getFeatureManager().registerFeature("info", new PluginInfo());
|
||||
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().isLayout()) tab.getFeatureManager().registerFeature("layout", new Layout(tab));
|
||||
if (tab.getConfiguration().getBossbarConfig().getBoolean("bossbar-enabled", false)) tab.getFeatureManager().registerFeature("bossbar", new BossBar(tab));
|
||||
}
|
||||
}
|
||||
@@ -23,16 +23,16 @@ public class Property {
|
||||
private String temporaryValue;
|
||||
|
||||
//last known output after placeholder replacement
|
||||
public String lastReplacedValue;
|
||||
private String lastReplacedValue;
|
||||
|
||||
//source of property's raw value
|
||||
private String source;
|
||||
|
||||
//used placeholders in current raw value
|
||||
public List<String> placeholders;
|
||||
private List<String> placeholders;
|
||||
|
||||
//used relational placeholders in current raw value
|
||||
public List<String> relPlaceholders;
|
||||
private List<String> relPlaceholders;
|
||||
|
||||
public Property(TabPlayer owner, String rawValue) {
|
||||
this(owner, rawValue, null);
|
||||
@@ -41,7 +41,7 @@ public class Property {
|
||||
public Property(TabPlayer owner, String rawValue, String source) {
|
||||
this.owner = owner;
|
||||
this.source = source;
|
||||
this.rawValue = RGBUtils.getInstance().applyFormats((rawValue == null ? "" : rawValue), true);
|
||||
this.rawValue = RGBUtils.getInstance().applyFormats((rawValue == null ? "" : TAB.getInstance().getPlaceholderManager().color(rawValue)), true);
|
||||
analyze(this.rawValue);
|
||||
update();
|
||||
}
|
||||
@@ -51,18 +51,18 @@ public class Property {
|
||||
* @param value - raw value to be checked
|
||||
*/
|
||||
private void analyze(String value) {
|
||||
List<String> placeholders = new ArrayList<String>();
|
||||
List<String> relPlaceholders = new ArrayList<String>();
|
||||
List<String> placeholders0 = new ArrayList<>();
|
||||
List<String> relPlaceholders0 = new ArrayList<>();
|
||||
for (String identifier : TAB.getInstance().getPlaceholderManager().getUsedPlaceholderIdentifiersRecursive(value)) {
|
||||
if (identifier.startsWith("%rel_")) {
|
||||
relPlaceholders.add(identifier);
|
||||
relPlaceholders0.add(identifier);
|
||||
} else {
|
||||
placeholders.add(identifier);
|
||||
placeholders0.add(identifier);
|
||||
}
|
||||
}
|
||||
//avoiding rare concurrent modification in #update
|
||||
this.placeholders = placeholders;
|
||||
this.relPlaceholders = relPlaceholders;
|
||||
placeholders = placeholders0;
|
||||
relPlaceholders = relPlaceholders0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,7 +71,7 @@ public class Property {
|
||||
*/
|
||||
public void setTemporaryValue(String temporaryValue) {
|
||||
if (temporaryValue != null) {
|
||||
this.temporaryValue = RGBUtils.getInstance().applyFormats(temporaryValue, true);
|
||||
this.temporaryValue = RGBUtils.getInstance().applyFormats(TAB.getInstance().getPlaceholderManager().color(temporaryValue), true);
|
||||
analyze(this.temporaryValue);
|
||||
} else {
|
||||
this.temporaryValue = null;
|
||||
@@ -86,7 +86,7 @@ public class Property {
|
||||
*/
|
||||
public void changeRawValue(String newValue) {
|
||||
if (rawValue.equals(newValue)) return;
|
||||
rawValue = RGBUtils.getInstance().applyFormats(newValue, true);
|
||||
rawValue = RGBUtils.getInstance().applyFormats(TAB.getInstance().getPlaceholderManager().color(newValue), true);
|
||||
if (temporaryValue == null) {
|
||||
analyze(rawValue);
|
||||
update();
|
||||
@@ -166,7 +166,7 @@ public class Property {
|
||||
|
||||
private String applyRemoveStrings(String text) {
|
||||
String reformatted = text;
|
||||
for (String removed : TAB.getInstance().getConfiguration().removeStrings) {
|
||||
for (String removed : TAB.getInstance().getConfiguration().getRemoveStrings()) {
|
||||
if (removed.startsWith("CONTAINS:") && reformatted.contains(removed.substring(9))) return "";
|
||||
if (removed.startsWith("STARTS:") && reformatted.startsWith(removed.substring(7))) return "";
|
||||
if (removed.startsWith("ENDS:") && reformatted.endsWith(removed.substring(5))) return "";
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package me.neznamy.tab.shared;
|
||||
|
||||
public class PropertyUtils {
|
||||
|
||||
public static final String HEADER = "header";
|
||||
public static final String FOOTER = "footer";
|
||||
|
||||
public static final String TABPREFIX = "tabprefix";
|
||||
public static final String CUSTOMTABNAME = "customtabname";
|
||||
public static final String TABSUFFIX = "tabsuffix";
|
||||
|
||||
public static final String TAGPREFIX = "tagprefix";
|
||||
public static final String CUSTOMTAGNAME = "customtagname";
|
||||
public static final String TAGSUFFIX = "tagsuffix";
|
||||
|
||||
public static final String ABOVENAME = "abovename";
|
||||
public static final String NAMETAG = "nametag";
|
||||
public static final String BELOWNAME = "belowname";
|
||||
|
||||
private PropertyUtils() {
|
||||
}
|
||||
|
||||
public static String bossbarTitle(String name) {
|
||||
return "bossbar-title-" + name;
|
||||
}
|
||||
|
||||
public static String bossbarProgress(String name) {
|
||||
return "bossbar-progress-" + name;
|
||||
}
|
||||
|
||||
public static String bossbarColor(String name) {
|
||||
return "bossbar-color-" + name;
|
||||
}
|
||||
|
||||
public static String bossbarStyle(String name) {
|
||||
return "bossbar-style-" + name;
|
||||
}
|
||||
}
|
||||
@@ -6,58 +6,56 @@ 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),
|
||||
v1_16_2 (751),
|
||||
v1_16_1 (736),
|
||||
v1_16 (735),
|
||||
v1_15_2 (578),
|
||||
v1_15_1 (575),
|
||||
v1_15 (573),
|
||||
v1_14_4 (498),
|
||||
v1_14_3 (490),
|
||||
v1_14_2 (485),
|
||||
v1_14_1 (480),
|
||||
v1_14 (477),
|
||||
v1_13_2 (404),
|
||||
v1_13_1 (401),
|
||||
v1_13 (393),
|
||||
v1_12_2 (340),
|
||||
v1_12_1 (338),
|
||||
v1_12 (335),
|
||||
v1_11_2 (316),
|
||||
v1_11_1 (316),
|
||||
v1_11 (315),
|
||||
v1_10_2 (210),
|
||||
v1_10_1 (210),
|
||||
v1_10 (210),
|
||||
v1_9_4 (110),
|
||||
v1_9_3 (110),
|
||||
v1_9_2 (109),
|
||||
v1_9_1 (108),
|
||||
v1_9 (107),
|
||||
v1_8 (47),
|
||||
v1_7_10 (5),
|
||||
v1_7_9 (5),
|
||||
v1_7_8 (5),
|
||||
v1_7_7 (5),
|
||||
v1_7_6 (5),
|
||||
v1_7_5 (4),
|
||||
v1_7_4 (4),
|
||||
v1_7_2 (4),
|
||||
v1_6_4 (78),
|
||||
v1_6_2 (74),
|
||||
v1_6_1 (73),
|
||||
v1_5_2 (61),
|
||||
v1_5_1 (60),
|
||||
v1_5 (60),
|
||||
v1_4_7 (51),
|
||||
v1_4_6 (51);
|
||||
|
||||
//server version, always using latest on proxies
|
||||
public static ProtocolVersion SERVER_VERSION;
|
||||
V1_17_1 (756),
|
||||
V1_17 (755),
|
||||
V1_16_5 (754),
|
||||
V1_16_4 (754),
|
||||
V1_16_3 (753),
|
||||
V1_16_2 (751),
|
||||
V1_16_1 (736),
|
||||
V1_16 (735),
|
||||
V1_15_2 (578),
|
||||
V1_15_1 (575),
|
||||
V1_15 (573),
|
||||
V1_14_4 (498),
|
||||
V1_14_3 (490),
|
||||
V1_14_2 (485),
|
||||
V1_14_1 (480),
|
||||
V1_14 (477),
|
||||
V1_13_2 (404),
|
||||
V1_13_1 (401),
|
||||
V1_13 (393),
|
||||
V1_12_2 (340),
|
||||
V1_12_1 (338),
|
||||
V1_12 (335),
|
||||
V1_11_2 (316),
|
||||
V1_11_1 (316),
|
||||
V1_11 (315),
|
||||
V1_10_2 (210),
|
||||
V1_10_1 (210),
|
||||
V1_10 (210),
|
||||
V1_9_4 (110),
|
||||
V1_9_3 (110),
|
||||
V1_9_2 (109),
|
||||
V1_9_1 (108),
|
||||
V1_9 (107),
|
||||
V1_8 (47),
|
||||
V1_7_10 (5),
|
||||
V1_7_9 (5),
|
||||
V1_7_8 (5),
|
||||
V1_7_7 (5),
|
||||
V1_7_6 (5),
|
||||
V1_7_5 (4),
|
||||
V1_7_4 (4),
|
||||
V1_7_2 (4),
|
||||
V1_6_4 (78),
|
||||
V1_6_2 (74),
|
||||
V1_6_1 (73),
|
||||
V1_5_2 (61),
|
||||
V1_5_1 (60),
|
||||
V1_5 (60),
|
||||
V1_4_7 (51),
|
||||
V1_4_6 (51);
|
||||
|
||||
//version's network id found at https://wiki.vg/Protocol_version_numbers
|
||||
private int networkId;
|
||||
@@ -92,7 +90,7 @@ public enum ProtocolVersion {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns user-friendly name of the version (such as 1.16.2 instead of v1_16_2)
|
||||
* Returns user-friendly name of the version (such as 1.16.2 instead of V1_16_2)
|
||||
* @return
|
||||
*/
|
||||
public String getFriendlyName() {
|
||||
@@ -113,10 +111,10 @@ public enum ProtocolVersion {
|
||||
* @return version or UNKNOWN if version is unknown
|
||||
*/
|
||||
public static ProtocolVersion fromFriendlyName(String friendlyName) {
|
||||
if (friendlyName.startsWith("1.8")) return v1_8;
|
||||
if (friendlyName.startsWith("1.8")) return V1_8;
|
||||
try {
|
||||
return valueOf("v" + friendlyName.replace(".", "_"));
|
||||
} catch (Throwable e) {
|
||||
return valueOf("V" + friendlyName.replace(".", "_"));
|
||||
} catch (Exception e) {
|
||||
return UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,16 +25,16 @@ public class TAB {
|
||||
private static TAB instance;
|
||||
|
||||
//version of plugin
|
||||
public static final String pluginVersion = "2.9.0";
|
||||
public static final String PLUGIN_VERSION = "2.9.2";
|
||||
|
||||
//player data
|
||||
public final Map<UUID, TabPlayer> data = new ConcurrentHashMap<UUID, TabPlayer>();
|
||||
private final Map<UUID, TabPlayer> data = new ConcurrentHashMap<>();
|
||||
|
||||
//the command
|
||||
public TabCommand command;
|
||||
private TabCommand command;
|
||||
|
||||
//command used if plugin is disabled due to a broken configuration file
|
||||
public final DisabledCommand disabledCommand = new DisabledCommand();
|
||||
private final DisabledCommand disabledCommand = new DisabledCommand();
|
||||
|
||||
//platform interface
|
||||
private Platform platform;
|
||||
@@ -52,22 +52,26 @@ public class TAB {
|
||||
private FeatureManager featureManager;
|
||||
|
||||
//name of broken configuration file filled on load and used in disabledCommand
|
||||
public String brokenFile = "-";
|
||||
private String brokenFile = "-";
|
||||
|
||||
//platform-specific packet builder
|
||||
private PacketBuilder packetBuilder;
|
||||
|
||||
private Configs configuration;
|
||||
|
||||
public boolean debugMode;
|
||||
private boolean debugMode;
|
||||
|
||||
private boolean disabled;
|
||||
|
||||
private PlaceholderManager placeholderManager;
|
||||
|
||||
//server version, always using latest on proxies
|
||||
private ProtocolVersion serverVersion;
|
||||
|
||||
public TAB(Platform platform, PacketBuilder packetBuilder) {
|
||||
public TAB(Platform platform, PacketBuilder packetBuilder, ProtocolVersion serverVersion) {
|
||||
this.platform = platform;
|
||||
this.packetBuilder = packetBuilder;
|
||||
this.serverVersion = serverVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,7 +137,7 @@ public class TAB {
|
||||
* @param message - message to be sent into console
|
||||
*/
|
||||
public void debug(String message) {
|
||||
if (debugMode) platform.sendConsoleMessage("&9[TAB DEBUG] " + message, true);
|
||||
if (isDebugMode()) platform.sendConsoleMessage("&9[TAB DEBUG] " + message, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -151,7 +155,7 @@ public class TAB {
|
||||
placeholderManager = new PlaceholderManager(this);
|
||||
featureManager.registerFeature("placeholders", placeholderManager);
|
||||
platform.loadFeatures();
|
||||
command = new TabCommand(this);
|
||||
setCommand(new TabCommand(this));
|
||||
featureManager.load();
|
||||
getPlayers().forEach(p -> ((ITabPlayer)p).markAsLoaded());
|
||||
errorManager.printConsoleWarnCount();
|
||||
@@ -161,7 +165,7 @@ public class TAB {
|
||||
} catch (YAMLException e) {
|
||||
print('c', "Did not enable due to a broken configuration file.");
|
||||
disabled = true;
|
||||
} catch (Throwable e) {
|
||||
} catch (Exception e) {
|
||||
errorManager.criticalError("Failed to enable. Did you just invent a new way to break the plugin by misconfiguring it?", e);
|
||||
disabled = true;
|
||||
}
|
||||
@@ -179,7 +183,7 @@ public class TAB {
|
||||
featureManager.unload();
|
||||
data.clear();
|
||||
platform.sendConsoleMessage("&a[TAB] Disabled in " + (System.currentTimeMillis()-time) + "ms", true);
|
||||
} catch (Throwable e) {
|
||||
} catch (Exception e) {
|
||||
errorManager.criticalError("Failed to disable", e);
|
||||
}
|
||||
}
|
||||
@@ -229,7 +233,7 @@ public class TAB {
|
||||
}
|
||||
|
||||
public String getPluginVersion() {
|
||||
return pluginVersion;
|
||||
return PLUGIN_VERSION;
|
||||
}
|
||||
|
||||
public Configs getConfiguration() {
|
||||
@@ -243,4 +247,36 @@ public class TAB {
|
||||
public PlaceholderManager getPlaceholderManager() {
|
||||
return placeholderManager;
|
||||
}
|
||||
|
||||
public TabCommand getCommand() {
|
||||
return command;
|
||||
}
|
||||
|
||||
public void setCommand(TabCommand command) {
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
public boolean isDebugMode() {
|
||||
return debugMode;
|
||||
}
|
||||
|
||||
public void setDebugMode(boolean debugMode) {
|
||||
this.debugMode = debugMode;
|
||||
}
|
||||
|
||||
public String getBrokenFile() {
|
||||
return brokenFile;
|
||||
}
|
||||
|
||||
public void setBrokenFile(String brokenFile) {
|
||||
this.brokenFile = brokenFile;
|
||||
}
|
||||
|
||||
public DisabledCommand getDisabledCommand() {
|
||||
return disabledCommand;
|
||||
}
|
||||
|
||||
public ProtocolVersion getServerVersion() {
|
||||
return serverVersion;
|
||||
}
|
||||
}
|
||||
@@ -18,23 +18,24 @@ public class DisabledCommand {
|
||||
* @return list of messages to send back
|
||||
*/
|
||||
public List<String> execute(String[] args, boolean hasReloadPermission, boolean hasAdminPermission) {
|
||||
List<String> messages = new ArrayList<String>();
|
||||
List<String> messages = new ArrayList<>();
|
||||
if (args.length == 1 && args[0].equalsIgnoreCase("reload")) {
|
||||
if (hasReloadPermission) {
|
||||
TAB.getInstance().load();
|
||||
if (TAB.getInstance().isDisabled()) {
|
||||
messages.add(TAB.getInstance().getConfiguration().reloadFailed.replace("%file%", TAB.getInstance().brokenFile));
|
||||
messages.add(TAB.getInstance().getConfiguration().getReloadFailedMessage().replace("%file%", TAB.getInstance().getBrokenFile()));
|
||||
} else {
|
||||
messages.add(TAB.getInstance().getConfiguration().translation.getString("reloaded"));
|
||||
messages.add(TAB.getInstance().getConfiguration().getTranslation().getString("reloaded"));
|
||||
}
|
||||
} else {
|
||||
messages.add(TAB.getInstance().getConfiguration().translation.getString("no_permission"));
|
||||
//cannot take message from file when syntax is broken
|
||||
messages.add("&cI'm sorry, but you do not have permission to perform this command. Please contact the server administrators if you believe that this is in error.");
|
||||
}
|
||||
} else {
|
||||
if (hasAdminPermission) {
|
||||
String command = TAB.getInstance().getPlatform().getSeparatorType().equals("world") ? "/tab" : "/btab";
|
||||
messages.add("&m ");
|
||||
messages.add(" &cPlugin is disabled due to a broken configuration file (" + TAB.getInstance().brokenFile + "). Check console for more details.");
|
||||
messages.add(" &cPlugin is disabled due to a broken configuration file (" + TAB.getInstance().getBrokenFile() + "). Check console for more details.");
|
||||
messages.add(" &8>> &3&l" + command + " reload");
|
||||
messages.add(" - &7Reloads plugin and config");
|
||||
messages.add("&m ");
|
||||
|
||||
@@ -6,6 +6,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import me.neznamy.tab.shared.PropertyUtils;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
/**
|
||||
* Abstract class representing a subcommand of "/tab" command
|
||||
@@ -13,10 +14,10 @@ import me.neznamy.tab.shared.TAB;
|
||||
public abstract class SubCommand {
|
||||
|
||||
//all properties assignable with a command
|
||||
public static String[] allProperties = {"tabprefix", "tabsuffix", "tagprefix", "tagsuffix", "customtabname", "abovename", "belowname", "customtagname"};
|
||||
private static String[] allProperties = {PropertyUtils.TABPREFIX, PropertyUtils.TABSUFFIX, PropertyUtils.TAGPREFIX, PropertyUtils.TAGSUFFIX, PropertyUtils.CUSTOMTABNAME, PropertyUtils.ABOVENAME, PropertyUtils.BELOWNAME, PropertyUtils.CUSTOMTAGNAME};
|
||||
|
||||
//properties that require unlimited nametag mode
|
||||
protected final List<String> extraProperties = Arrays.asList("abovename", "belowname", "customtagname");
|
||||
protected final List<String> extraProperties = Arrays.asList(PropertyUtils.ABOVENAME, PropertyUtils.BELOWNAME, PropertyUtils.CUSTOMTAGNAME);
|
||||
|
||||
//name of this subcommand
|
||||
private String name;
|
||||
@@ -25,14 +26,14 @@ public abstract class SubCommand {
|
||||
private String permission;
|
||||
|
||||
//subcommands of this command
|
||||
public Map<String, SubCommand> subcommands = new HashMap<String, SubCommand>();
|
||||
private Map<String, SubCommand> subcommands = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters
|
||||
* @param name - command name
|
||||
* @param permission - permission requirement
|
||||
*/
|
||||
public SubCommand(String name, String permission) {
|
||||
protected SubCommand(String name, String permission) {
|
||||
this.name = name;
|
||||
this.permission = permission;
|
||||
}
|
||||
@@ -42,7 +43,7 @@ public abstract class SubCommand {
|
||||
* @param subcommand - subcommand to register
|
||||
*/
|
||||
public void registerSubCommand(SubCommand subcommand) {
|
||||
subcommands.put(subcommand.getName(), subcommand);
|
||||
getSubcommands().put(subcommand.getName(), subcommand);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,7 +110,7 @@ public abstract class SubCommand {
|
||||
* @return List of compatible players
|
||||
*/
|
||||
public List<String> getPlayers(String nameStart){
|
||||
List<String> suggestions = new ArrayList<String>();
|
||||
List<String> suggestions = new ArrayList<>();
|
||||
for (TabPlayer all : TAB.getInstance().getPlayers()) {
|
||||
if (all.getName().toLowerCase().startsWith(nameStart.toLowerCase())) suggestions.add(all.getName());
|
||||
}
|
||||
@@ -130,17 +131,17 @@ public abstract class SubCommand {
|
||||
argument = arguments[0].toLowerCase();
|
||||
}
|
||||
if (arguments.length < 2) {
|
||||
List<String> suggestions = new ArrayList<String>();
|
||||
for (String subcommand : subcommands.keySet()) {
|
||||
List<String> suggestions = new ArrayList<>();
|
||||
for (String subcommand : getSubcommands().keySet()) {
|
||||
if (subcommand.startsWith(argument)) suggestions.add(subcommand);
|
||||
}
|
||||
return suggestions;
|
||||
}
|
||||
SubCommand subcommand = subcommands.get(argument);
|
||||
SubCommand subcommand = getSubcommands().get(argument);
|
||||
if (subcommand != null) {
|
||||
return subcommand.complete(sender, Arrays.copyOfRange(arguments, 1, arguments.length));
|
||||
}
|
||||
return new ArrayList<String>();
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -162,7 +163,7 @@ public abstract class SubCommand {
|
||||
* @return translation from file
|
||||
*/
|
||||
public String getTranslation(String key) {
|
||||
return TAB.getInstance().getConfiguration().translation.getString(key);
|
||||
return TAB.getInstance().getConfiguration().getTranslation().getString(key);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -171,4 +172,20 @@ public abstract class SubCommand {
|
||||
* @param args - arguments of the command
|
||||
*/
|
||||
public abstract void execute(TabPlayer sender, String[] args);
|
||||
|
||||
public static String[] getAllProperties() {
|
||||
return allProperties;
|
||||
}
|
||||
|
||||
public static void setAllProperties(String[] allProperties) {
|
||||
SubCommand.allProperties = allProperties;
|
||||
}
|
||||
|
||||
public Map<String, SubCommand> getSubcommands() {
|
||||
return subcommands;
|
||||
}
|
||||
|
||||
public void setSubcommands(Map<String, SubCommand> subcommands) {
|
||||
this.subcommands = subcommands;
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import java.util.Set;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import me.neznamy.tab.shared.PropertyUtils;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.command.level1.AnnounceCommand;
|
||||
import me.neznamy.tab.shared.command.level1.BossBarCommand;
|
||||
@@ -55,18 +56,18 @@ public class TabCommand extends SubCommand {
|
||||
if (tab.isPremium()) {
|
||||
registerSubCommand(new ScoreboardCommand());
|
||||
}
|
||||
Set<String> properties = Sets.newHashSet("tabprefix", "tabsuffix", "tagprefix", "tagsuffix", "customtabname", "abovename", "belowname", "customtagname");
|
||||
for (Object line : ((DebugCommand)subcommands.get("debug")).getExtraLines()) {
|
||||
Set<String> properties = Sets.newHashSet(PropertyUtils.TABPREFIX, PropertyUtils.TABSUFFIX, PropertyUtils.TAGPREFIX, PropertyUtils.TAGSUFFIX, PropertyUtils.CUSTOMTABNAME, PropertyUtils.ABOVENAME, PropertyUtils.BELOWNAME, PropertyUtils.CUSTOMTAGNAME);
|
||||
for (Object line : ((DebugCommand)getSubcommands().get("debug")).getExtraLines()) {
|
||||
properties.add(line.toString());
|
||||
}
|
||||
SubCommand.allProperties = properties.toArray(new String[0]);
|
||||
SubCommand.setAllProperties(properties.toArray(new String[0]));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(TabPlayer sender, String[] args) {
|
||||
if (args.length > 0) {
|
||||
String arg0 = args[0];
|
||||
SubCommand command = subcommands.get(arg0.toLowerCase());
|
||||
SubCommand command = getSubcommands().get(arg0.toLowerCase());
|
||||
if (command != null) {
|
||||
if (command.hasPermission(sender)) {
|
||||
command.execute(sender, Arrays.copyOfRange(args, 1, args.length));
|
||||
@@ -89,22 +90,23 @@ public class TabCommand extends SubCommand {
|
||||
if (sender == null) tab.getPlatform().sendConsoleMessage("&3TAB v" + tab.getPluginVersion(), true);
|
||||
if ((sender == null || sender.hasPermission("tab.admin"))) {
|
||||
String command = tab.getPlatform().getSeparatorType().equals("world") ? "/tab" : "/btab";
|
||||
String prefix = " &8>> &3&l";
|
||||
sendMessage(sender, "&m ");
|
||||
sendMessage(sender, " &8>> &3&l" + command + " reload");
|
||||
sendMessage(sender, prefix + command + " reload");
|
||||
sendMessage(sender, " - &7Reloads plugin and config");
|
||||
sendMessage(sender, " &8>> &3&l" + command + " &9group&3/&9player &3<name> &9<property> &3<value...>");
|
||||
sendMessage(sender, prefix + command + " &9group&3/&9player &3<name> &9<property> &3<value...>");
|
||||
sendMessage(sender, " - &7Do &8/tab group/player &7to show properties");
|
||||
sendMessage(sender, " &8>> &3&l" + command + " ntpreview");
|
||||
sendMessage(sender, prefix + command + " ntpreview");
|
||||
sendMessage(sender, " - &7Shows your nametag for yourself, for testing purposes");
|
||||
sendMessage(sender, " &8>> &3&l" + command + " announce bar &3<name> &9<seconds>");
|
||||
sendMessage(sender, prefix + command + " announce bar &3<name> &9<seconds>");
|
||||
sendMessage(sender, " - &7Temporarily displays bossbar to all players");
|
||||
sendMessage(sender, " &8>> &3&l" + command + " parse <placeholder> ");
|
||||
sendMessage(sender, prefix + command + " parse <placeholder> ");
|
||||
sendMessage(sender, " - &7Test if a placeholder works");
|
||||
sendMessage(sender, " &8>> &3&l" + command + " debug [player]");
|
||||
sendMessage(sender, prefix + command + " debug [player]");
|
||||
sendMessage(sender, " - &7displays debug information about player");
|
||||
sendMessage(sender, " &8>> &3&l" + command + " cpu");
|
||||
sendMessage(sender, prefix + command + " cpu");
|
||||
sendMessage(sender, " - &7shows CPU usage of the plugin");
|
||||
sendMessage(sender, " &8>> &4&l" + command + " group/player <name> remove");
|
||||
sendMessage(sender, prefix + command + " group/player <name> remove");
|
||||
sendMessage(sender, " - &7Clears all data about player/group");
|
||||
sendMessage(sender, "&m ");
|
||||
}
|
||||
@@ -112,7 +114,7 @@ public class TabCommand extends SubCommand {
|
||||
|
||||
@Override
|
||||
public List<String> complete(TabPlayer sender, String[] arguments) {
|
||||
if (!hasPermission(sender, "tab.tabcomplete")) return new ArrayList<String>();
|
||||
if (!hasPermission(sender, "tab.tabcomplete")) return new ArrayList<>();
|
||||
return super.complete(sender, arguments);
|
||||
}
|
||||
}
|
||||
@@ -17,8 +17,8 @@ public class AnnounceCommand extends SubCommand {
|
||||
*/
|
||||
public AnnounceCommand() {
|
||||
super("announce", null);
|
||||
subcommands.put("bar", new AnnounceBarCommand());
|
||||
subcommands.put("scoreboard", new AnnounceScoreboardCommand());
|
||||
getSubcommands().put("bar", new AnnounceBarCommand());
|
||||
getSubcommands().put("scoreboard", new AnnounceScoreboardCommand());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -29,7 +29,7 @@ public class AnnounceCommand extends SubCommand {
|
||||
return;
|
||||
}
|
||||
String arg0 = args[0].toLowerCase();
|
||||
SubCommand command = subcommands.get(arg0);
|
||||
SubCommand command = getSubcommands().get(arg0);
|
||||
if (command != null) {
|
||||
if (command.hasPermission(sender)) {
|
||||
command.execute(sender, Arrays.copyOfRange(args, 1, args.length));
|
||||
|
||||
@@ -28,7 +28,7 @@ public class BossBarCommand extends SubCommand{
|
||||
sendMessage(sender, "&cThis command must be ran from the game");
|
||||
return;
|
||||
}
|
||||
if (!bossbar.permToToggle || sender.hasPermission("tab.togglebar")) {
|
||||
if (!bossbar.isPermToToggle() || sender.hasPermission("tab.togglebar")) {
|
||||
sender.setBossbarVisible(!sender.hasBossbarVisible(), true);
|
||||
} else {
|
||||
sender.sendMessage(getTranslation("no_permission"), true);
|
||||
|
||||
@@ -21,8 +21,8 @@ public class CpuCommand extends SubCommand {
|
||||
|
||||
private final DecimalFormat decimal3 = new DecimalFormat("#.###");
|
||||
|
||||
private final char LINE_CHAR = (char)9553;
|
||||
private final String SEPARATOR = "&8&l" + LINE_CHAR + "&8&m ";
|
||||
private static final char LINE_CHAR = (char)9553;
|
||||
private static final String SEPARATOR = "&8&l" + LINE_CHAR + "&8&m ";
|
||||
|
||||
/**
|
||||
* Constructs new instance
|
||||
@@ -59,21 +59,21 @@ public class CpuCommand extends SubCommand {
|
||||
for (Entry<String, Float> entry : placeholders.entrySet()) {
|
||||
if (printCounter++ == 5) break;
|
||||
String refresh = "";
|
||||
Placeholder p = TAB.getInstance().getPlaceholderManager().getPlaceholder(entry.getKey().toString());
|
||||
Placeholder p = TAB.getInstance().getPlaceholderManager().getPlaceholder(entry.getKey());
|
||||
if (p != null) refresh = " &8(" + p.getRefresh() + ")&7";
|
||||
sendMessage(sender, String.format("&8&l" + LINE_CHAR + " &7%s - %s%%", entry.getKey() + refresh, colorize(decimal3.format(entry.getValue()), 1, 0.3f)));
|
||||
sendMessage(sender, String.format("&8&l%s &7%s - %s%%", LINE_CHAR, entry.getKey() + refresh, colorize(decimal3.format(entry.getValue()), 1, 0.3f)));
|
||||
}
|
||||
sendMessage(sender, SEPARATOR);
|
||||
sendMessage(sender, "&8&l" + LINE_CHAR + " &6Some internal separately measured methods:");
|
||||
for (Entry<String, Float> entry : tab.getCPUManager().getMethodUsage().entrySet()) {
|
||||
sendMessage(sender, String.format("&8&l" + LINE_CHAR + " &7%s: %s%%", entry.getKey(), colorize(decimal3.format(entry.getValue()), 5, 2)));
|
||||
sendMessage(sender, String.format("&8&l%s &7%s: %s%%", LINE_CHAR, entry.getKey(), colorize(decimal3.format(entry.getValue()), 5, 2)));
|
||||
}
|
||||
sendMessage(sender, SEPARATOR);
|
||||
if (tab.getPlatform().getSeparatorType().equals("server")) {
|
||||
sendMessage(sender, "&8&l" + LINE_CHAR + " &6Placeholder usage on Bukkit servers:");
|
||||
for (Entry<String, Float> entry : bridgeplaceholders.entrySet()) {
|
||||
if (entry.getValue() < 0.1) continue;
|
||||
sendMessage(sender, String.format("&8&l" + LINE_CHAR + " &7%s - %s%%", entry.getKey(), colorize(decimal3.format(entry.getValue()), 1, 0.3f)));
|
||||
sendMessage(sender, String.format("&8&l%s &7%s - %s%%", LINE_CHAR, entry.getKey(), colorize(decimal3.format(entry.getValue()), 1, 0.3f)));
|
||||
}
|
||||
sendMessage(sender, SEPARATOR);
|
||||
}
|
||||
@@ -83,18 +83,18 @@ public class CpuCommand extends SubCommand {
|
||||
sendToConsole(features);
|
||||
}
|
||||
sendMessage(sender, SEPARATOR);
|
||||
sendMessage(sender, String.format("&8&l" + LINE_CHAR + " &7Threads created by the plugin (active/total): &7%s", tab.getCPUManager().getThreadCount()));
|
||||
sendMessage(sender, String.format("&8&l%s &7Threads created by the plugin (active/total): &7%s", LINE_CHAR, tab.getCPUManager().getThreadCount()));
|
||||
if (sender != null) {
|
||||
sendPacketCountToPlayer(sender);
|
||||
} else {
|
||||
sendPacketCountToConsole();
|
||||
}
|
||||
sendMessage(sender, String.format("&8&l" + LINE_CHAR + " &6&lPlaceholders Total: &a&l%s%%", colorize(decimal3.format(placeholdersTotal), 10, 5)));
|
||||
sendMessage(sender, String.format("&8&l%s &6&lPlaceholders Total: &a&l%s%%", LINE_CHAR, colorize(decimal3.format(placeholdersTotal), 10, 5)));
|
||||
if (tab.getPlatform().getSeparatorType().equals("server")) {
|
||||
sendMessage(sender, String.format("&8&l" + LINE_CHAR + " &6&lBukkit bridge placeholders Total: &a&l%s%%", colorize(decimal3.format(bridgeplaceholdersTotal), 10, 5)));
|
||||
sendMessage(sender, String.format("&8&l%s &6&lBukkit bridge placeholders Total: &a&l%s%%", LINE_CHAR, colorize(decimal3.format(bridgeplaceholdersTotal), 10, 5)));
|
||||
}
|
||||
sendMessage(sender, String.format("&8&l" + LINE_CHAR + " &6&lPlugin internals: &a&l%s%%", colorize(decimal3.format(featuresTotal-placeholdersTotal), 10, 5)));
|
||||
sendMessage(sender, String.format("&8&l" + LINE_CHAR + " &6&lTotal: &e&l%s%%", colorize(decimal3.format(featuresTotal + bridgeplaceholdersTotal), 10, 5)));
|
||||
sendMessage(sender, String.format("&8&l%s &6&lPlugin internals: &a&l%s%%", LINE_CHAR, colorize(decimal3.format(featuresTotal-placeholdersTotal), 10, 5)));
|
||||
sendMessage(sender, String.format("&8&l%s &6&lTotal: &e&l%s%%", LINE_CHAR, colorize(decimal3.format(featuresTotal + bridgeplaceholdersTotal), 10, 5)));
|
||||
sendMessage(sender, "&8&l" + LINE_CHAR + "&8&m &r&8&l[ &bTAB CPU Stats &8&l]&r&8&l&m ");
|
||||
sendMessage(sender, " ");
|
||||
}
|
||||
@@ -106,10 +106,10 @@ public class CpuCommand extends SubCommand {
|
||||
for (Float f : entry.getValue().values()) {
|
||||
featureTotal += f;
|
||||
}
|
||||
String core = String.format("&8&l" + LINE_CHAR + " &7%s (%s%%&7):", entry.getKey(), colorize(decimal3.format(featureTotal), 5, 1));
|
||||
List<String> messages = new ArrayList<String>();
|
||||
String core = String.format("&8&l%s &7%s (%s%%&7):", LINE_CHAR, entry.getKey(), colorize(decimal3.format(featureTotal), 5, 1));
|
||||
List<String> messages = new ArrayList<>();
|
||||
for (Entry<UsageType, Float> type : entry.getValue().entrySet()){
|
||||
messages.add(String.format("&8&l" + LINE_CHAR + " &7%s - %s%%", type.getKey(), colorize(decimal3.format(type.getValue()), 5, 1)));
|
||||
messages.add(String.format("&8&l%s &7%s - %s%%", LINE_CHAR, type.getKey(), colorize(decimal3.format(type.getValue()), 5, 1)));
|
||||
}
|
||||
TAB.getInstance().getPlatform().sendConsoleMessage(core, true);
|
||||
for (String message : messages) {
|
||||
@@ -125,8 +125,8 @@ public class CpuCommand extends SubCommand {
|
||||
for (Float f : entry.getValue().values()) {
|
||||
featureTotal += f;
|
||||
}
|
||||
String core = String.format("&8&l" + LINE_CHAR + " &7%s (%s%%&7):", entry.getKey(), colorize(decimal3.format(featureTotal), 5, 1));
|
||||
List<String> messages = new ArrayList<String>();
|
||||
String core = String.format("&8&l%s &7%s (%s%%&7):", LINE_CHAR, entry.getKey(), colorize(decimal3.format(featureTotal), 5, 1));
|
||||
List<String> messages = new ArrayList<>();
|
||||
for (Entry<UsageType, Float> type : entry.getValue().entrySet()){
|
||||
messages.add("&3" + type.getKey().toString() + " - " + colorize(decimal3.format(type.getValue()), 5, 1) + "%");
|
||||
}
|
||||
@@ -139,7 +139,7 @@ public class CpuCommand extends SubCommand {
|
||||
public void sendPacketCountToConsole() {
|
||||
Map<Object, AtomicInteger> packets = TAB.getInstance().getCPUManager().getSentPackets();
|
||||
int count = 0;
|
||||
List<String> messages = new ArrayList<String>();
|
||||
List<String> messages = new ArrayList<>();
|
||||
for (Entry<Object, AtomicInteger> entry : packets.entrySet()) {
|
||||
count += entry.getValue().get();
|
||||
messages.add("&8&l" + LINE_CHAR + " &7" + entry.getKey().toString() + " - " + entry.getValue());
|
||||
@@ -153,7 +153,7 @@ public class CpuCommand extends SubCommand {
|
||||
public void sendPacketCountToPlayer(TabPlayer sender) {
|
||||
Map<Object, AtomicInteger> packets = TAB.getInstance().getCPUManager().getSentPackets();
|
||||
int count = 0;
|
||||
List<String> messages = new ArrayList<String>();
|
||||
List<String> messages = new ArrayList<>();
|
||||
for (Entry<Object, AtomicInteger> entry : packets.entrySet()) {
|
||||
count += entry.getValue().get();
|
||||
messages.add("&3" + entry.getKey().toString() + " - " + entry.getValue());
|
||||
|
||||
@@ -19,15 +19,12 @@ public class CpuTestCommand extends SubCommand {
|
||||
|
||||
@Override
|
||||
public void execute(TabPlayer sender, String[] args) {
|
||||
new Thread(new Runnable() {
|
||||
new Thread(() -> {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
sendMessage(sender, "&9Performing CPU test");
|
||||
long time = System.currentTimeMillis();
|
||||
test();
|
||||
sendMessage(sender, "&9Task took &6" + (System.currentTimeMillis()-time) + "ms &9to process");
|
||||
}
|
||||
sendMessage(sender, "&9Performing CPU test");
|
||||
long time = System.currentTimeMillis();
|
||||
test();
|
||||
sendMessage(sender, "&9Task took &6" + (System.currentTimeMillis()-time) + "ms &9to process");
|
||||
}).start();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package me.neznamy.tab.shared.command.level1;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -8,11 +9,13 @@ import com.google.common.collect.Lists;
|
||||
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import me.neznamy.tab.shared.Property;
|
||||
import me.neznamy.tab.shared.PropertyUtils;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.command.SubCommand;
|
||||
import me.neznamy.tab.shared.features.GroupRefresher;
|
||||
import me.neznamy.tab.shared.features.NameTag;
|
||||
import me.neznamy.tab.shared.features.Playerlist;
|
||||
import me.neznamy.tab.shared.features.sorting.types.GroupPermission;
|
||||
|
||||
/**
|
||||
* Handler for "/tab debug" subcommand
|
||||
@@ -49,28 +52,30 @@ public class DebugCommand extends SubCommand {
|
||||
*/
|
||||
private void debug(TabPlayer sender, TabPlayer analyzed) {
|
||||
TAB tab = TAB.getInstance();
|
||||
String separator = "&7&m>-------------------------------<";
|
||||
sendMessage(sender, "&3[TAB] &a&lShowing debug information");
|
||||
sendMessage(sender, "&7&m>-------------------------------<");
|
||||
sendMessage(sender, separator);
|
||||
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");
|
||||
if (tab.getErrorManager().getErrorLog().exists()) {
|
||||
sendMessage(sender, "&6" + tab.getErrorManager().getErrorLog().getPath() + " size: &c" + tab.getErrorManager().getErrorLog().length()/1024 + "KB");
|
||||
}
|
||||
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>-------------------------------<");
|
||||
sendMessage(sender, separator);
|
||||
if (analyzed == null) return;
|
||||
sendMessage(sender, "&ePlayer: &a" + analyzed.getName());
|
||||
sendMessage(sender, getGroup(analyzed));
|
||||
sendMessage(sender, getTeamName(analyzed));
|
||||
sendMessage(sender, getTeamNameNote(analyzed));
|
||||
if (tab.getFeatureManager().isFeatureEnabled("playerlist")) {
|
||||
Playerlist playerlist = (Playerlist) tab.getFeatureManager().getFeature("playerlist");
|
||||
boolean disabledPlayerlist = playerlist.isDisabledWorld(playerlist.disabledWorlds, analyzed.getWorldName());
|
||||
showProperty(sender, analyzed, "tabprefix", disabledPlayerlist);
|
||||
showProperty(sender, analyzed, "tabsuffix", disabledPlayerlist);
|
||||
showProperty(sender, analyzed, "customtabname", disabledPlayerlist);
|
||||
boolean disabledPlayerlist = playerlist.isDisabledWorld(playerlist.getDisabledWorlds(), analyzed.getWorldName());
|
||||
showProperty(sender, analyzed, PropertyUtils.TABPREFIX, disabledPlayerlist);
|
||||
showProperty(sender, analyzed, PropertyUtils.TABSUFFIX, disabledPlayerlist);
|
||||
showProperty(sender, analyzed, PropertyUtils.CUSTOMTABNAME, disabledPlayerlist);
|
||||
} else {
|
||||
sendMessage(sender, "&atabprefix: &cDisabled");
|
||||
sendMessage(sender, "&atabsuffix: &cDisabled");
|
||||
@@ -78,8 +83,8 @@ public class DebugCommand extends SubCommand {
|
||||
}
|
||||
if (tab.getFeatureManager().getNameTagFeature() != null) {
|
||||
boolean disabledNametags = tab.getFeatureManager().getNameTagFeature().isDisabledWorld(analyzed.getWorldName());
|
||||
showProperty(sender, analyzed, "tagprefix", disabledNametags);
|
||||
showProperty(sender, analyzed, "tagsuffix", disabledNametags);
|
||||
showProperty(sender, analyzed, PropertyUtils.TAGPREFIX, disabledNametags);
|
||||
showProperty(sender, analyzed, PropertyUtils.TAGSUFFIX, disabledNametags);
|
||||
for (Object line : getExtraLines()) {
|
||||
showProperty(sender, analyzed, line.toString(), disabledNametags);
|
||||
}
|
||||
@@ -87,7 +92,7 @@ public class DebugCommand extends SubCommand {
|
||||
sendMessage(sender, "&atagprefix: &cDisabled");
|
||||
sendMessage(sender, "&atagsuffix: &cDisabled");
|
||||
}
|
||||
sendMessage(sender, "&7&m>-------------------------------<");
|
||||
sendMessage(sender, separator);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,9 +101,9 @@ public class DebugCommand extends SubCommand {
|
||||
*/
|
||||
private String getGroupChoiceLogic() {
|
||||
GroupRefresher group = (GroupRefresher) TAB.getInstance().getFeatureManager().getFeature("group");
|
||||
if (group.groupsByPermissions) {
|
||||
if (group.isGroupsByPermissions()) {
|
||||
return "Permissions";
|
||||
} else if (group.usePrimaryGroup) {
|
||||
} else if (group.isUsePrimaryGroup()) {
|
||||
return "Primary group";
|
||||
} else {
|
||||
return "Choose from list";
|
||||
@@ -113,12 +118,12 @@ public class DebugCommand extends SubCommand {
|
||||
NameTag nametag = TAB.getInstance().getFeatureManager().getNameTagFeature();
|
||||
if (nametag != null) {
|
||||
if (TAB.getInstance().isPremium()) {
|
||||
String sortingType = nametag.sorting.typesToString();
|
||||
String sortingType = nametag.getSorting().typesToString();
|
||||
if (sortingType.contains("PLACEHOLDER")) {
|
||||
sortingType += " - " + nametag.sorting.sortingPlaceholder;
|
||||
sortingType += " - " + nametag.getSorting().getSortingPlaceholder();
|
||||
}
|
||||
return sortingType;
|
||||
} else if (nametag.sorting.sorting.get(0).getClass().getSimpleName().equals("GroupPermission")) {
|
||||
} else if (nametag.getSorting().getSorting().get(0) instanceof GroupPermission) {
|
||||
return "Permissions &c(this option was enabled by user, it is disabled by default!)";
|
||||
} else {
|
||||
return "Groups";
|
||||
@@ -135,14 +140,14 @@ public class DebugCommand extends SubCommand {
|
||||
*/
|
||||
private String getGroup(TabPlayer analyzed) {
|
||||
GroupRefresher group = (GroupRefresher) TAB.getInstance().getFeatureManager().getFeature("group");
|
||||
if (group.groupsByPermissions) {
|
||||
if (group.isGroupsByPermissions()) {
|
||||
return "&eHighest permission for group: &a" + analyzed.getGroup();
|
||||
} else if (group.usePrimaryGroup) {
|
||||
} else if (group.isUsePrimaryGroup()) {
|
||||
return "&ePrimary permission group: &a" + analyzed.getGroup();
|
||||
} else {
|
||||
try {
|
||||
return "&eFull permission group list: &a" + Arrays.toString(TAB.getInstance().getPermissionPlugin().getAllGroups(analyzed)) + "\n&eChosen group: &a" + analyzed.getGroup();
|
||||
} catch (Throwable e) {
|
||||
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException | SecurityException | ClassNotFoundException e) {
|
||||
return "&eFull permission group list: &a[]\n&eChosen group: &a" + analyzed.getGroup();
|
||||
}
|
||||
}
|
||||
@@ -158,29 +163,41 @@ public class DebugCommand extends SubCommand {
|
||||
if (TAB.getInstance().getFeatureManager().getNameTagFeature().isDisabledWorld(analyzed.getWorldName())) {
|
||||
return "&eTeam name: &cSorting is disabled in player's " + TAB.getInstance().getPlatform().getSeparatorType();
|
||||
} else {
|
||||
String s = "&eTeam name: &a" + analyzed.getTeamName();
|
||||
if (analyzed.getTeamNameNote() != null) s += "\n&eTeam name note: &a" + analyzed.getTeamNameNote();
|
||||
return s;
|
||||
return "&eTeam name: &a" + analyzed.getTeamName();
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns team name note of specified player
|
||||
* @param analyzed - player to get team name note of
|
||||
* @return team name note of specified player
|
||||
*/
|
||||
private String getTeamNameNote(TabPlayer analyzed) {
|
||||
if (TAB.getInstance().getFeatureManager().getNameTagFeature() != null &&
|
||||
!TAB.getInstance().getFeatureManager().getNameTagFeature().isDisabledWorld(analyzed.getWorldName()) &&
|
||||
analyzed.getTeamNameNote() != null)
|
||||
return "&eTeam name note: &a" + analyzed.getTeamNameNote();
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of extra properties if unlimited nametag mode is enabled
|
||||
* @return list of extra properties
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Object> getExtraLines(){
|
||||
if (!TAB.getInstance().getFeatureManager().isFeatureEnabled("nametagx")) return new ArrayList<Object>();
|
||||
if (!TAB.getInstance().getFeatureManager().isFeatureEnabled("nametagx")) return new ArrayList<>();
|
||||
if (TAB.getInstance().isPremium()) {
|
||||
List<Object> lines = Lists.newArrayList((List<Object>) TAB.getInstance().getConfiguration().premiumconfig.getObject("unlimited-nametag-mode-dynamic-lines"));
|
||||
lines.addAll(TAB.getInstance().getConfiguration().premiumconfig.getConfigurationSection("unlimited-nametag-mode-static-lines").keySet());
|
||||
lines.remove("nametag");
|
||||
lines.add("customtagname");
|
||||
List<Object> lines = Lists.newArrayList((List<Object>) TAB.getInstance().getConfiguration().getPremiumConfig().getObject("unlimited-nametag-mode-dynamic-lines"));
|
||||
lines.addAll(TAB.getInstance().getConfiguration().getPremiumConfig().getConfigurationSection("unlimited-nametag-mode-static-lines").keySet());
|
||||
lines.remove(PropertyUtils.NAMETAG);
|
||||
lines.add(PropertyUtils.CUSTOMTAGNAME);
|
||||
return lines;
|
||||
} else {
|
||||
return Arrays.asList("customtagname", "belowname", "abovename");
|
||||
return Arrays.asList(PropertyUtils.CUSTOMTAGNAME, PropertyUtils.BELOWNAME, PropertyUtils.ABOVENAME);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,6 +222,6 @@ public class DebugCommand extends SubCommand {
|
||||
|
||||
@Override
|
||||
public List<String> complete(TabPlayer sender, String[] arguments) {
|
||||
return arguments.length == 1 ? getPlayers(arguments[0]) : new ArrayList<String>();
|
||||
return arguments.length == 1 ? getPlayers(arguments[0]) : new ArrayList<>();
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,14 @@
|
||||
package me.neznamy.tab.shared.command.level1;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.command.SubCommand;
|
||||
|
||||
/**
|
||||
* Handler for "/tab group" subcommand
|
||||
*/
|
||||
public class GroupCommand extends SubCommand {
|
||||
public class GroupCommand extends PropertyCommand {
|
||||
|
||||
/**
|
||||
* Constructs new instance
|
||||
@@ -29,7 +26,7 @@ public class GroupCommand extends SubCommand {
|
||||
String value = buildArgument(Arrays.copyOfRange(args, 2, args.length));
|
||||
if (type.equals("remove")) {
|
||||
if (hasPermission(sender, "tab.remove")) {
|
||||
TAB.getInstance().getConfiguration().config.set("Groups." + group, null);
|
||||
TAB.getInstance().getConfiguration().getConfig().set("Groups." + group, null);
|
||||
for (TabPlayer pl : TAB.getInstance().getPlayers()) {
|
||||
if (pl.getGroup().equals(group) || group.equals("_OTHER_")){
|
||||
pl.forceRefresh();
|
||||
@@ -39,7 +36,7 @@ public class GroupCommand extends SubCommand {
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (String property : allProperties) {
|
||||
for (String property : getAllProperties()) {
|
||||
if (type.equals(property)) {
|
||||
if (hasPermission(sender, "tab.change." + property)) {
|
||||
saveGroup(sender, group, type, value);
|
||||
@@ -73,8 +70,8 @@ public class GroupCommand extends SubCommand {
|
||||
} else {
|
||||
sendMessage(sender, getTranslation("value_removed").replace("%type%", type).replace("%unit%", group).replace("%category%", "group"));
|
||||
}
|
||||
if (String.valueOf(value.length() == 0 ? null : value).equals(String.valueOf(TAB.getInstance().getConfiguration().config.getObject("Groups." + group.replace(".", "@#@") + "." + type)))) return;
|
||||
TAB.getInstance().getConfiguration().config.set("Groups." + group.replace(".", "@#@") + "." + type, value.length() == 0 ? null : value);
|
||||
if (String.valueOf(value.length() == 0 ? null : value).equals(String.valueOf(TAB.getInstance().getConfiguration().getConfig().getObject("Groups." + group.replace(".", "@#@") + "." + type)))) return;
|
||||
TAB.getInstance().getConfiguration().getConfig().set("Groups." + group.replace(".", "@#@") + "." + type, value.length() == 0 ? null : value);
|
||||
TAB.getInstance().getPlaceholderManager().checkForRegistration(value);
|
||||
for (TabPlayer pl : TAB.getInstance().getPlayers()) {
|
||||
if (pl.getGroup().equals(group) || group.equals("_OTHER_")){
|
||||
@@ -82,15 +79,4 @@ public class GroupCommand extends SubCommand {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> complete(TabPlayer sender, String[] arguments) {
|
||||
List<String> suggestions = new ArrayList<String>();
|
||||
if (arguments.length == 2) {
|
||||
for (String property : allProperties) {
|
||||
if (property.startsWith(arguments[1].toLowerCase())) suggestions.add(property);
|
||||
}
|
||||
}
|
||||
return suggestions;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package me.neznamy.tab.shared.command.level1;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@@ -29,7 +28,7 @@ public class PlayerCommand extends SubCommand {
|
||||
String value = buildArgument(Arrays.copyOfRange(args, 2, args.length));
|
||||
if (type.equals("remove")) {
|
||||
if (hasPermission(sender, "tab.remove")) {
|
||||
TAB.getInstance().getConfiguration().config.set("Users." + player, null);
|
||||
TAB.getInstance().getConfiguration().getConfig().set("Users." + player, null);
|
||||
TabPlayer pl = TAB.getInstance().getPlayer(player);
|
||||
if (pl != null) {
|
||||
pl.forceRefresh();
|
||||
@@ -38,7 +37,7 @@ public class PlayerCommand extends SubCommand {
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (String property : allProperties) {
|
||||
for (String property : getAllProperties()) {
|
||||
if (type.equals(property)) {
|
||||
if (hasPermission(sender, "tab.change." + property)) {
|
||||
savePlayer(sender, player, type, value);
|
||||
@@ -72,8 +71,8 @@ public class PlayerCommand extends SubCommand {
|
||||
} else {
|
||||
sendMessage(sender, getTranslation("value_removed").replace("%type%", type).replace("%unit%", player).replace("%category%", "player"));
|
||||
}
|
||||
if (String.valueOf(value.length() == 0 ? null : value).equals(String.valueOf(TAB.getInstance().getConfiguration().config.getObject("Users." + player + "." + type)))) return;
|
||||
TAB.getInstance().getConfiguration().config.set("Users." + player + "." + type, value.length() == 0 ? null : value);
|
||||
if (String.valueOf(value.length() == 0 ? null : value).equals(String.valueOf(TAB.getInstance().getConfiguration().getConfig().getObject("Users." + player + "." + type)))) return;
|
||||
TAB.getInstance().getConfiguration().getConfig().set("Users." + player + "." + type, value.length() == 0 ? null : value);
|
||||
TAB.getInstance().getPlaceholderManager().checkForRegistration(value);
|
||||
TabPlayer pl = TAB.getInstance().getPlayer(player);
|
||||
if (pl != null) {
|
||||
@@ -84,12 +83,6 @@ public class PlayerCommand extends SubCommand {
|
||||
@Override
|
||||
public List<String> complete(TabPlayer sender, String[] arguments) {
|
||||
if (arguments.length == 1) return getPlayers(arguments[0]);
|
||||
List<String> suggestions = new ArrayList<String>();
|
||||
if (arguments.length == 2) {
|
||||
for (String property : allProperties) {
|
||||
if (property.startsWith(arguments[1].toLowerCase())) suggestions.add(property);
|
||||
}
|
||||
}
|
||||
return suggestions;
|
||||
return super.complete(sender, arguments);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package me.neznamy.tab.shared.command.level1;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@@ -34,13 +33,13 @@ public class PlayerUUIDCommand extends SubCommand {
|
||||
String value = buildArgument(Arrays.copyOfRange(args, 2, args.length));
|
||||
if (type.equals("remove")) {
|
||||
if (hasPermission(sender, "tab.remove")) {
|
||||
TAB.getInstance().getConfiguration().config.set("Users." + changed.getUniqueId().toString(), null);
|
||||
TAB.getInstance().getConfiguration().getConfig().set("Users." + changed.getUniqueId().toString(), null);
|
||||
changed.forceRefresh();
|
||||
sendMessage(sender, getTranslation("data_removed").replace("%category%", "player").replace("%value%", changed.getName() + "(" + changed.getUniqueId().toString() + ")"));
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (String property : allProperties) {
|
||||
for (String property : getAllProperties()) {
|
||||
if (type.equals(property)) {
|
||||
if (hasPermission(sender, "tab.change." + property)) {
|
||||
savePlayer(sender, changed, type, value);
|
||||
@@ -74,8 +73,8 @@ public class PlayerUUIDCommand extends SubCommand {
|
||||
} else {
|
||||
sendMessage(sender, getTranslation("value_removed").replace("%type%", type).replace("%unit%", player.getName() + "(" + player.getUniqueId().toString() + ")").replace("%category%", "UUID"));
|
||||
}
|
||||
if (String.valueOf(value.length() == 0 ? null : value).equals(String.valueOf(TAB.getInstance().getConfiguration().config.getObject("Users." + player.getUniqueId() + "." + type)))) return;
|
||||
TAB.getInstance().getConfiguration().config.set("Users." + player.getUniqueId() + "." + type, value.length() == 0 ? null : value);
|
||||
if (String.valueOf(value.length() == 0 ? null : value).equals(String.valueOf(TAB.getInstance().getConfiguration().getConfig().getObject("Users." + player.getUniqueId() + "." + type)))) return;
|
||||
TAB.getInstance().getConfiguration().getConfig().set("Users." + player.getUniqueId() + "." + type, value.length() == 0 ? null : value);
|
||||
TAB.getInstance().getPlaceholderManager().checkForRegistration(value);
|
||||
player.forceRefresh();
|
||||
}
|
||||
@@ -83,12 +82,6 @@ public class PlayerUUIDCommand extends SubCommand {
|
||||
@Override
|
||||
public List<String> complete(TabPlayer sender, String[] arguments) {
|
||||
if (arguments.length == 1) return getPlayers(arguments[0]);
|
||||
List<String> suggestions = new ArrayList<String>();
|
||||
if (arguments.length == 2) {
|
||||
for (String property : allProperties) {
|
||||
if (property.startsWith(arguments[1].toLowerCase())) suggestions.add(property);
|
||||
}
|
||||
}
|
||||
return suggestions;
|
||||
return super.complete(sender, arguments);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package me.neznamy.tab.shared.command.level1;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import me.neznamy.tab.shared.command.SubCommand;
|
||||
|
||||
public abstract class PropertyCommand extends SubCommand {
|
||||
|
||||
protected PropertyCommand(String name, String permission) {
|
||||
super(name, permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> complete(TabPlayer sender, String[] arguments) {
|
||||
List<String> suggestions = new ArrayList<>();
|
||||
if (arguments.length == 2) {
|
||||
for (String property : getAllProperties()) {
|
||||
if (property.startsWith(arguments[1].toLowerCase())) suggestions.add(property);
|
||||
}
|
||||
}
|
||||
return suggestions;
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ public class ReloadCommand extends SubCommand {
|
||||
TAB.getInstance().load();
|
||||
if (TAB.getInstance().isDisabled()) {
|
||||
if (sender != null) {
|
||||
sendMessage(sender, TAB.getInstance().getConfiguration().reloadFailed.replace("%file%", TAB.getInstance().brokenFile));
|
||||
sendMessage(sender, TAB.getInstance().getConfiguration().getReloadFailedMessage().replace("%file%", TAB.getInstance().getBrokenFile()));
|
||||
}
|
||||
} else {
|
||||
sendMessage(sender, getTranslation("reloaded"));
|
||||
|
||||
@@ -25,7 +25,7 @@ public class ScoreboardCommand extends SubCommand {
|
||||
sendMessage(sender, "&cScoreboard feature is not enabled, therefore toggle command cannot be used.");
|
||||
return;
|
||||
}
|
||||
if (scoreboard.permToToggle && !hasPermission(sender, "tab.togglescoreboard")) {
|
||||
if (scoreboard.isPermToToggle() && !hasPermission(sender, "tab.togglescoreboard")) {
|
||||
sendMessage(sender, getTranslation("no_permission"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -16,14 +16,14 @@ public class SendCommand extends SubCommand {
|
||||
*/
|
||||
public SendCommand() {
|
||||
super("send", null);
|
||||
subcommands.put("bar", new SendBarCommand());
|
||||
getSubcommands().put("bar", new SendBarCommand());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(TabPlayer sender, String[] args) {
|
||||
if (args.length > 0) {
|
||||
String arg0 = args[0].toLowerCase();
|
||||
SubCommand command = subcommands.get(arg0);
|
||||
SubCommand command = getSubcommands().get(arg0);
|
||||
if (command != null) {
|
||||
if (command.hasPermission(sender)) {
|
||||
command.execute(sender, Arrays.copyOfRange(args, 1, args.length));
|
||||
|
||||
@@ -41,29 +41,29 @@ public class AnnounceBarCommand extends SubCommand{
|
||||
sendMessage(sender, args[1] + " is not a number!");
|
||||
return;
|
||||
}
|
||||
BossBarLine bar = feature.lines.get(barname);
|
||||
BossBarLine bar = feature.getLines().get(barname);
|
||||
if (bar == null) {
|
||||
sendMessage(sender, "Bar not found");
|
||||
return;
|
||||
}
|
||||
new Thread(() -> {
|
||||
try {
|
||||
feature.announcements.add(barname);
|
||||
feature.announceEndTime = System.currentTimeMillis() + duration*1000;
|
||||
feature.getAnnouncements().add(barname);
|
||||
feature.setAnnounceEndTime(System.currentTimeMillis() + duration*1000);
|
||||
for (TabPlayer all : TAB.getInstance().getPlayers()) {
|
||||
if (!all.hasBossbarVisible()) continue;
|
||||
bar.create(all);
|
||||
all.getActiveBossBars().add(bar);
|
||||
}
|
||||
Thread.sleep(duration*1000);
|
||||
Thread.sleep(duration*1000L);
|
||||
for (TabPlayer all : TAB.getInstance().getPlayers()) {
|
||||
if (!all.hasBossbarVisible()) continue;
|
||||
bar.remove(all);
|
||||
all.getActiveBossBars().remove(bar);
|
||||
}
|
||||
feature.announcements.remove(barname);
|
||||
} catch (Exception e) {
|
||||
|
||||
feature.getAnnouncements().remove(barname);
|
||||
} catch (InterruptedException pluginDisabled) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
@@ -71,13 +71,13 @@ public class AnnounceBarCommand extends SubCommand{
|
||||
@Override
|
||||
public List<String> complete(TabPlayer sender, String[] arguments) {
|
||||
BossBar b = (BossBar) TAB.getInstance().getFeatureManager().getFeature("bossbar");
|
||||
if (b == null) return new ArrayList<String>();
|
||||
List<String> suggestions = new ArrayList<String>();
|
||||
if (b == null) return new ArrayList<>();
|
||||
List<String> suggestions = new ArrayList<>();
|
||||
if (arguments.length == 1) {
|
||||
for (String bar : b.lines.keySet()) {
|
||||
for (String bar : b.getLines().keySet()) {
|
||||
if (bar.toLowerCase().startsWith(arguments[0].toLowerCase())) suggestions.add(bar);
|
||||
}
|
||||
} else if (arguments.length == 2 && b.lines.get(arguments[0]) != null){
|
||||
} else if (arguments.length == 2 && b.getLines().get(arguments[0]) != null){
|
||||
for (String time : Arrays.asList("5", "10", "30", "60", "120")) {
|
||||
if (time.startsWith(arguments[1])) suggestions.add(time);
|
||||
}
|
||||
|
||||
+8
-8
@@ -60,23 +60,23 @@ public class AnnounceScoreboardCommand extends SubCommand{
|
||||
private void announce(ScoreboardManager feature, Scoreboard sb, int duration) {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
feature.announcement = sb;
|
||||
Map<TabPlayer, Scoreboard> previous = new HashMap<TabPlayer, Scoreboard>();
|
||||
feature.setAnnouncement(sb);
|
||||
Map<TabPlayer, Scoreboard> previous = new HashMap<>();
|
||||
for (TabPlayer all : TAB.getInstance().getPlayers()) {
|
||||
if (!all.isScoreboardVisible()) continue;
|
||||
previous.put(all, all.getActiveScoreboard());
|
||||
if (all.getActiveScoreboard() != null) all.getActiveScoreboard().unregister(all);
|
||||
sb.register(all);
|
||||
}
|
||||
Thread.sleep(duration*1000);
|
||||
Thread.sleep(duration*1000L);
|
||||
for (TabPlayer all : TAB.getInstance().getPlayers()) {
|
||||
if (!all.hasBossbarVisible()) continue;
|
||||
sb.unregister(all);
|
||||
if (previous.get(all) != null) previous.get(all).register(all);
|
||||
}
|
||||
feature.announcement = null;
|
||||
} catch (Exception e) {
|
||||
|
||||
feature.setAnnouncement(null);
|
||||
} catch (InterruptedException pluginDisabled) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
@@ -84,8 +84,8 @@ public class AnnounceScoreboardCommand extends SubCommand{
|
||||
@Override
|
||||
public List<String> complete(TabPlayer sender, String[] arguments) {
|
||||
ScoreboardManager s = (ScoreboardManager) TAB.getInstance().getFeatureManager().getFeature("scoreboard");
|
||||
if (s == null) return new ArrayList<String>();
|
||||
List<String> suggestions = new ArrayList<String>();
|
||||
if (s == null) return new ArrayList<>();
|
||||
List<String> suggestions = new ArrayList<>();
|
||||
if (arguments.length == 1) {
|
||||
for (String bar : s.getScoreboards().keySet()) {
|
||||
if (bar.toLowerCase().startsWith(arguments[0].toLowerCase())) suggestions.add(bar);
|
||||
|
||||
@@ -46,7 +46,7 @@ public class SendBarCommand extends SubCommand{
|
||||
sendMessage(sender, args[1] + " is not a number!");
|
||||
return;
|
||||
}
|
||||
BossBarLine bar = feature.lines.get(barname);
|
||||
BossBarLine bar = feature.getLines().get(barname);
|
||||
if (bar == null) {
|
||||
sendMessage(sender, "No bar found with name \"" + bar + "\"");
|
||||
return;
|
||||
@@ -57,13 +57,13 @@ public class SendBarCommand extends SubCommand{
|
||||
bar.create(target);
|
||||
target.getActiveBossBars().add(bar);
|
||||
}
|
||||
Thread.sleep(duration*1000);
|
||||
Thread.sleep(duration*1000L);
|
||||
if (target.hasBossbarVisible()) {
|
||||
bar.remove(target);
|
||||
target.getActiveBossBars().remove(bar);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
||||
} catch (InterruptedException pluginDisabled) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
@@ -71,15 +71,15 @@ public class SendBarCommand extends SubCommand{
|
||||
@Override
|
||||
public List<String> complete(TabPlayer sender, String[] arguments) {
|
||||
BossBar b = (BossBar) TAB.getInstance().getFeatureManager().getFeature("bossbar");
|
||||
if (b == null) return new ArrayList<String>();
|
||||
List<String> suggestions = new ArrayList<String>();
|
||||
if (b == null) return new ArrayList<>();
|
||||
List<String> suggestions = new ArrayList<>();
|
||||
if (arguments.length == 1) {
|
||||
return getPlayers(arguments[0]);
|
||||
} else if (arguments.length == 2) {
|
||||
for (String bar : b.lines.keySet()) {
|
||||
for (String bar : b.getLines().keySet()) {
|
||||
if (bar.toLowerCase().startsWith(arguments[1].toLowerCase())) suggestions.add(bar);
|
||||
}
|
||||
} else if (arguments.length == 3 && b.lines.get(arguments[1]) != null){
|
||||
} else if (arguments.length == 3 && b.getLines().get(arguments[1]) != null){
|
||||
for (String time : Arrays.asList("5", "10", "30", "60", "120")) {
|
||||
if (time.startsWith(arguments[2])) suggestions.add(time);
|
||||
}
|
||||
|
||||
@@ -4,8 +4,10 @@ import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -16,6 +18,8 @@ import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import org.yaml.snakeyaml.error.YAMLException;
|
||||
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
|
||||
/**
|
||||
@@ -24,41 +28,40 @@ import me.neznamy.tab.shared.TAB;
|
||||
public class Configs {
|
||||
|
||||
private TAB tab;
|
||||
|
||||
//config.yml file
|
||||
public ConfigurationFile config;
|
||||
|
||||
//remove-strings option
|
||||
public List<String> removeStrings;
|
||||
|
||||
//config.yml file
|
||||
private ConfigurationFile config;
|
||||
|
||||
private List<String> removeStrings;
|
||||
private boolean bukkitPermissions;
|
||||
|
||||
//hidden config options
|
||||
public boolean rgbSupport;
|
||||
public boolean unregisterBeforeRegister;
|
||||
public String multiWorldSeparator;
|
||||
public String essentialsNickPrefix;
|
||||
public boolean armorStandsAlwaysVisible; //paid private addition
|
||||
public boolean removeGhostPlayers;
|
||||
public boolean layout;
|
||||
public boolean pipelineInjection;
|
||||
public boolean bukkitPermissions;
|
||||
private boolean rgbSupport;
|
||||
private boolean unregisterBeforeRegister;
|
||||
private String multiWorldSeparator;
|
||||
private String essentialsNickPrefix;
|
||||
private boolean armorStandsAlwaysVisible; //paid private addition
|
||||
private boolean removeGhostPlayers;
|
||||
private boolean layout;
|
||||
private boolean pipelineInjection;
|
||||
|
||||
//animations.yml file
|
||||
public ConfigurationFile animation;
|
||||
private ConfigurationFile animation;
|
||||
|
||||
//bossbar.yml file
|
||||
public ConfigurationFile bossbar;
|
||||
private ConfigurationFile bossbar;
|
||||
|
||||
//translation.yml file
|
||||
public ConfigurationFile translation;
|
||||
|
||||
private ConfigurationFile translation;
|
||||
|
||||
//default reload message in case plugin did not load translation file due to an error
|
||||
public String reloadFailed = "&4Failed to reload, file %file% has broken syntax. Check console for more info.";
|
||||
|
||||
private String reloadFailed = "&4Failed to reload, file %file% has broken syntax. Check console for more info.";
|
||||
|
||||
//premiumconfig.yml
|
||||
public ConfigurationFile premiumconfig;
|
||||
private ConfigurationFile premiumconfig;
|
||||
|
||||
//playerdata.yml, used for bossbar & scoreboard toggle saving
|
||||
public ConfigurationFile playerdata;
|
||||
private ConfigurationFile playerdata;
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameter
|
||||
@@ -67,56 +70,41 @@ public class Configs {
|
||||
public Configs(TAB tab) {
|
||||
this.tab = tab;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Loads all configuration files and converts files to latest version
|
||||
* @throws Exception - if I/O file opration fails or some file has broken yaml syntax
|
||||
* @throws IOException
|
||||
* @throws YAMLException
|
||||
*/
|
||||
public void loadFiles() throws Exception {
|
||||
public void loadFiles() throws YAMLException, IOException {
|
||||
ClassLoader loader = Configs.class.getClassLoader();
|
||||
removeAdvancedConfig();
|
||||
loadConfig();
|
||||
animation = new YamlConfigurationFile(loader.getResourceAsStream("animations.yml"), new File(tab.getPlatform().getDataFolder(), "animations.yml"));
|
||||
Map<String, Object> values = animation.getValues();
|
||||
Map<String, Object> values = getAnimationFile().getValues();
|
||||
if (values.size() == 1 && values.containsKey("animations")) {
|
||||
animation.setValues(animation.getConfigurationSection("animations"));
|
||||
animation.save();
|
||||
getAnimationFile().setValues(getAnimationFile().getConfigurationSection("animations"));
|
||||
getAnimationFile().save();
|
||||
TAB.getInstance().print('2', "Converted animations.yml to new format.");
|
||||
}
|
||||
bossbar = new YamlConfigurationFile(loader.getResourceAsStream("bossbar.yml"), new File(tab.getPlatform().getDataFolder(), "bossbar.yml"));
|
||||
translation = new YamlConfigurationFile(loader.getResourceAsStream("translation.yml"), new File(tab.getPlatform().getDataFolder(), "translation.yml"));
|
||||
reloadFailed = translation.getString("reload-failed", "&4Failed to reload, file %file% has broken syntax. Check console for more info.");
|
||||
reloadFailed = getTranslation().getString("reload-failed", "&4Failed to reload, file %file% has broken syntax. Check console for more info.");
|
||||
if (tab.isPremium()) premiumconfig = new YamlConfigurationFile(loader.getResourceAsStream("premiumconfig.yml"), new File(tab.getPlatform().getDataFolder(), "premiumconfig.yml"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Conversion from old advancedconfig.yml file
|
||||
*/
|
||||
private void removeAdvancedConfig() {
|
||||
File f = new File(tab.getPlatform().getDataFolder(), "advancedconfig.yml");
|
||||
if (f.exists()) {
|
||||
List<String> fileLines = readAllLines(f);
|
||||
File config = new File(tab.getPlatform().getDataFolder(), "config.yml");
|
||||
for (String line : fileLines) {
|
||||
if (!line.startsWith("#")) {
|
||||
write(config, line);
|
||||
}
|
||||
}
|
||||
f.delete();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Loads config.yml and some of it's values
|
||||
* @throws Exception - if file has broken syntax or I/O file operation fails
|
||||
* @throws IOException
|
||||
* @throws YAMLException
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void loadConfig() throws Exception {
|
||||
public void loadConfig() throws YAMLException, IOException {
|
||||
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'));
|
||||
for (String s : getConfig().getStringList("placeholders.remove-strings", Arrays.asList("[] ", "< > "))) {
|
||||
getRemoveStrings().add(s.replace('&', '\u00a7'));
|
||||
}
|
||||
tab.debugMode = (boolean) getSecretOption("debug", false);
|
||||
tab.setDebugMode(getConfig().getBoolean("debug", false));
|
||||
rgbSupport = (boolean) getSecretOption("rgb-support", true);
|
||||
unregisterBeforeRegister = (boolean) getSecretOption("unregister-before-register", true);
|
||||
multiWorldSeparator = (String) getSecretOption("multi-world-separator", "-");
|
||||
@@ -126,14 +114,14 @@ public class Configs {
|
||||
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);
|
||||
bukkitPermissions = getConfig().getBoolean("use-bukkit-permissions-manager", false);
|
||||
}
|
||||
|
||||
|
||||
//checking for unnecessary copypaste in config
|
||||
Set<Object> groups = config.getConfigurationSection("Groups").keySet();
|
||||
Set<Object> groups = getConfig().getConfigurationSection("Groups").keySet();
|
||||
if (groups.size() < 2) return;
|
||||
Map<Object, Object> sharedProperties = new HashMap<>(config.getConfigurationSection("Groups." + groups.toArray()[0])); //cloning to not delete from original one
|
||||
for (Object groupSettings : config.getConfigurationSection("Groups").values()) {
|
||||
Map<Object, Object> sharedProperties = new HashMap<>(getConfig().getConfigurationSection("Groups." + groups.toArray()[0])); //cloning to not delete from original one
|
||||
for (Object groupSettings : getConfig().getConfigurationSection("Groups").values()) {
|
||||
if (!(groupSettings instanceof Map)) continue;
|
||||
Map<String, Object> group = (Map<String, Object>) groupSettings;
|
||||
for (Entry<Object, Object> sharedProperty : new HashSet<>(sharedProperties.entrySet())) {
|
||||
@@ -155,11 +143,11 @@ public class Configs {
|
||||
* @return value with specified path or default value if not present
|
||||
*/
|
||||
private Object getSecretOption(String path, Object defaultValue) {
|
||||
if (config == null) return defaultValue;
|
||||
Object value = config.getObject(path);
|
||||
if (getConfig() == null) return defaultValue;
|
||||
Object value = getConfig().getObject(path);
|
||||
return value == null ? defaultValue : value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns player data with specified key
|
||||
* @param key - data key
|
||||
@@ -169,64 +157,132 @@ public class Configs {
|
||||
if (playerdata == null) {
|
||||
File file = new File(tab.getPlatform().getDataFolder(), "playerdata.yml");
|
||||
try {
|
||||
if (!file.exists()) file.createNewFile();
|
||||
playerdata = new YamlConfigurationFile(null, file);
|
||||
if (file.exists() || file.createNewFile()) {
|
||||
playerdata = new YamlConfigurationFile(null, file);
|
||||
return playerdata.getStringList(key, new ArrayList<>());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
tab.getErrorManager().criticalError("Failed to load playerdata.yml", e);
|
||||
return new ArrayList<String>();
|
||||
}
|
||||
} else {
|
||||
return playerdata.getStringList(key, new ArrayList<>());
|
||||
}
|
||||
return playerdata.getStringList(key, new ArrayList<String>());
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns name of world group of specified world in per-server-settings that may consist of multiple
|
||||
* world separated with "-" or something else defined in config
|
||||
* Returns name of world group in specified set that may consist of multiple
|
||||
* worlds separated with "-" or something else defined in config
|
||||
* @param world - name of world to find group of
|
||||
* @return name of world group
|
||||
*/
|
||||
public String getWorldGroupOf(String world) {
|
||||
Map<String, Object> worlds = config.getConfigurationSection("per-" + tab.getPlatform().getSeparatorType() + "-settings");
|
||||
if (worlds.isEmpty()) return world;
|
||||
for (String worldGroup : worlds.keySet()) {
|
||||
for (String localWorld : worldGroup.split(multiWorldSeparator)) {
|
||||
if (localWorld.equalsIgnoreCase(world)) return worldGroup;
|
||||
public String getWorldGroupOf(Set<?> groups, String world) {
|
||||
if (groups.isEmpty()) return world;
|
||||
for (Object worldGroup : groups) {
|
||||
for (String definedWorld : worldGroup.toString().split(multiWorldSeparator)) {
|
||||
if (definedWorld.endsWith("*")) {
|
||||
if (world.toLowerCase().startsWith(definedWorld.substring(0, definedWorld.length()-1).toLowerCase())) return worldGroup.toString();
|
||||
} else {
|
||||
if (world.equalsIgnoreCase(definedWorld)) return worldGroup.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
return world;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads all lines in file and returns them as List
|
||||
* @return list of lines in file
|
||||
*/
|
||||
public List<String> readAllLines(File file) {
|
||||
List<String> list = new ArrayList<String>();
|
||||
try {
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8));
|
||||
public static List<String> readAllLines(File file) {
|
||||
List<String> list = new ArrayList<>();
|
||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8))){
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
list.add(line);
|
||||
}
|
||||
br.close();
|
||||
} catch (Exception ex) {
|
||||
tab.getErrorManager().criticalError("Failed to read file " + file, ex);
|
||||
TAB.getInstance().getErrorManager().criticalError("Failed to read file " + file, ex);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Writes defined line of text to file
|
||||
* @param f - file to write to
|
||||
* @param line - line to write
|
||||
*/
|
||||
public void write(File f, String line){
|
||||
try {
|
||||
BufferedWriter buf = new BufferedWriter(new FileWriter(f, true));
|
||||
buf.write(line + System.getProperty("line.separator"));
|
||||
buf.close();
|
||||
} catch (Exception ex) {
|
||||
tab.getErrorManager().criticalError("Failed to write to file " + f.getName(), ex);
|
||||
}
|
||||
public static void write(File file, List<String> lines){
|
||||
try (BufferedWriter buf = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, true), StandardCharsets.UTF_8))){
|
||||
for (String line : lines) {
|
||||
buf.write(line + System.getProperty("line.separator"));
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
TAB.getInstance().getErrorManager().criticalError("Failed to write to file " + file.getName(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> getRemoveStrings() {
|
||||
return removeStrings;
|
||||
}
|
||||
|
||||
public boolean isUnregisterBeforeRegister() {
|
||||
return unregisterBeforeRegister;
|
||||
}
|
||||
|
||||
public ConfigurationFile getTranslation() {
|
||||
return translation;
|
||||
}
|
||||
|
||||
public ConfigurationFile getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public boolean isRemoveGhostPlayers() {
|
||||
return removeGhostPlayers;
|
||||
}
|
||||
|
||||
public ConfigurationFile getPremiumConfig() {
|
||||
return premiumconfig;
|
||||
}
|
||||
|
||||
public ConfigurationFile getBossbarConfig() {
|
||||
return bossbar;
|
||||
}
|
||||
|
||||
public boolean isLayout() {
|
||||
return layout;
|
||||
}
|
||||
|
||||
public ConfigurationFile getAnimationFile() {
|
||||
return animation;
|
||||
}
|
||||
|
||||
public boolean isRgbSupport() {
|
||||
return rgbSupport;
|
||||
}
|
||||
|
||||
public boolean isBukkitPermissions() {
|
||||
return bukkitPermissions;
|
||||
}
|
||||
|
||||
public boolean isPipelineInjection() {
|
||||
return pipelineInjection;
|
||||
}
|
||||
|
||||
public boolean isArmorStandsAlwaysVisible() {
|
||||
return armorStandsAlwaysVisible;
|
||||
}
|
||||
|
||||
public String getEssentialsNickPrefix() {
|
||||
return essentialsNickPrefix;
|
||||
}
|
||||
|
||||
public String getReloadFailedMessage() {
|
||||
return reloadFailed;
|
||||
}
|
||||
|
||||
public ConfigurationFile getPlayerDataFile() {
|
||||
return playerdata;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,8 @@
|
||||
package me.neznamy.tab.shared.config;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -44,7 +37,7 @@ public abstract class ConfigurationFile {
|
||||
* @throws IllegalStateException - if file does not exist and source is null
|
||||
* @throws IOException - if I/O file operation fails
|
||||
*/
|
||||
public ConfigurationFile(InputStream source, File destination, List<String> header) throws IllegalStateException, IOException {
|
||||
protected ConfigurationFile(InputStream source, File destination, List<String> header) throws IOException {
|
||||
this.header = header;
|
||||
this.file = destination;
|
||||
if (file.getParentFile() != null) file.getParentFile().mkdirs();
|
||||
@@ -103,7 +96,7 @@ public abstract class ConfigurationFile {
|
||||
return defaultValue;
|
||||
}
|
||||
return value;
|
||||
} catch (Throwable e) {
|
||||
} catch (Exception e) {
|
||||
if (defaultValue != null) set(path, defaultValue);
|
||||
return defaultValue;
|
||||
}
|
||||
@@ -125,8 +118,8 @@ public abstract class ConfigurationFile {
|
||||
* @return value from map
|
||||
*/
|
||||
private Object getIgnoreCase(Map<Object, Object> map, String key) {
|
||||
for (Object mapkey : map.keySet()) {
|
||||
if (mapkey.toString().equalsIgnoreCase(key)) return map.get(mapkey);
|
||||
for (Entry<Object, Object> entry : map.entrySet()) {
|
||||
if (entry.getKey().toString().equalsIgnoreCase(key)) return entry.getValue();
|
||||
}
|
||||
return map.get(key);
|
||||
}
|
||||
@@ -174,9 +167,9 @@ public abstract class ConfigurationFile {
|
||||
if (value == null) return defaultValue;
|
||||
if (!(value instanceof List)) {
|
||||
dataMismatch(path, ArrayList.class, value.getClass());
|
||||
return new ArrayList<String>();
|
||||
return new ArrayList<>();
|
||||
}
|
||||
List<String> fixedList = new ArrayList<String>();
|
||||
List<String> fixedList = new ArrayList<>();
|
||||
for (Object key : (List<Object>)value) {
|
||||
fixedList.add(key.toString());
|
||||
}
|
||||
@@ -225,7 +218,14 @@ public abstract class ConfigurationFile {
|
||||
* @return value from file or null if not present
|
||||
*/
|
||||
public Boolean getBoolean(String path) {
|
||||
return getBoolean(path, null);
|
||||
Object value = getObject(path, null);
|
||||
if (value == null) return null;
|
||||
try {
|
||||
return Boolean.parseBoolean(value.toString());
|
||||
} catch (Exception e) {
|
||||
dataMismatch(path, Boolean.class, value.getClass());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -235,10 +235,10 @@ public abstract class ConfigurationFile {
|
||||
* @param defaultValue - value to be inserted and returned if option is not present
|
||||
* @return value from config
|
||||
*/
|
||||
public Boolean getBoolean(String path, Boolean defaultValue) {
|
||||
public boolean getBoolean(String path, boolean defaultValue) {
|
||||
Object value = getObject(path, defaultValue);
|
||||
if (value == null) return defaultValue;
|
||||
try{
|
||||
try {
|
||||
return Boolean.parseBoolean(value.toString());
|
||||
} catch (Exception e) {
|
||||
dataMismatch(path, Boolean.class, value.getClass());
|
||||
@@ -312,7 +312,7 @@ public abstract class ConfigurationFile {
|
||||
if (path.contains(".")) {
|
||||
String keyWord = getRealKey(map, path.split("\\.")[0]);
|
||||
Object submap = map.get(keyWord);
|
||||
if (submap == null || !(submap instanceof Map)) {
|
||||
if (!(submap instanceof Map)) {
|
||||
submap = new HashMap<String, Object>();
|
||||
}
|
||||
map.put(keyWord.replace("@#@", "."), set((Map<String, Object>) submap, path.substring(keyWord.length()+1, path.length()), value));
|
||||
@@ -345,7 +345,7 @@ public abstract class ConfigurationFile {
|
||||
*/
|
||||
public boolean hasHeader() {
|
||||
if (header == null) return true;
|
||||
for (String line : readAllLines(file)) {
|
||||
for (String line : Configs.readAllLines(file)) {
|
||||
if (line.contains("#")) return true;
|
||||
}
|
||||
return false;
|
||||
@@ -357,39 +357,17 @@ public abstract class ConfigurationFile {
|
||||
public void fixHeader() {
|
||||
if (header == null) return;
|
||||
try {
|
||||
List<String> content = new ArrayList<String>(header);
|
||||
content.addAll(readAllLines(file));
|
||||
file.delete();
|
||||
file.createNewFile();
|
||||
BufferedWriter buf = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, true), StandardCharsets.UTF_8));
|
||||
for (String line : content) {
|
||||
buf.write(line + System.getProperty("line.separator"));
|
||||
List<String> content = new ArrayList<>(header);
|
||||
content.addAll(Configs.readAllLines(file));
|
||||
Files.delete(file.toPath());
|
||||
if (file.createNewFile()) {
|
||||
Configs.write(file, content);
|
||||
}
|
||||
buf.close();
|
||||
} catch (Exception ex) {
|
||||
TAB.getInstance().getErrorManager().criticalError("Failed to modify file " + file, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads all lines in file and returns them as List
|
||||
* @return list of lines in file
|
||||
*/
|
||||
private List<String> readAllLines(File file) {
|
||||
List<String> list = new ArrayList<String>();
|
||||
try {
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8));
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
list.add(line);
|
||||
}
|
||||
br.close();
|
||||
} catch (Exception ex) {
|
||||
TAB.getInstance().getErrorManager().criticalError("Failed to read file " + file, ex);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all used placeholder identifiers in the file including nested placeholders in given keys
|
||||
* @param simpleKeys - keys to check
|
||||
@@ -406,22 +384,22 @@ public abstract class ConfigurationFile {
|
||||
* @return Set of used identifiers
|
||||
*/
|
||||
private Set<String> getUsedPlaceholders(Map<String, Object> map, String... simpleKeys){
|
||||
Set<String> values = new HashSet<String>();
|
||||
Set<String> placeholders = new HashSet<>();
|
||||
for (Entry<String, Object> entry : map.entrySet()) {
|
||||
for (String simpleKey : simpleKeys) {
|
||||
if (String.valueOf(entry.getKey()).equals(simpleKey)) values.addAll(TAB.getInstance().getPlaceholderManager().detectAll(String.valueOf(entry.getValue())));
|
||||
if (String.valueOf(entry.getKey()).equals(simpleKey)) placeholders.addAll(TAB.getInstance().getPlaceholderManager().detectAll(String.valueOf(entry.getValue())));
|
||||
}
|
||||
if (entry.getValue() instanceof Map) {
|
||||
values.addAll(getUsedPlaceholders((Map<String, Object>)entry.getValue(), simpleKeys));
|
||||
placeholders.addAll(getUsedPlaceholders((Map<String, Object>)entry.getValue(), simpleKeys));
|
||||
}
|
||||
if (entry.getValue() instanceof List) {
|
||||
for (Object obj : (List<Object>)entry.getValue()) {
|
||||
for (String simpleKey : simpleKeys) {
|
||||
if (String.valueOf(obj).equals(simpleKey)) values.addAll(TAB.getInstance().getPlaceholderManager().detectAll(String.valueOf(entry.getValue())));
|
||||
if (String.valueOf(obj).equals(simpleKey)) placeholders.addAll(TAB.getInstance().getPlaceholderManager().detectAll(String.valueOf(entry.getValue())));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return values;
|
||||
return placeholders;
|
||||
}
|
||||
}
|
||||
@@ -63,10 +63,10 @@ public class YamlConfigurationFile extends ConfigurationFile {
|
||||
input.close();
|
||||
if (!hasHeader()) fixHeader();
|
||||
} catch (YAMLException e) {
|
||||
input.close();
|
||||
if (input != null) input.close();
|
||||
TAB tab = TAB.getInstance();
|
||||
tab.getErrorManager().startupWarn("File " + destination + " has broken syntax.");
|
||||
tab.brokenFile = file.getPath();
|
||||
tab.setBrokenFile(file.getPath());
|
||||
tab.getPlatform().sendConsoleMessage("&6[TAB] Error message from yaml parser: " + e.getMessage(), true);
|
||||
List<String> suggestions = YamlAssist.getSuggestions(file);
|
||||
if (!suggestions.isEmpty()) {
|
||||
@@ -86,7 +86,7 @@ public class YamlConfigurationFile extends ConfigurationFile {
|
||||
yaml.dump(values, writer);
|
||||
writer.close();
|
||||
if (!hasHeader()) fixHeader();
|
||||
} catch (Throwable e) {
|
||||
} catch (IOException e) {
|
||||
TAB.getInstance().getErrorManager().criticalError("Failed to save yaml file " + file.getPath() + " with content " + values.toString(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package me.neznamy.tab.shared.cpu;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
@@ -23,25 +24,25 @@ import me.neznamy.tab.shared.ErrorManager;
|
||||
public class CPUManager {
|
||||
|
||||
//data reset interval in milliseconds
|
||||
private final int bufferSizeMillis = 10000;
|
||||
private static final int BUFFER_SIZE_MILLIS = 10000;
|
||||
|
||||
//nanoseconds worked in the current 10 seconds
|
||||
private Map<Object, Map<UsageType, AtomicLong>> featureUsageCurrent = new ConcurrentHashMap<Object, Map<UsageType, AtomicLong>>();
|
||||
private Map<String, AtomicLong> placeholderUsageCurrent = new ConcurrentHashMap<String, AtomicLong>();
|
||||
private Map<String, AtomicLong> bridgePlaceholderUsageCurrent = new ConcurrentHashMap<String, AtomicLong>();
|
||||
private Map<String, AtomicLong> methodUsageCurrent = new ConcurrentHashMap<String, AtomicLong>();
|
||||
private Map<Object, Map<UsageType, AtomicLong>> featureUsageCurrent = new ConcurrentHashMap<>();
|
||||
private Map<String, AtomicLong> placeholderUsageCurrent = new ConcurrentHashMap<>();
|
||||
private Map<String, AtomicLong> bridgePlaceholderUsageCurrent = new ConcurrentHashMap<>();
|
||||
private Map<String, AtomicLong> methodUsageCurrent = new ConcurrentHashMap<>();
|
||||
|
||||
//packets sent in the current 10 seconds
|
||||
private Map<Object, AtomicInteger> packetsCurrent = new ConcurrentHashMap<Object, AtomicInteger>();
|
||||
private Map<Object, AtomicInteger> packetsCurrent = new ConcurrentHashMap<>();
|
||||
|
||||
//nanoseconds worked in the previous 10 seconds
|
||||
private Map<Object, Map<UsageType, AtomicLong>> featureUsagePrevious = new HashMap<Object, Map<UsageType, AtomicLong>>();
|
||||
private Map<String, AtomicLong> placeholderUsagePrevious = new HashMap<String, AtomicLong>();
|
||||
private Map<String, AtomicLong> bridgePlaceholderUsagePrevious = new HashMap<String, AtomicLong>();
|
||||
private Map<String, AtomicLong> methodUsagePrevious = new HashMap<String, AtomicLong>();
|
||||
private Map<Object, Map<UsageType, AtomicLong>> featureUsagePrevious = new HashMap<>();
|
||||
private Map<String, AtomicLong> placeholderUsagePrevious = new HashMap<>();
|
||||
private Map<String, AtomicLong> bridgePlaceholderUsagePrevious = new HashMap<>();
|
||||
private Map<String, AtomicLong> methodUsagePrevious = new HashMap<>();
|
||||
|
||||
//packets sent in the previous 10 seconds
|
||||
private Map<Object, AtomicInteger> packetsPrevious = new ConcurrentHashMap<Object, AtomicInteger>();
|
||||
private Map<Object, AtomicInteger> packetsPrevious = new ConcurrentHashMap<>();
|
||||
|
||||
//thread pool
|
||||
private ThreadPoolExecutor exe = (ThreadPoolExecutor) Executors.newCachedThreadPool();
|
||||
@@ -55,29 +56,26 @@ public class CPUManager {
|
||||
*/
|
||||
public CPUManager(ErrorManager errorManager) {
|
||||
this.errorManager = errorManager;
|
||||
exe.submit(new Runnable() {
|
||||
exe.submit(() -> {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while (true) {
|
||||
Thread.sleep(bufferSizeMillis);
|
||||
try {
|
||||
while (true) {
|
||||
Thread.sleep(BUFFER_SIZE_MILLIS);
|
||||
|
||||
featureUsagePrevious = featureUsageCurrent;
|
||||
placeholderUsagePrevious = placeholderUsageCurrent;
|
||||
bridgePlaceholderUsagePrevious = bridgePlaceholderUsageCurrent;
|
||||
methodUsagePrevious = methodUsageCurrent;
|
||||
packetsPrevious = packetsCurrent;
|
||||
|
||||
featureUsageCurrent = new ConcurrentHashMap<Object, Map<UsageType, AtomicLong>>();
|
||||
placeholderUsageCurrent = new ConcurrentHashMap<String, AtomicLong>();
|
||||
bridgePlaceholderUsageCurrent = new ConcurrentHashMap<String, AtomicLong>();
|
||||
methodUsageCurrent = new ConcurrentHashMap<String, AtomicLong>();
|
||||
packetsCurrent = new ConcurrentHashMap<Object, AtomicInteger>();
|
||||
}
|
||||
} catch (InterruptedException pluginDisabled) {
|
||||
featureUsagePrevious = featureUsageCurrent;
|
||||
placeholderUsagePrevious = placeholderUsageCurrent;
|
||||
bridgePlaceholderUsagePrevious = bridgePlaceholderUsageCurrent;
|
||||
methodUsagePrevious = methodUsageCurrent;
|
||||
packetsPrevious = packetsCurrent;
|
||||
|
||||
featureUsageCurrent = new ConcurrentHashMap<>();
|
||||
placeholderUsageCurrent = new ConcurrentHashMap<>();
|
||||
bridgePlaceholderUsageCurrent = new ConcurrentHashMap<>();
|
||||
methodUsageCurrent = new ConcurrentHashMap<>();
|
||||
packetsCurrent = new ConcurrentHashMap<>();
|
||||
}
|
||||
} catch (InterruptedException pluginDisabled) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -108,17 +106,10 @@ public class CPUManager {
|
||||
* @param task - the task
|
||||
*/
|
||||
public void runMeasuredTask(String errorDescription, Object feature, UsageType type, Runnable task) {
|
||||
exe.submit(new Runnable() {
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
long time = System.nanoTime();
|
||||
task.run();
|
||||
addTime(feature, type, System.nanoTime()-time);
|
||||
} catch (Throwable t) {
|
||||
errorManager.printError("An error occurred when " + errorDescription, t);
|
||||
}
|
||||
}
|
||||
submit(errorDescription, () -> {
|
||||
long time = System.nanoTime();
|
||||
task.run();
|
||||
addTime(feature, type, System.nanoTime()-time);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -128,16 +119,7 @@ public class CPUManager {
|
||||
* @param task - the task
|
||||
*/
|
||||
public void runTask(String errorDescription, Runnable task) {
|
||||
exe.submit(new Runnable() {
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
task.run();
|
||||
} catch (Throwable t) {
|
||||
errorManager.printError("An error occurred when " + errorDescription, t);
|
||||
}
|
||||
}
|
||||
});
|
||||
submit(errorDescription, task);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,26 +132,22 @@ public class CPUManager {
|
||||
*/
|
||||
public void startRepeatingMeasuredTask(int intervalMilliseconds, String errorDescription, Object feature, UsageType type, Runnable task) {
|
||||
if (intervalMilliseconds <= 0) return;
|
||||
exe.submit(new Runnable() {
|
||||
|
||||
public void run() {
|
||||
long lastLoop = System.currentTimeMillis()-intervalMilliseconds;
|
||||
while (true) {
|
||||
try {
|
||||
long sleep = intervalMilliseconds - (System.currentTimeMillis()-lastLoop);
|
||||
if (sleep < 0) {
|
||||
sleep = 0;
|
||||
}
|
||||
Thread.sleep(sleep);
|
||||
lastLoop = System.currentTimeMillis();
|
||||
long time = System.nanoTime();
|
||||
task.run();
|
||||
addTime(feature, type, System.nanoTime()-time);
|
||||
} catch (InterruptedException pluginDisabled) {
|
||||
break;
|
||||
} catch (Throwable t) {
|
||||
errorManager.printError("An error occurred when " + errorDescription, t);
|
||||
submit(errorDescription, () -> {
|
||||
long lastLoop = System.currentTimeMillis()-intervalMilliseconds;
|
||||
while (true) {
|
||||
try {
|
||||
long sleep = intervalMilliseconds - (System.currentTimeMillis()-lastLoop);
|
||||
if (sleep < 0) {
|
||||
sleep = 0;
|
||||
}
|
||||
Thread.sleep(sleep);
|
||||
lastLoop = System.currentTimeMillis();
|
||||
long time = System.nanoTime();
|
||||
task.run();
|
||||
addTime(feature, type, System.nanoTime()-time);
|
||||
} catch (InterruptedException pluginDisabled) {
|
||||
Thread.currentThread().interrupt();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -184,18 +162,24 @@ public class CPUManager {
|
||||
* @param task - the task
|
||||
*/
|
||||
public void runTaskLater(int delayMilliseconds, String errorDescription, Object feature, UsageType type, Runnable task) {
|
||||
exe.submit(new Runnable() {
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
Thread.sleep(delayMilliseconds);
|
||||
long time = System.nanoTime();
|
||||
task.run();
|
||||
addTime(feature, type, System.nanoTime()-time);
|
||||
} catch (InterruptedException pluginDisabled) {
|
||||
} catch (Throwable t) {
|
||||
errorManager.printError("An error occurred when " + errorDescription, t);
|
||||
}
|
||||
submit(errorDescription, () -> {
|
||||
try {
|
||||
Thread.sleep(delayMilliseconds);
|
||||
long time = System.nanoTime();
|
||||
task.run();
|
||||
addTime(feature, type, System.nanoTime()-time);
|
||||
} catch (InterruptedException pluginDisabled) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void submit(String errorDescription, Runnable task) {
|
||||
exe.submit(() -> {
|
||||
try {
|
||||
task.run();
|
||||
} catch (Exception | Error e) {
|
||||
errorManager.printError("An error occurred when " + errorDescription, e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -239,14 +223,14 @@ public class CPUManager {
|
||||
* @return converted and sorted map
|
||||
*/
|
||||
private Map<String, Float> getUsage(Map<String, AtomicLong> map){
|
||||
Map<String, Long> nanoMap = new HashMap<String, Long>();
|
||||
Map<String, Long> nanoMap = new HashMap<>();
|
||||
String key;
|
||||
for (Entry<String, AtomicLong> nanos : map.entrySet()) {
|
||||
key = nanos.getKey();
|
||||
if (!nanoMap.containsKey(key)) nanoMap.put(key, 0L);
|
||||
nanoMap.put(key, nanoMap.get(key)+nanos.getValue().get());
|
||||
}
|
||||
Map<String, Float> percentMap = new HashMap<String, Float>();
|
||||
Map<String, Float> percentMap = new HashMap<>();
|
||||
for (Entry<String, Long> entry : nanoMap.entrySet()) {
|
||||
percentMap.put(entry.getKey(), nanosToPercent(entry.getValue()));
|
||||
}
|
||||
@@ -258,11 +242,11 @@ public class CPUManager {
|
||||
* @return map of CPU usage per feature per type
|
||||
*/
|
||||
public Map<Object, Map<UsageType, Float>> getFeatureUsage(){
|
||||
Map<Object, Map<UsageType, Long>> total = new HashMap<Object, Map<UsageType, Long>>();
|
||||
Map<Object, EnumMap<UsageType, Long>> total = new HashMap<>();
|
||||
for (Entry<Object, Map<UsageType, AtomicLong>> nanos : featureUsagePrevious.entrySet()) {
|
||||
Object key = nanos.getKey();
|
||||
if (!total.containsKey(key)) {
|
||||
total.put(key, new HashMap<UsageType, Long>());
|
||||
total.put(key, new EnumMap<>(UsageType.class));
|
||||
}
|
||||
Map<UsageType, Long> usage = total.get(key);
|
||||
for (Entry<UsageType, AtomicLong> entry : nanos.getValue().entrySet()) {
|
||||
@@ -272,10 +256,10 @@ public class CPUManager {
|
||||
usage.put(entry.getKey(), usage.get(entry.getKey()) + entry.getValue().get());
|
||||
}
|
||||
}
|
||||
Map<Object, Map<UsageType, Float>> sorted = new LinkedHashMap<Object, Map<UsageType, Float>>();
|
||||
Map<Object, Map<UsageType, Float>> sorted = new LinkedHashMap<>();
|
||||
for (Object key : sortKeys(total)) {
|
||||
Map<UsageType, Long> local = sortByValue(total.get(key));
|
||||
Map<UsageType, Float> percent = new LinkedHashMap<UsageType, Float>();
|
||||
Map<UsageType, Float> percent = new LinkedHashMap<>();
|
||||
for (Entry<UsageType, Long> entry : local.entrySet()) {
|
||||
percent.put(entry.getKey(), nanosToPercent(entry.getValue()));
|
||||
}
|
||||
@@ -290,7 +274,7 @@ public class CPUManager {
|
||||
* @return usage in % (0-100)
|
||||
*/
|
||||
private float nanosToPercent(long nanos) {
|
||||
float percent = (float) nanos / bufferSizeMillis / 1000000; //relative usage (0-1)
|
||||
float percent = (float) nanos / BUFFER_SIZE_MILLIS / 1000000; //relative usage (0-1)
|
||||
percent *= 100; //relative into %
|
||||
return percent;
|
||||
}
|
||||
@@ -303,14 +287,12 @@ public class CPUManager {
|
||||
* @return sorted map
|
||||
*/
|
||||
private <K, V extends Comparable<V>> Map<K, V> sortByValue(Map<K, V> map) {
|
||||
Comparator<K> valueComparator = new Comparator<K>() {
|
||||
public int compare(K k1, K k2) {
|
||||
int compare = map.get(k2).compareTo(map.get(k1));
|
||||
if (compare == 0) return 1;
|
||||
else return compare;
|
||||
}
|
||||
Comparator<K> valueComparator = (k1, k2) -> {
|
||||
int compare = map.get(k2).compareTo(map.get(k1));
|
||||
if (compare == 0) return 1;
|
||||
else return compare;
|
||||
};
|
||||
Map<K, V> sortedByValues = new TreeMap<K, V>(valueComparator);
|
||||
Map<K, V> sortedByValues = new TreeMap<>(valueComparator);
|
||||
sortedByValues.putAll(map);
|
||||
return sortedByValues;
|
||||
}
|
||||
@@ -323,14 +305,12 @@ public class CPUManager {
|
||||
* @return sorted map
|
||||
*/
|
||||
private <K> Map<K, AtomicInteger> sortByValue1(Map<K, AtomicInteger> map) {
|
||||
Comparator<K> valueComparator = new Comparator<K>() {
|
||||
public int compare(K k1, K k2) {
|
||||
int compare = ((Comparable<Integer>)map.get(k2).get()).compareTo(map.get(k1).get());
|
||||
if (compare == 0) return 1;
|
||||
else return compare;
|
||||
}
|
||||
Comparator<K> valueComparator = (k1, k2) -> {
|
||||
int compare = ((Comparable<Integer>)map.get(k2).get()).compareTo(map.get(k1).get());
|
||||
if (compare == 0) return 1;
|
||||
else return compare;
|
||||
};
|
||||
Map<K, AtomicInteger> sortedByValues = new TreeMap<K, AtomicInteger>(valueComparator);
|
||||
Map<K, AtomicInteger> sortedByValues = new TreeMap<>(valueComparator);
|
||||
sortedByValues.putAll(map);
|
||||
return sortedByValues;
|
||||
}
|
||||
@@ -342,13 +322,13 @@ public class CPUManager {
|
||||
* @param map - map to sort
|
||||
* @return list of keys sorted from highest usage to lowest
|
||||
*/
|
||||
private <K, L> List<K> sortKeys(Map<K, Map<L, Long>> map){
|
||||
Map<K, Long> simplified = new LinkedHashMap<K, Long>();
|
||||
for (Entry<K, Map<L, Long>> entry : map.entrySet()) {
|
||||
private <K> List<K> sortKeys(Map<K, EnumMap<UsageType, Long>> map){
|
||||
Map<K, Long> simplified = new LinkedHashMap<>();
|
||||
for (Entry<K, EnumMap<UsageType, Long>> entry : map.entrySet()) {
|
||||
simplified.put(entry.getKey(), sumValues(entry.getValue()));
|
||||
}
|
||||
simplified = sortByValue(simplified);
|
||||
List<K> sortedKeys = new ArrayList<K>();
|
||||
List<K> sortedKeys = new ArrayList<>();
|
||||
for (K key : simplified.keySet()) {
|
||||
sortedKeys.add(key);
|
||||
}
|
||||
@@ -375,27 +355,7 @@ public class CPUManager {
|
||||
* @param nanoseconds - time to add
|
||||
*/
|
||||
public void addTime(Object feature, UsageType type, long nanoseconds) {
|
||||
Map<UsageType, AtomicLong> usage = featureUsageCurrent.get(feature);
|
||||
if (usage == null) {
|
||||
usage = new ConcurrentHashMap<UsageType, AtomicLong>();
|
||||
featureUsageCurrent.put(feature, usage);
|
||||
}
|
||||
try {
|
||||
if (!usage.containsKey(type)) {
|
||||
usage.put(type, new AtomicLong());
|
||||
}
|
||||
} catch (NullPointerException e) {
|
||||
//java.lang.NullPointerException: null
|
||||
//at java.base/java.util.concurrent.ConcurrentHashMap.get(ConcurrentHashMap.java:936)
|
||||
//at java.base/java.util.concurrent.ConcurrentHashMap.containsKey(ConcurrentHashMap.java:964)
|
||||
return;
|
||||
}
|
||||
AtomicLong current = usage.get(type);
|
||||
if (current == null) {
|
||||
usage.put(type, new AtomicLong(nanoseconds));
|
||||
} else {
|
||||
current.addAndGet(nanoseconds);
|
||||
}
|
||||
featureUsageCurrent.computeIfAbsent(feature, f -> new ConcurrentHashMap<>()).computeIfAbsent(type, t -> new AtomicLong()).addAndGet(nanoseconds);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -432,12 +392,7 @@ public class CPUManager {
|
||||
* @param time - nanoseconds the task took
|
||||
*/
|
||||
private void addTime(Map<String, AtomicLong> map, String key, long time) {
|
||||
AtomicLong current = map.get(key);
|
||||
if (current == null) {
|
||||
map.put(key, new AtomicLong(time));
|
||||
} else {
|
||||
current.addAndGet(time);
|
||||
}
|
||||
map.computeIfAbsent(key, k -> new AtomicLong()).addAndGet(time);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -445,11 +400,6 @@ public class CPUManager {
|
||||
* @param feature - feature to increment packet counter of
|
||||
*/
|
||||
public void packetSent(Object feature) {
|
||||
AtomicInteger current = packetsCurrent.get(feature);
|
||||
if (current == null) {
|
||||
packetsCurrent.put(feature, new AtomicInteger(1));
|
||||
} else {
|
||||
current.addAndGet(1);
|
||||
}
|
||||
packetsCurrent.computeIfAbsent(feature, f -> new AtomicInteger()).incrementAndGet();
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,7 @@ public enum UsageType {
|
||||
REFRESHING("Refreshing"),
|
||||
REPEATING_TASK("Repeating task"),
|
||||
TICKING_VEHICLES("Ticking vehicles"),
|
||||
v1_8_0_BUG_COMPENSATION("Compensating for 1.8.0 bugs");
|
||||
V1_8_0_BUG_COMPENSATION("Compensating for 1.8.0 bugs");
|
||||
|
||||
//user-friendly name to be used in /tab cpu
|
||||
private String friendlyName;
|
||||
|
||||
@@ -5,8 +5,10 @@ import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import me.neznamy.tab.shared.PropertyUtils;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.cpu.TabFeature;
|
||||
import me.neznamy.tab.shared.features.types.event.QuitEventListener;
|
||||
@@ -21,13 +23,18 @@ public class AlignedSuffix implements QuitEventListener, WorldChangeListener {
|
||||
private TAB tab;
|
||||
private int maxWidth;
|
||||
private TabPlayer maxPlayer;
|
||||
private Map<Character, Byte> widths = new HashMap<Character, Byte>();
|
||||
private Map<Character, Byte> widths = new HashMap<>();
|
||||
private Playerlist playerlist;
|
||||
|
||||
public AlignedSuffix(Playerlist playerlist, TAB tab) {
|
||||
this.tab = tab;
|
||||
this.playerlist = playerlist;
|
||||
loadWidthsFromFile();
|
||||
Map<Integer, Integer> widthOverrides = tab.getConfiguration().getPremiumConfig().getConfigurationSection("character-width-overrides");
|
||||
for (Entry<Integer, Integer> entry : widthOverrides.entrySet()) {
|
||||
widths.put((char)(int)entry.getKey(), (byte)(int)entry.getValue());
|
||||
}
|
||||
tab.debug(String.format("Loaded AlignedSuffix feature with parameters widthOverrides=%s", widthOverrides));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -47,9 +54,9 @@ public class AlignedSuffix implements QuitEventListener, WorldChangeListener {
|
||||
tab.getErrorManager().criticalError("Failed to read character widths from file", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public String formatNameAndUpdateLeader(TabPlayer player, TabPlayer viewer) {
|
||||
int playerNameWidth = getTextWidth(IChatBaseComponent.fromColoredText(player.getProperty("tabprefix").getFormat(null) + player.getProperty("customtabname").getFormat(null) + player.getProperty("tabsuffix").getFormat(null)));
|
||||
int playerNameWidth = getTextWidth(IChatBaseComponent.fromColoredText(player.getProperty(PropertyUtils.TABPREFIX).getFormat(null) + player.getProperty(PropertyUtils.CUSTOMTABNAME).getFormat(null) + player.getProperty(PropertyUtils.TABSUFFIX).getFormat(null)));
|
||||
if (player == maxPlayer && playerNameWidth < maxWidth) {
|
||||
maxWidth = playerNameWidth;
|
||||
for (TabPlayer all : tab.getPlayers()) {
|
||||
@@ -65,7 +72,7 @@ public class AlignedSuffix implements QuitEventListener, WorldChangeListener {
|
||||
maxPlayer = player;
|
||||
updateAllNames(player);
|
||||
}
|
||||
return formatName(player.getProperty("tabprefix").getFormat(viewer) + player.getProperty("customtabname").getFormat(viewer), player.getProperty("tabsuffix").getFormat(viewer));
|
||||
return formatName(player.getProperty(PropertyUtils.TABPREFIX).getFormat(viewer) + player.getProperty(PropertyUtils.CUSTOMTABNAME).getFormat(viewer), player.getProperty(PropertyUtils.TABSUFFIX).getFormat(viewer));
|
||||
}
|
||||
|
||||
public String formatName(String prefixAndName, String suffix) {
|
||||
@@ -109,7 +116,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").getFormat(null) + p.getProperty("customtabname").getFormat(null) + p.getProperty("tabsuffix").getFormat(null);
|
||||
String format = p.getProperty(PropertyUtils.TABPREFIX).getFormat(null) + p.getProperty(PropertyUtils.CUSTOMTABNAME).getFormat(null) + p.getProperty(PropertyUtils.TABSUFFIX).getFormat(null);
|
||||
return getTextWidth(IChatBaseComponent.fromColoredText(format));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package me.neznamy.tab.shared.features;
|
||||
|
||||
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.PacketAPI;
|
||||
@@ -10,81 +12,57 @@ import me.neznamy.tab.shared.cpu.TabFeature;
|
||||
import me.neznamy.tab.shared.features.types.Loadable;
|
||||
import me.neznamy.tab.shared.features.types.Refreshable;
|
||||
import me.neznamy.tab.shared.features.types.event.JoinEventListener;
|
||||
import me.neznamy.tab.shared.features.types.event.QuitEventListener;
|
||||
import me.neznamy.tab.shared.features.types.event.WorldChangeListener;
|
||||
import me.neznamy.tab.shared.features.types.packet.DisplayObjectivePacketListener;
|
||||
import me.neznamy.tab.shared.features.types.packet.LoginPacketListener;
|
||||
import me.neznamy.tab.shared.packets.PacketPlayOutScoreboardDisplayObjective;
|
||||
import me.neznamy.tab.shared.packets.PacketPlayOutScoreboardObjective;
|
||||
import me.neznamy.tab.shared.packets.PacketPlayOutScoreboardScore;
|
||||
import me.neznamy.tab.shared.packets.PacketPlayOutScoreboardObjective.EnumScoreboardHealthDisplay;
|
||||
import me.neznamy.tab.shared.packets.PacketPlayOutScoreboardScore;
|
||||
import me.neznamy.tab.shared.packets.PacketPlayOutScoreboardScore.Action;
|
||||
|
||||
/**
|
||||
* Feature handler for BelowName feature
|
||||
*/
|
||||
public class BelowName implements Loadable, JoinEventListener, WorldChangeListener, Refreshable, LoginPacketListener, DisplayObjectivePacketListener {
|
||||
public class BelowName implements Loadable, JoinEventListener, QuitEventListener, WorldChangeListener, Refreshable, LoginPacketListener, DisplayObjectivePacketListener {
|
||||
|
||||
public static final String ObjectiveName = "TAB-BelowName";
|
||||
public static final int DisplaySlot = 2;
|
||||
|
||||
private final String numberPropertyName = "belowname-number";
|
||||
private final String textPropertyName = "belowname-text";
|
||||
public static final String OBJECTIVE_NAME = "TAB-BelowName";
|
||||
public static final int DISPLAY_SLOT = 2;
|
||||
private static final String NUMBER_PROPERTY = "belowname-number";
|
||||
private static final String TEXT_PROPERTY = "belowname-text";
|
||||
|
||||
private TAB tab;
|
||||
private String rawNumber;
|
||||
private String rawText;
|
||||
private List<String> usedPlaceholders;
|
||||
private List<String> disabledWorlds;
|
||||
private Set<TabPlayer> playersInDisabledWorlds = new HashSet<>();
|
||||
|
||||
public BelowName(TAB tab) {
|
||||
this.tab = tab;
|
||||
rawNumber = tab.getConfiguration().config.getString("classic-vanilla-belowname.number", "%health%");
|
||||
rawText = tab.getConfiguration().config.getString("classic-vanilla-belowname.text", "Health");
|
||||
disabledWorlds = tab.getConfiguration().config.getStringList("disable-features-in-"+tab.getPlatform().getSeparatorType()+"s.belowname", Arrays.asList("disabled" + tab.getPlatform().getSeparatorType()));
|
||||
rawNumber = tab.getConfiguration().getConfig().getString("classic-vanilla-belowname.number", "%health%");
|
||||
rawText = tab.getConfiguration().getConfig().getString("classic-vanilla-belowname.text", "Health");
|
||||
disabledWorlds = tab.getConfiguration().getConfig().getStringList("disable-features-in-"+tab.getPlatform().getSeparatorType()+"s.belowname", Arrays.asList("disabled" + tab.getPlatform().getSeparatorType()));
|
||||
refreshUsedPlaceholders();
|
||||
tab.debug(String.format("Loaded BelowName feature with parameters number=%s, text=%s, disabledWorlds=%s", rawNumber, rawText, disabledWorlds));
|
||||
tab.getFeatureManager().registerFeature("belowname-text", new Refreshable() {
|
||||
|
||||
private List<String> usedPlaceholders;
|
||||
|
||||
{
|
||||
refreshUsedPlaceholders();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh(TabPlayer refreshed, boolean force) {
|
||||
if (isDisabledWorld(disabledWorlds, refreshed.getWorldName())) return;
|
||||
refreshed.sendCustomPacket(new PacketPlayOutScoreboardObjective(2, ObjectiveName, refreshed.getProperty(textPropertyName).updateAndGet(), EnumScoreboardHealthDisplay.INTEGER), TabFeature.BELOWNAME_TEXT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getUsedPlaceholders() {
|
||||
return usedPlaceholders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshUsedPlaceholders() {
|
||||
usedPlaceholders = tab.getPlaceholderManager().getUsedPlaceholderIdentifiersRecursive(rawText);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TabFeature getFeatureType() {
|
||||
return TabFeature.BELOWNAME_TEXT;
|
||||
}
|
||||
});
|
||||
tab.getFeatureManager().registerFeature("belowname-text-refresher", new TextRefresher());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
for (TabPlayer loaded : tab.getPlayers()){
|
||||
loaded.setProperty(numberPropertyName, rawNumber);
|
||||
loaded.setProperty(textPropertyName, rawText);
|
||||
if (isDisabledWorld(disabledWorlds, loaded.getWorldName())) continue;
|
||||
PacketAPI.registerScoreboardObjective(loaded, ObjectiveName, loaded.getProperty(textPropertyName).updateAndGet(), DisplaySlot, EnumScoreboardHealthDisplay.INTEGER, TabFeature.BELOWNAME_TEXT);
|
||||
loaded.setProperty(NUMBER_PROPERTY, rawNumber);
|
||||
loaded.setProperty(TEXT_PROPERTY, rawText);
|
||||
if (isDisabledWorld(disabledWorlds, loaded.getWorldName())) {
|
||||
playersInDisabledWorlds.add(loaded);
|
||||
continue;
|
||||
}
|
||||
PacketAPI.registerScoreboardObjective(loaded, OBJECTIVE_NAME, loaded.getProperty(TEXT_PROPERTY).updateAndGet(), DISPLAY_SLOT, EnumScoreboardHealthDisplay.INTEGER, TabFeature.BELOWNAME_TEXT);
|
||||
}
|
||||
for (TabPlayer viewer : tab.getPlayers()){
|
||||
for (TabPlayer target : tab.getPlayers()){
|
||||
viewer.sendCustomPacket(new PacketPlayOutScoreboardScore(Action.CHANGE, ObjectiveName, target.getName(), getValue(target)), TabFeature.BELOWNAME_NUMBER);
|
||||
viewer.sendCustomPacket(new PacketPlayOutScoreboardScore(Action.CHANGE, OBJECTIVE_NAME, target.getName(), getValue(target)), TabFeature.BELOWNAME_NUMBER);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -92,46 +70,55 @@ public class BelowName implements Loadable, JoinEventListener, WorldChangeListen
|
||||
@Override
|
||||
public void unload() {
|
||||
for (TabPlayer p : tab.getPlayers()){
|
||||
if (isDisabledWorld(disabledWorlds, p.getWorldName())) continue;
|
||||
p.sendCustomPacket(new PacketPlayOutScoreboardObjective(ObjectiveName), TabFeature.BELOWNAME_TEXT);
|
||||
if (playersInDisabledWorlds.contains(p)) continue;
|
||||
p.sendCustomPacket(new PacketPlayOutScoreboardObjective(OBJECTIVE_NAME), TabFeature.BELOWNAME_TEXT);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onJoin(TabPlayer connectedPlayer) {
|
||||
connectedPlayer.setProperty(numberPropertyName, rawNumber);
|
||||
connectedPlayer.setProperty(textPropertyName, rawText);
|
||||
if (isDisabledWorld(disabledWorlds, connectedPlayer.getWorldName())) return;
|
||||
PacketAPI.registerScoreboardObjective(connectedPlayer, ObjectiveName, connectedPlayer.getProperty(textPropertyName).get(), DisplaySlot, EnumScoreboardHealthDisplay.INTEGER, TabFeature.BELOWNAME_TEXT);
|
||||
connectedPlayer.setProperty(NUMBER_PROPERTY, rawNumber);
|
||||
connectedPlayer.setProperty(TEXT_PROPERTY, rawText);
|
||||
if (isDisabledWorld(disabledWorlds, connectedPlayer.getWorldName())) {
|
||||
playersInDisabledWorlds.add(connectedPlayer);
|
||||
return;
|
||||
}
|
||||
PacketAPI.registerScoreboardObjective(connectedPlayer, OBJECTIVE_NAME, connectedPlayer.getProperty(TEXT_PROPERTY).get(), DISPLAY_SLOT, EnumScoreboardHealthDisplay.INTEGER, TabFeature.BELOWNAME_TEXT);
|
||||
int number = getValue(connectedPlayer);
|
||||
for (TabPlayer all : tab.getPlayers()){
|
||||
all.sendCustomPacket(new PacketPlayOutScoreboardScore(Action.CHANGE, ObjectiveName, connectedPlayer.getName(), number), TabFeature.BELOWNAME_NUMBER);
|
||||
if (all.isLoaded()) connectedPlayer.sendCustomPacket(new PacketPlayOutScoreboardScore(Action.CHANGE, ObjectiveName, all.getName(), getValue(all)), TabFeature.BELOWNAME_NUMBER);
|
||||
all.sendCustomPacket(new PacketPlayOutScoreboardScore(Action.CHANGE, OBJECTIVE_NAME, connectedPlayer.getName(), number), TabFeature.BELOWNAME_NUMBER);
|
||||
if (all.isLoaded()) connectedPlayer.sendCustomPacket(new PacketPlayOutScoreboardScore(Action.CHANGE, OBJECTIVE_NAME, all.getName(), getValue(all)), TabFeature.BELOWNAME_NUMBER);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWorldChange(TabPlayer p, String from, String to) {
|
||||
if (isDisabledWorld(disabledWorlds, p.getWorldName()) && !isDisabledWorld(disabledWorlds, from)) {
|
||||
p.sendCustomPacket(new PacketPlayOutScoreboardObjective(ObjectiveName), TabFeature.BELOWNAME_TEXT);
|
||||
return;
|
||||
boolean disabledBefore = playersInDisabledWorlds.contains(p);
|
||||
boolean disabledNow = false;
|
||||
if (isDisabledWorld(disabledWorlds, p.getWorldName())) {
|
||||
disabledNow = true;
|
||||
playersInDisabledWorlds.add(p);
|
||||
} else {
|
||||
playersInDisabledWorlds.remove(p);
|
||||
}
|
||||
if (!isDisabledWorld(disabledWorlds, p.getWorldName()) && isDisabledWorld(disabledWorlds, from)) {
|
||||
if (disabledNow && !disabledBefore) {
|
||||
p.sendCustomPacket(new PacketPlayOutScoreboardObjective(OBJECTIVE_NAME), TabFeature.BELOWNAME_TEXT);
|
||||
}
|
||||
if (!disabledNow && disabledBefore) {
|
||||
onJoin(p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private int getValue(TabPlayer p) {
|
||||
return tab.getErrorManager().parseInteger(p.getProperty(numberPropertyName).updateAndGet(), 0, "belowname number");
|
||||
return tab.getErrorManager().parseInteger(p.getProperty(NUMBER_PROPERTY).updateAndGet(), 0, "belowname number");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh(TabPlayer refreshed, boolean force) {
|
||||
if (isDisabledWorld(disabledWorlds, refreshed.getWorldName())) return;
|
||||
if (playersInDisabledWorlds.contains(refreshed)) return;
|
||||
int number = getValue(refreshed);
|
||||
for (TabPlayer all : tab.getPlayers()) {
|
||||
all.sendCustomPacket(new PacketPlayOutScoreboardScore(Action.CHANGE, ObjectiveName, refreshed.getName(), number), TabFeature.BELOWNAME_NUMBER);
|
||||
all.sendCustomPacket(new PacketPlayOutScoreboardScore(Action.CHANGE, OBJECTIVE_NAME, refreshed.getName(), number), TabFeature.BELOWNAME_NUMBER);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,20 +139,55 @@ public class BelowName implements Loadable, JoinEventListener, WorldChangeListen
|
||||
|
||||
@Override
|
||||
public void onLoginPacket(TabPlayer packetReceiver) {
|
||||
if (isDisabledWorld(disabledWorlds, packetReceiver.getWorldName())) return;
|
||||
PacketAPI.registerScoreboardObjective(packetReceiver, ObjectiveName, packetReceiver.getProperty(textPropertyName).get(), DisplaySlot, EnumScoreboardHealthDisplay.INTEGER, TabFeature.BELOWNAME_TEXT);
|
||||
if (playersInDisabledWorlds.contains(packetReceiver)) return;
|
||||
PacketAPI.registerScoreboardObjective(packetReceiver, OBJECTIVE_NAME, packetReceiver.getProperty(TEXT_PROPERTY).get(), DISPLAY_SLOT, EnumScoreboardHealthDisplay.INTEGER, TabFeature.BELOWNAME_TEXT);
|
||||
for (TabPlayer all : tab.getPlayers()){
|
||||
if (all.isLoaded()) packetReceiver.sendCustomPacket(new PacketPlayOutScoreboardScore(Action.CHANGE, ObjectiveName, all.getName(), getValue(all)), TabFeature.BELOWNAME_NUMBER);
|
||||
if (all.isLoaded()) packetReceiver.sendCustomPacket(new PacketPlayOutScoreboardScore(Action.CHANGE, OBJECTIVE_NAME, all.getName(), getValue(all)), TabFeature.BELOWNAME_NUMBER);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPacketSend(TabPlayer receiver, PacketPlayOutScoreboardDisplayObjective packet) {
|
||||
if (isDisabledWorld(disabledWorlds, receiver.getWorldName())) return false;
|
||||
if (packet.slot == DisplaySlot && !packet.objectiveName.equals(ObjectiveName)) {
|
||||
tab.getErrorManager().printError("Something just tried to register objective \"" + packet.objectiveName + "\" in position " + packet.slot + " (belowname)", null, false, tab.getErrorManager().antiOverrideLog);
|
||||
if (playersInDisabledWorlds.contains(receiver)) return false;
|
||||
if (packet.getSlot() == DISPLAY_SLOT && !packet.getObjectiveName().equals(OBJECTIVE_NAME)) {
|
||||
tab.getErrorManager().printError("Something just tried to register objective \"" + packet.getObjectiveName() + "\" in position " + packet.getSlot() + " (belowname)", null, false, tab.getErrorManager().getAntiOverrideLog());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public class TextRefresher implements Refreshable {
|
||||
|
||||
private List<String> usedPlaceholders;
|
||||
|
||||
public TextRefresher(){
|
||||
refreshUsedPlaceholders();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh(TabPlayer refreshed, boolean force) {
|
||||
if (playersInDisabledWorlds.contains(refreshed)) return;
|
||||
refreshed.sendCustomPacket(new PacketPlayOutScoreboardObjective(2, OBJECTIVE_NAME, refreshed.getProperty(TEXT_PROPERTY).updateAndGet(), EnumScoreboardHealthDisplay.INTEGER), TabFeature.BELOWNAME_TEXT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getUsedPlaceholders() {
|
||||
return usedPlaceholders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshUsedPlaceholders() {
|
||||
usedPlaceholders = tab.getPlaceholderManager().getUsedPlaceholderIdentifiersRecursive(rawText);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TabFeature getFeatureType() {
|
||||
return TabFeature.BELOWNAME_TEXT;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onQuit(TabPlayer disconnectedPlayer) {
|
||||
playersInDisabledWorlds.remove(disconnectedPlayer);
|
||||
}
|
||||
}
|
||||
@@ -20,15 +20,12 @@ public class GhostPlayerFix implements QuitEventListener {
|
||||
|
||||
@Override
|
||||
public void onQuit(TabPlayer disconnectedPlayer) {
|
||||
TAB.getInstance().getCPUManager().runTaskLater(500, "removing players", getFeatureType(), UsageType.PLAYER_QUIT_EVENT, new Runnable() {
|
||||
TAB.getInstance().getCPUManager().runTaskLater(500, "removing players", getFeatureType(), UsageType.PLAYER_QUIT_EVENT, () -> {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (TAB.getInstance().getPlayer(disconnectedPlayer.getName()) != null) return; //player reconnected meanwhile, not removing then
|
||||
for (TabPlayer all : TAB.getInstance().getPlayers()) {
|
||||
if (all == disconnectedPlayer) continue;
|
||||
all.sendCustomPacket(new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.REMOVE_PLAYER, new PlayerInfoData(disconnectedPlayer.getUniqueId())), getFeatureType());
|
||||
}
|
||||
if (TAB.getInstance().getPlayer(disconnectedPlayer.getName()) != null) return; //player reconnected meanwhile, not removing then
|
||||
for (TabPlayer all : TAB.getInstance().getPlayers()) {
|
||||
if (all == disconnectedPlayer) continue;
|
||||
all.sendCustomPacket(new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.REMOVE_PLAYER, new PlayerInfoData(disconnectedPlayer.getUniqueId())), getFeatureType());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.UUID;
|
||||
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
@@ -31,10 +32,10 @@ public class GlobalPlayerlist implements Loadable, JoinEventListener, QuitEventL
|
||||
private List<String> spyServers;
|
||||
private Map<String, List<String>> sharedServers;
|
||||
private boolean displayAsSpectators;
|
||||
public boolean vanishedAsSpectators;
|
||||
private boolean vanishedAsSpectators;
|
||||
private boolean isolateUnlistedServers;
|
||||
|
||||
private List<TabPlayer> vanishedPlayers = new ArrayList<TabPlayer>();
|
||||
private List<TabPlayer> vanishedPlayers = new ArrayList<>();
|
||||
|
||||
public GlobalPlayerlist(TAB tab) {
|
||||
this.tab = tab;
|
||||
@@ -42,11 +43,11 @@ public class GlobalPlayerlist implements Loadable, JoinEventListener, QuitEventL
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
spyServers = tab.getConfiguration().config.getStringList("global-playerlist.spy-servers", Arrays.asList("spaserver1"));
|
||||
sharedServers = tab.getConfiguration().config.getConfigurationSection("global-playerlist.server-groups");
|
||||
displayAsSpectators = tab.getConfiguration().config.getBoolean("global-playerlist.display-others-as-spectators", false);
|
||||
vanishedAsSpectators = tab.getConfiguration().config.getBoolean("global-playerlist.display-vanished-players-as-spectators", true);
|
||||
isolateUnlistedServers = tab.getConfiguration().config.getBoolean("global-playerlist.isolate-unlisted-servers", false);
|
||||
spyServers = tab.getConfiguration().getConfig().getStringList("global-playerlist.spy-servers", Arrays.asList("spaserver1"));
|
||||
sharedServers = tab.getConfiguration().getConfig().getConfigurationSection("global-playerlist.server-groups");
|
||||
displayAsSpectators = tab.getConfiguration().getConfig().getBoolean("global-playerlist.display-others-as-spectators", false);
|
||||
setVanishedAsSpectators(tab.getConfiguration().getConfig().getBoolean("global-playerlist.display-vanished-players-as-spectators", true));
|
||||
isolateUnlistedServers = tab.getConfiguration().getConfig().getBoolean("global-playerlist.isolate-unlisted-servers", false);
|
||||
for (TabPlayer displayed : tab.getPlayers()) {
|
||||
for (TabPlayer viewer : tab.getPlayers()) {
|
||||
if (viewer.getWorldName().equals(displayed.getWorldName())) continue;
|
||||
@@ -54,7 +55,7 @@ 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));
|
||||
spyServers, sharedServers, displayAsSpectators, isVanishedAsSpectators(), isolateUnlistedServers));
|
||||
startTask();
|
||||
}
|
||||
|
||||
@@ -92,8 +93,8 @@ public class GlobalPlayerlist implements Loadable, JoinEventListener, QuitEventL
|
||||
}
|
||||
|
||||
private String getServerGroup(String serverName) {
|
||||
for (String group : sharedServers.keySet()) {
|
||||
if (sharedServers.get(group).contains(serverName)) return group;
|
||||
for (Entry<String, List<String>> group : sharedServers.entrySet()) {
|
||||
if (group.getValue().contains(serverName)) return group.getKey();
|
||||
}
|
||||
return isolateUnlistedServers ? "isolated:" + serverName : "DEFAULT";
|
||||
}
|
||||
@@ -154,7 +155,7 @@ public class GlobalPlayerlist implements Loadable, JoinEventListener, QuitEventL
|
||||
|
||||
public PacketPlayOutPlayerInfo getRemovePacket(TabPlayer p) {
|
||||
PlayerInfoData data = new PlayerInfoData(p.getTablistUUID());
|
||||
data.name = p.getName();
|
||||
data.setName(p.getName());
|
||||
return new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.REMOVE_PLAYER, data);
|
||||
}
|
||||
|
||||
@@ -165,27 +166,27 @@ public class GlobalPlayerlist implements Loadable, JoinEventListener, QuitEventL
|
||||
format = playerlist.getTabFormat(p, viewer);
|
||||
}
|
||||
return new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.ADD_PLAYER, new PlayerInfoData(p.getName(), p.getTablistUUID(), p.getSkin(),
|
||||
(int)p.getPing(), vanishedAsSpectators && p.isVanished() ? EnumGamemode.SPECTATOR : EnumGamemode.CREATIVE, format));
|
||||
(int)p.getPing(), isVanishedAsSpectators() && p.isVanished() ? EnumGamemode.SPECTATOR : EnumGamemode.CREATIVE, format));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSend(TabPlayer receiver, PacketPlayOutPlayerInfo info) {
|
||||
if (info.action == EnumPlayerInfoAction.REMOVE_PLAYER) {
|
||||
for (PlayerInfoData playerInfoData : info.entries) {
|
||||
if (info.getAction() == EnumPlayerInfoAction.REMOVE_PLAYER) {
|
||||
for (PlayerInfoData playerInfoData : info.getEntries()) {
|
||||
//not preventing NPC removals
|
||||
if (tab.getPlayerByTablistUUID(playerInfoData.uniqueId) != null && (playerInfoData.name == null || playerInfoData.name.length() == 0)) {
|
||||
if (tab.getPlayerByTablistUUID(playerInfoData.getUniqueId()) != null && (playerInfoData.getName() == null || playerInfoData.getName().length() == 0)) {
|
||||
//remove packet not coming from tab
|
||||
//changing to random non-existing player, the easiest way to cancel the removal
|
||||
playerInfoData.uniqueId = UUID.randomUUID();
|
||||
playerInfoData.setUniqueId(UUID.randomUUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!displayAsSpectators) return;
|
||||
if (info.action == EnumPlayerInfoAction.ADD_PLAYER || info.action == EnumPlayerInfoAction.UPDATE_GAME_MODE) {
|
||||
for (PlayerInfoData playerInfoData : info.entries) {
|
||||
TabPlayer packetPlayer = tab.getPlayerByTablistUUID(playerInfoData.uniqueId);
|
||||
if (info.getAction() == EnumPlayerInfoAction.ADD_PLAYER || info.getAction() == EnumPlayerInfoAction.UPDATE_GAME_MODE) {
|
||||
for (PlayerInfoData playerInfoData : info.getEntries()) {
|
||||
TabPlayer packetPlayer = tab.getPlayerByTablistUUID(playerInfoData.getUniqueId());
|
||||
if (packetPlayer != null && !receiver.getWorldName().equals(packetPlayer.getWorldName())) {
|
||||
playerInfoData.gameMode = EnumGamemode.SPECTATOR;
|
||||
playerInfoData.setGameMode(EnumGamemode.SPECTATOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -195,4 +196,12 @@ public class GlobalPlayerlist implements Loadable, JoinEventListener, QuitEventL
|
||||
public TabFeature getFeatureType() {
|
||||
return TabFeature.GLOBAL_PLAYERLIST;
|
||||
}
|
||||
|
||||
public boolean isVanishedAsSpectators() {
|
||||
return vanishedAsSpectators;
|
||||
}
|
||||
|
||||
public void setVanishedAsSpectators(boolean vanishedAsSpectators) {
|
||||
this.vanishedAsSpectators = vanishedAsSpectators;
|
||||
}
|
||||
}
|
||||
@@ -16,35 +16,34 @@ import me.neznamy.tab.shared.features.types.Feature;
|
||||
*/
|
||||
public class GroupRefresher implements Feature {
|
||||
|
||||
public static final String DEFAULT_GROUP = "NONE";
|
||||
|
||||
private TAB tab;
|
||||
public boolean groupsByPermissions;
|
||||
public boolean usePrimaryGroup;
|
||||
private boolean groupsByPermissions;
|
||||
private boolean usePrimaryGroup;
|
||||
private List<String> primaryGroupFindingList;
|
||||
|
||||
public GroupRefresher(TAB tab) {
|
||||
this.tab = tab;
|
||||
usePrimaryGroup = tab.getConfiguration().config.getBoolean("use-primary-group", true);
|
||||
groupsByPermissions = tab.getConfiguration().config.getBoolean("assign-groups-by-permissions", false);
|
||||
primaryGroupFindingList = new ArrayList<String>();
|
||||
for (Object group : tab.getConfiguration().config.getStringList("primary-group-finding-list", Arrays.asList("Owner", "Admin", "Helper", "default"))){
|
||||
usePrimaryGroup = tab.getConfiguration().getConfig().getBoolean("use-primary-group", true);
|
||||
groupsByPermissions = tab.getConfiguration().getConfig().getBoolean("assign-groups-by-permissions", false);
|
||||
primaryGroupFindingList = new ArrayList<>();
|
||||
for (Object group : tab.getConfiguration().getConfig().getStringList("primary-group-finding-list", Arrays.asList("Owner", "Admin", "Helper", "default"))){
|
||||
primaryGroupFindingList.add(group.toString());
|
||||
}
|
||||
tab.getCPUManager().startRepeatingMeasuredTask(1000, "refreshing permission groups", getFeatureType(), UsageType.REPEATING_TASK, new Runnable() {
|
||||
tab.getCPUManager().startRepeatingMeasuredTask(1000, "refreshing permission groups", getFeatureType(), UsageType.REPEATING_TASK, () -> {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for (TabPlayer p : tab.getPlayers()) {
|
||||
((ITabPlayer) p).setGroup(detectPermissionGroup(p), true);
|
||||
}
|
||||
for (TabPlayer p : tab.getPlayers()) {
|
||||
((ITabPlayer) p).setGroup(detectPermissionGroup(p), true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public String detectPermissionGroup(TabPlayer p) {
|
||||
if (groupsByPermissions) {
|
||||
if (isGroupsByPermissions()) {
|
||||
return getByPermission(p);
|
||||
}
|
||||
if (usePrimaryGroup) {
|
||||
if (isUsePrimaryGroup()) {
|
||||
return getByPrimary(p);
|
||||
}
|
||||
return getFromList(p);
|
||||
@@ -53,8 +52,8 @@ public class GroupRefresher implements Feature {
|
||||
public String getByPrimary(TabPlayer p) {
|
||||
try {
|
||||
return tab.getPermissionPlugin().getPrimaryGroup(p);
|
||||
} catch (Throwable e) {
|
||||
return tab.getErrorManager().printError("<null>", "Failed to get permission group of " + p.getName() + " using " + tab.getPermissionPlugin().getName() + " v" + tab.getPermissionPlugin().getVersion(), e);
|
||||
} catch (Exception e) {
|
||||
return tab.getErrorManager().printError(DEFAULT_GROUP, "Failed to get permission group of " + p.getName() + " using " + tab.getPermissionPlugin().getName() + " v" + tab.getPermissionPlugin().getVersion(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,10 +70,10 @@ public class GroupRefresher implements Feature {
|
||||
}
|
||||
return playerGroups[0];
|
||||
} else {
|
||||
return "<null>";
|
||||
return DEFAULT_GROUP;
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
return tab.getErrorManager().printError("<null>", "Failed to get permission groups of " + p.getName() + " using " + tab.getPermissionPlugin().getName() + " v" + tab.getPermissionPlugin().getVersion(), e);
|
||||
} catch (Exception e) {
|
||||
return tab.getErrorManager().printError(DEFAULT_GROUP, "Failed to get permission groups of " + p.getName() + " using " + tab.getPermissionPlugin().getName() + " v" + tab.getPermissionPlugin().getVersion(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,11 +84,19 @@ public class GroupRefresher implements Feature {
|
||||
}
|
||||
}
|
||||
tab.getErrorManager().oneTimeConsoleError("Player " + p.getName() + " does not have any group permission while assign-groups-by-permissions is enabled! Did you forget to add his group to primary-group-finding-list?");
|
||||
return "<null>";
|
||||
return DEFAULT_GROUP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TabFeature getFeatureType() {
|
||||
return TabFeature.GROUP_REFRESHING;
|
||||
}
|
||||
|
||||
public boolean isGroupsByPermissions() {
|
||||
return groupsByPermissions;
|
||||
}
|
||||
|
||||
public boolean isUsePrimaryGroup() {
|
||||
return usePrimaryGroup;
|
||||
}
|
||||
}
|
||||
@@ -2,14 +2,18 @@ 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.PropertyUtils;
|
||||
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.Refreshable;
|
||||
import me.neznamy.tab.shared.features.types.event.JoinEventListener;
|
||||
import me.neznamy.tab.shared.features.types.event.QuitEventListener;
|
||||
import me.neznamy.tab.shared.features.types.event.WorldChangeListener;
|
||||
import me.neznamy.tab.shared.packets.IChatBaseComponent;
|
||||
import me.neznamy.tab.shared.packets.PacketPlayOutPlayerListHeaderFooter;
|
||||
@@ -17,15 +21,17 @@ import me.neznamy.tab.shared.packets.PacketPlayOutPlayerListHeaderFooter;
|
||||
/**
|
||||
* Feature handler for header and footer
|
||||
*/
|
||||
public class HeaderFooter implements Loadable, JoinEventListener, WorldChangeListener, Refreshable {
|
||||
public class HeaderFooter implements Loadable, JoinEventListener, QuitEventListener, WorldChangeListener, Refreshable {
|
||||
|
||||
private static final String LINE_SEPARATOR = "\n\u00a7r";
|
||||
private TAB tab;
|
||||
private List<String> usedPlaceholders;
|
||||
public List<String> disabledWorlds;
|
||||
private List<String> disabledWorlds;
|
||||
private Set<TabPlayer> playersInDisabledWorlds = new HashSet<>();
|
||||
|
||||
public HeaderFooter(TAB tab) {
|
||||
this.tab = tab;
|
||||
disabledWorlds = tab.getConfiguration().config.getStringList("disable-features-in-"+tab.getPlatform().getSeparatorType()+"s.header-footer", Arrays.asList("disabled" + tab.getPlatform().getSeparatorType()));
|
||||
disabledWorlds = tab.getConfiguration().getConfig().getStringList("disable-features-in-"+tab.getPlatform().getSeparatorType()+"s.header-footer", Arrays.asList("disabled" + tab.getPlatform().getSeparatorType()));
|
||||
refreshUsedPlaceholders();
|
||||
tab.debug(String.format("Loaded HeaderFooter feature with parameters disabledWorlds=%s", disabledWorlds));
|
||||
}
|
||||
@@ -33,48 +39,64 @@ public class HeaderFooter implements Loadable, JoinEventListener, WorldChangeLis
|
||||
@Override
|
||||
public void load() {
|
||||
for (TabPlayer p : tab.getPlayers()) {
|
||||
refresh(p, true);
|
||||
onJoin(p);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unload() {
|
||||
for (TabPlayer p : tab.getPlayers()) {
|
||||
if (isDisabledWorld(disabledWorlds, p.getWorldName()) || p.getVersion().getMinorVersion() < 8) continue;
|
||||
if (playersInDisabledWorlds.contains(p) || p.getVersion().getMinorVersion() < 8) continue;
|
||||
p.sendCustomPacket(new PacketPlayOutPlayerListHeaderFooter("",""), getFeatureType());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onJoin(TabPlayer connectedPlayer) {
|
||||
if (isDisabledWorld(disabledWorlds, connectedPlayer.getWorldName())) {
|
||||
playersInDisabledWorlds.add(connectedPlayer);
|
||||
return;
|
||||
}
|
||||
refresh(connectedPlayer, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWorldChange(TabPlayer p, String from, String to) {
|
||||
if (p.getVersion().getMinorVersion() < 8) return;
|
||||
boolean disabledBefore = playersInDisabledWorlds.contains(p);
|
||||
boolean disabledNow = false;
|
||||
if (isDisabledWorld(disabledWorlds, p.getWorldName())) {
|
||||
if (!isDisabledWorld(disabledWorlds, from)) p.sendCustomPacket(new PacketPlayOutPlayerListHeaderFooter("", ""), getFeatureType());
|
||||
disabledNow = true;
|
||||
playersInDisabledWorlds.add(p);
|
||||
} else {
|
||||
playersInDisabledWorlds.remove(p);
|
||||
}
|
||||
if (p.getVersion().getMinorVersion() < 8) return;
|
||||
if (disabledNow) {
|
||||
if (!disabledBefore) p.sendCustomPacket(new PacketPlayOutPlayerListHeaderFooter("", ""), getFeatureType());
|
||||
} else {
|
||||
if (disabledBefore) {
|
||||
refresh(p, true);
|
||||
return;
|
||||
}
|
||||
boolean refresh = false;
|
||||
String headerAppend = getValue(p, "headerappend");
|
||||
if (headerAppend.length() > 0) headerAppend = "\n\u00a7r" + headerAppend;
|
||||
String header = getValue(p, "header") + headerAppend;
|
||||
if (!p.getProperty("header").getOriginalRawValue().equals(header)) {
|
||||
p.setProperty("header", header);
|
||||
if (headerAppend.length() > 0) headerAppend = LINE_SEPARATOR + headerAppend;
|
||||
String header = getValue(p, PropertyUtils.HEADER) + headerAppend;
|
||||
if (!p.getProperty(PropertyUtils.HEADER).getOriginalRawValue().equals(header)) {
|
||||
p.setProperty(PropertyUtils.HEADER, header);
|
||||
refresh = true;
|
||||
}
|
||||
|
||||
String footerAppend = getValue(p, "footerappend");
|
||||
if (footerAppend.length() > 0) footerAppend = "\n\u00a7r" + footerAppend;
|
||||
String footer = getValue(p, "footer") + footerAppend;
|
||||
if (!p.getProperty("footer").getOriginalRawValue().equals(footer)) {
|
||||
p.setProperty("footer", footer);
|
||||
if (footerAppend.length() > 0) footerAppend = LINE_SEPARATOR + footerAppend;
|
||||
String footer = getValue(p, PropertyUtils.FOOTER) + footerAppend;
|
||||
if (!p.getProperty(PropertyUtils.FOOTER).getOriginalRawValue().equals(footer)) {
|
||||
p.setProperty(PropertyUtils.FOOTER, footer);
|
||||
refresh = true;
|
||||
}
|
||||
if (refresh) {
|
||||
p.sendCustomPacket(new PacketPlayOutPlayerListHeaderFooter(IChatBaseComponent.optimizedComponent(p.getProperty("header").updateAndGet()),
|
||||
IChatBaseComponent.optimizedComponent(p.getProperty("footer").updateAndGet())), getFeatureType());
|
||||
p.sendCustomPacket(new PacketPlayOutPlayerListHeaderFooter(IChatBaseComponent.optimizedComponent(p.getProperty(PropertyUtils.HEADER).updateAndGet()),
|
||||
IChatBaseComponent.optimizedComponent(p.getProperty(PropertyUtils.FOOTER).updateAndGet())), getFeatureType());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -83,16 +105,16 @@ public class HeaderFooter implements Loadable, JoinEventListener, WorldChangeLis
|
||||
public void refresh(TabPlayer p, boolean force) {
|
||||
if (force) {
|
||||
String headerAppend = getValue(p, "headerappend");
|
||||
if (headerAppend.length() > 0) headerAppend = "\n\u00a7r" + headerAppend;
|
||||
p.setProperty("header", getValue(p, "header") + headerAppend);
|
||||
if (headerAppend.length() > 0) headerAppend = LINE_SEPARATOR + headerAppend;
|
||||
p.setProperty(PropertyUtils.HEADER, getValue(p, PropertyUtils.HEADER) + headerAppend);
|
||||
|
||||
String footerAppend = getValue(p, "footerappend");
|
||||
if (footerAppend.length() > 0) footerAppend = "\n\u00a7r" + footerAppend;
|
||||
p.setProperty("footer", getValue(p, "footer") + footerAppend);
|
||||
if (footerAppend.length() > 0) footerAppend = LINE_SEPARATOR + footerAppend;
|
||||
p.setProperty(PropertyUtils.FOOTER, getValue(p, PropertyUtils.FOOTER) + footerAppend);
|
||||
}
|
||||
if (isDisabledWorld(disabledWorlds, p.getWorldName()) || p.getVersion().getMinorVersion() < 8) return;
|
||||
p.sendCustomPacket(new PacketPlayOutPlayerListHeaderFooter(IChatBaseComponent.optimizedComponent(p.getProperty("header").updateAndGet()),
|
||||
IChatBaseComponent.optimizedComponent(p.getProperty("footer").updateAndGet())), getFeatureType());
|
||||
if (playersInDisabledWorlds.contains(p) || p.getVersion().getMinorVersion() < 8) return;
|
||||
p.sendCustomPacket(new PacketPlayOutPlayerListHeaderFooter(IChatBaseComponent.optimizedComponent(p.getProperty(PropertyUtils.HEADER).updateAndGet()),
|
||||
IChatBaseComponent.optimizedComponent(p.getProperty(PropertyUtils.FOOTER).updateAndGet())), getFeatureType());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -101,7 +123,7 @@ public class HeaderFooter implements Loadable, JoinEventListener, WorldChangeLis
|
||||
}
|
||||
|
||||
private String getValue(TabPlayer p, String property) {
|
||||
String worldGroup = tab.getConfiguration().getWorldGroupOf(p.getWorldName());
|
||||
String worldGroup = tab.getConfiguration().getWorldGroupOf(tab.getConfiguration().getConfig().getConfigurationSection("per-" + tab.getPlatform().getSeparatorType() + "-settings").keySet(), p.getWorldName());
|
||||
String[] priorities = {
|
||||
"per-" + tab.getPlatform().getSeparatorType() + "-settings." + worldGroup + ".Users." + p.getName() + "." + property,
|
||||
"per-" + tab.getPlatform().getSeparatorType() + "-settings." + worldGroup + ".Users." + p.getUniqueId().toString() + "." + property,
|
||||
@@ -114,20 +136,25 @@ public class HeaderFooter implements Loadable, JoinEventListener, WorldChangeLis
|
||||
};
|
||||
List<String> lines = null;
|
||||
for (String path : priorities) {
|
||||
lines = tab.getConfiguration().config.getStringList(path);
|
||||
lines = tab.getConfiguration().getConfig().getStringList(path);
|
||||
if (lines != null) break;
|
||||
}
|
||||
if (lines == null) lines = new ArrayList<String>();
|
||||
return String.join("\n\u00a7r", lines);
|
||||
if (lines == null) lines = new ArrayList<>();
|
||||
return String.join(LINE_SEPARATOR, lines);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshUsedPlaceholders() {
|
||||
usedPlaceholders = tab.getConfiguration().config.getUsedPlaceholderIdentifiersRecursive("header", "footer");
|
||||
usedPlaceholders = tab.getConfiguration().getConfig().getUsedPlaceholderIdentifiersRecursive(PropertyUtils.HEADER, PropertyUtils.FOOTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TabFeature getFeatureType() {
|
||||
return TabFeature.HEADER_FOOTER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onQuit(TabPlayer disconnectedPlayer) {
|
||||
playersInDisabledWorlds.remove(disconnectedPlayer);
|
||||
}
|
||||
}
|
||||
@@ -1,365 +0,0 @@
|
||||
package me.neznamy.tab.shared.features;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
|
||||
/**
|
||||
* Universal code for metrics classes
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public abstract class Metrics {
|
||||
|
||||
public final int B_STATS_VERSION = 1;
|
||||
private String URL;
|
||||
protected boolean logSentData;
|
||||
protected boolean enabled;
|
||||
protected String serverUUID;
|
||||
protected boolean logResponseStatusText;
|
||||
protected boolean logFailedRequests;
|
||||
protected List<CustomChart> charts = new ArrayList<CustomChart>();
|
||||
|
||||
public Metrics(String URL) {
|
||||
this.URL = URL;
|
||||
}
|
||||
|
||||
public void addCustomChart(CustomChart chart) {
|
||||
if (chart == null) {
|
||||
throw new IllegalArgumentException("Chart cannot be null!");
|
||||
}
|
||||
charts.add(chart);
|
||||
}
|
||||
|
||||
public JSONObject getPluginData() {
|
||||
TAB tab = TAB.getInstance();
|
||||
JSONObject data = new JSONObject();
|
||||
|
||||
String pluginName = "TAB Reborn";
|
||||
String pluginVersion = tab.getPluginVersion();
|
||||
if (tab.isPremium()) pluginVersion += " Premium";
|
||||
|
||||
data.put("pluginName", pluginName);
|
||||
data.put("pluginVersion", pluginVersion);
|
||||
JSONArray customCharts = new JSONArray();
|
||||
for (CustomChart customChart : charts) {
|
||||
JSONObject chart = customChart.getRequestJSONObject();
|
||||
if (chart == null) {
|
||||
continue;
|
||||
}
|
||||
customCharts.add(chart);
|
||||
}
|
||||
data.put("customCharts", customCharts);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public void sendData(JSONObject data, boolean logResponseStatusText) throws Exception {
|
||||
if (data == null) {
|
||||
throw new IllegalArgumentException("Data cannot be null!");
|
||||
}
|
||||
if (logSentData) {
|
||||
System.out.println("[TAB] Sending data to bStats: " + data.toString());
|
||||
}
|
||||
HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection();
|
||||
|
||||
// Compress the data to save bandwidth
|
||||
byte[] compressedData = compress(data.toString());
|
||||
|
||||
// Add headers
|
||||
connection.setRequestMethod("POST");
|
||||
connection.addRequestProperty("Accept", "application/json");
|
||||
connection.addRequestProperty("Connection", "close");
|
||||
connection.addRequestProperty("Content-Encoding", "gzip"); // We gzip our request
|
||||
connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length));
|
||||
connection.setRequestProperty("Content-Type", "application/json"); // We send our data in JSON format
|
||||
connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION);
|
||||
|
||||
// Send data
|
||||
connection.setDoOutput(true);
|
||||
DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());
|
||||
outputStream.write(compressedData);
|
||||
outputStream.flush();
|
||||
outputStream.close();
|
||||
|
||||
InputStream inputStream = connection.getInputStream();
|
||||
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
String line;
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
builder.append(line);
|
||||
}
|
||||
bufferedReader.close();
|
||||
if (logResponseStatusText) {
|
||||
System.out.println("[TAB] Sent data to bStats and received response: " + builder.toString());
|
||||
}
|
||||
}
|
||||
|
||||
protected byte[] compress(String str) throws IOException {
|
||||
if (str == null) {
|
||||
return null;
|
||||
}
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
GZIPOutputStream gzip = new GZIPOutputStream(outputStream);
|
||||
gzip.write(str.getBytes(StandardCharsets.UTF_8));
|
||||
gzip.close();
|
||||
return outputStream.toByteArray();
|
||||
}
|
||||
|
||||
public static abstract class CustomChart {
|
||||
|
||||
private String chartId;
|
||||
|
||||
public CustomChart(String chartId) {
|
||||
if (chartId == null || chartId.isEmpty()) {
|
||||
throw new IllegalArgumentException("ChartId cannot be null or empty!");
|
||||
}
|
||||
this.chartId = chartId;
|
||||
}
|
||||
|
||||
public JSONObject getRequestJSONObject() {
|
||||
JSONObject chart = new JSONObject();
|
||||
chart.put("chartId", chartId);
|
||||
try {
|
||||
JSONObject data = getChartData();
|
||||
if (data == null) {
|
||||
return null;
|
||||
}
|
||||
chart.put("data", data);
|
||||
} catch (Throwable t) {
|
||||
return null;
|
||||
}
|
||||
return chart;
|
||||
}
|
||||
|
||||
protected abstract JSONObject getChartData() throws Exception;
|
||||
}
|
||||
|
||||
public static class SimplePie extends CustomChart {
|
||||
|
||||
private Callable<String> callable;
|
||||
|
||||
public SimplePie(String chartId, Callable<String> callable) {
|
||||
super(chartId);
|
||||
this.callable = callable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JSONObject getChartData() throws Exception {
|
||||
JSONObject data = new JSONObject();
|
||||
String value = callable.call();
|
||||
if (value == null || value.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
data.put("value", value);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
public static class AdvancedPie extends CustomChart {
|
||||
|
||||
private Callable<Map<String, Integer>> callable;
|
||||
|
||||
public AdvancedPie(String chartId, Callable<Map<String, Integer>> callable) {
|
||||
super(chartId);
|
||||
this.callable = callable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JSONObject getChartData() throws Exception {
|
||||
JSONObject data = new JSONObject();
|
||||
JSONObject values = new JSONObject();
|
||||
Map<String, Integer> map = callable.call();
|
||||
if (map == null || map.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
boolean allSkipped = true;
|
||||
for (Map.Entry<String, Integer> entry : map.entrySet()) {
|
||||
if (entry.getValue() == 0) {
|
||||
continue;
|
||||
}
|
||||
allSkipped = false;
|
||||
values.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
if (allSkipped) {
|
||||
return null;
|
||||
}
|
||||
data.put("values", values);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
public static class DrilldownPie extends CustomChart {
|
||||
|
||||
private Callable<Map<String, Map<String, Integer>>> callable;
|
||||
|
||||
public DrilldownPie(String chartId, Callable<Map<String, Map<String, Integer>>> callable) {
|
||||
super(chartId);
|
||||
this.callable = callable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject getChartData() throws Exception {
|
||||
JSONObject data = new JSONObject();
|
||||
JSONObject values = new JSONObject();
|
||||
Map<String, Map<String, Integer>> map = callable.call();
|
||||
if (map == null || map.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
boolean reallyAllSkipped = true;
|
||||
for (Map.Entry<String, Map<String, Integer>> entryValues : map.entrySet()) {
|
||||
JSONObject value = new JSONObject();
|
||||
boolean allSkipped = true;
|
||||
for (Map.Entry<String, Integer> valueEntry : map.get(entryValues.getKey()).entrySet()) {
|
||||
value.put(valueEntry.getKey(), valueEntry.getValue());
|
||||
allSkipped = false;
|
||||
}
|
||||
if (!allSkipped) {
|
||||
reallyAllSkipped = false;
|
||||
values.put(entryValues.getKey(), value);
|
||||
}
|
||||
}
|
||||
if (reallyAllSkipped) {
|
||||
return null;
|
||||
}
|
||||
data.put("values", values);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
public static class SingleLineChart extends CustomChart {
|
||||
|
||||
private Callable<Integer> callable;
|
||||
|
||||
public SingleLineChart(String chartId, Callable<Integer> callable) {
|
||||
super(chartId);
|
||||
this.callable = callable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JSONObject getChartData() throws Exception {
|
||||
JSONObject data = new JSONObject();
|
||||
int value = callable.call();
|
||||
if (value == 0) {
|
||||
return null;
|
||||
}
|
||||
data.put("value", value);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
public static class MultiLineChart extends CustomChart {
|
||||
|
||||
private Callable<Map<String, Integer>> callable;
|
||||
|
||||
public MultiLineChart(String chartId, Callable<Map<String, Integer>> callable) {
|
||||
super(chartId);
|
||||
this.callable = callable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JSONObject getChartData() throws Exception {
|
||||
JSONObject data = new JSONObject();
|
||||
JSONObject values = new JSONObject();
|
||||
Map<String, Integer> map = callable.call();
|
||||
if (map == null || map.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
boolean allSkipped = true;
|
||||
for (Map.Entry<String, Integer> entry : map.entrySet()) {
|
||||
if (entry.getValue() == 0) {
|
||||
continue;
|
||||
}
|
||||
allSkipped = false;
|
||||
values.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
if (allSkipped) {
|
||||
return null;
|
||||
}
|
||||
data.put("values", values);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
public static class SimpleBarChart extends CustomChart {
|
||||
|
||||
private Callable<Map<String, Integer>> callable;
|
||||
|
||||
public SimpleBarChart(String chartId, Callable<Map<String, Integer>> callable) {
|
||||
super(chartId);
|
||||
this.callable = callable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JSONObject getChartData() throws Exception {
|
||||
JSONObject data = new JSONObject();
|
||||
JSONObject values = new JSONObject();
|
||||
Map<String, Integer> map = callable.call();
|
||||
if (map == null || map.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
for (Map.Entry<String, Integer> entry : map.entrySet()) {
|
||||
JSONArray categoryValues = new JSONArray();
|
||||
categoryValues.add(entry.getValue());
|
||||
values.put(entry.getKey(), categoryValues);
|
||||
}
|
||||
data.put("values", values);
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class AdvancedBarChart extends CustomChart {
|
||||
|
||||
private Callable<Map<String, int[]>> callable;
|
||||
|
||||
public AdvancedBarChart(String chartId, Callable<Map<String, int[]>> callable) {
|
||||
super(chartId);
|
||||
this.callable = callable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JSONObject getChartData() throws Exception {
|
||||
JSONObject data = new JSONObject();
|
||||
JSONObject values = new JSONObject();
|
||||
Map<String, int[]> map = callable.call();
|
||||
if (map == null || map.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
boolean allSkipped = true;
|
||||
for (Map.Entry<String, int[]> entry : map.entrySet()) {
|
||||
if (entry.getValue().length == 0) {
|
||||
continue;
|
||||
}
|
||||
allSkipped = false;
|
||||
JSONArray categoryValues = new JSONArray();
|
||||
for (int categoryValue : entry.getValue()) {
|
||||
categoryValues.add(categoryValue);
|
||||
}
|
||||
values.put(entry.getKey(), categoryValues);
|
||||
}
|
||||
if (allSkipped) {
|
||||
return null;
|
||||
}
|
||||
data.put("values", values);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ 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;
|
||||
import me.neznamy.tab.shared.PropertyUtils;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.cpu.TabFeature;
|
||||
import me.neznamy.tab.shared.cpu.UsageType;
|
||||
@@ -33,21 +33,22 @@ public class NameTag implements Loadable, Refreshable, LoginPacketListener, Quit
|
||||
private boolean collisionRule;
|
||||
private List<String> revertedCollision;
|
||||
private boolean invisibleNametags;
|
||||
protected Set<String> invisiblePlayers = new HashSet<String>();
|
||||
public Sorting sorting;
|
||||
protected Map<TabPlayer, Boolean> collision = new HashMap<TabPlayer, Boolean>();
|
||||
protected Set<String> invisiblePlayers = new HashSet<>();
|
||||
private Sorting sorting;
|
||||
protected Map<String, Boolean> collision = new HashMap<>();
|
||||
protected Set<TabPlayer> playersInDisabledWorlds = new HashSet<>();
|
||||
|
||||
public NameTag(TAB tab) {
|
||||
this.tab = tab;
|
||||
disabledWorlds = tab.getConfiguration().config.getStringList("disable-features-in-"+tab.getPlatform().getSeparatorType()+"s.nametag", Arrays.asList("disabled" + tab.getPlatform().getSeparatorType()));
|
||||
collisionRule = tab.getConfiguration().config.getBoolean("enable-collision", true);
|
||||
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);
|
||||
disabledWorlds = tab.getConfiguration().getConfig().getStringList("disable-features-in-"+tab.getPlatform().getSeparatorType()+"s.nametag", Arrays.asList("disabled" + tab.getPlatform().getSeparatorType()));
|
||||
collisionRule = tab.getConfiguration().getConfig().getBoolean("enable-collision", true);
|
||||
revertedCollision = tab.getConfiguration().getConfig().getStringList("revert-collision-rule-in-" + tab.getPlatform().getSeparatorType()+"s", Arrays.asList("reverted" + tab.getPlatform().getSeparatorType()));
|
||||
invisibleNametags = tab.getConfiguration().getConfig().getBoolean("invisible-nametags", false);
|
||||
sorting = new Sorting(tab, this);
|
||||
usedPlaceholders = new HashSet<>(tab.getConfiguration().config.getUsedPlaceholderIdentifiersRecursive("tagprefix", "tagsuffix"));
|
||||
usedPlaceholders = new HashSet<>(tab.getConfiguration().getConfig().getUsedPlaceholderIdentifiersRecursive(PropertyUtils.TAGPREFIX, PropertyUtils.TAGSUFFIX));
|
||||
for (TabPlayer p : tab.getPlayers()) {
|
||||
usedPlaceholders.addAll(tab.getPlaceholderManager().getUsedPlaceholderIdentifiersRecursive(
|
||||
p.getProperty("tagprefix").getCurrentRawValue(), p.getProperty("tagsuffix").getCurrentRawValue()));
|
||||
p.getProperty(PropertyUtils.TAGPREFIX).getCurrentRawValue(), p.getProperty(PropertyUtils.TAGSUFFIX).getCurrentRawValue()));
|
||||
}
|
||||
tab.debug(String.format("Loaded NameTag feature with parameters collisionRule=%s, revertedCollision=%s, disabledWorlds=%s, invisibleNametags=%s",
|
||||
collisionRule, revertedCollision, disabledWorlds, invisibleNametags));
|
||||
@@ -56,11 +57,14 @@ public class NameTag implements Loadable, Refreshable, LoginPacketListener, Quit
|
||||
@Override
|
||||
public void load(){
|
||||
for (TabPlayer all : tab.getPlayers()) {
|
||||
((ITabPlayer) all).setTeamName(sorting.getTeamName(all));
|
||||
((ITabPlayer) all).setTeamName(getSorting().getTeamName(all));
|
||||
updateProperties(all);
|
||||
collision.put(all, true);
|
||||
collision.put(all.getName(), true);
|
||||
if (all.hasInvisibilityPotion()) invisiblePlayers.add(all.getName());
|
||||
if (isDisabledWorld(all.getWorldName())) continue;
|
||||
if (isDisabledWorld(disabledWorlds, all.getWorldName())) {
|
||||
playersInDisabledWorlds.add(all);
|
||||
continue;
|
||||
}
|
||||
registerTeam(all);
|
||||
}
|
||||
startRefreshingTasks();
|
||||
@@ -69,33 +73,32 @@ public class NameTag implements Loadable, Refreshable, LoginPacketListener, Quit
|
||||
@Override
|
||||
public void unload() {
|
||||
for (TabPlayer p : tab.getPlayers()) {
|
||||
if (!isDisabledWorld(p.getWorldName())) unregisterTeam(p);
|
||||
if (!playersInDisabledWorlds.contains(p)) unregisterTeam(p);
|
||||
}
|
||||
}
|
||||
|
||||
public void startRefreshingTasks() {
|
||||
//workaround for a 1.8.x client-sided bug
|
||||
tab.getCPUManager().startRepeatingMeasuredTask(500, "refreshing nametag visibility", TabFeature.NAMETAGS, UsageType.REFRESHING_NAMETAG_VISIBILITY_AND_COLLISION, new Runnable() {
|
||||
public void run() {
|
||||
tab.getCPUManager().startRepeatingMeasuredTask(500, "refreshing nametag visibility", TabFeature.NAMETAGS, UsageType.REFRESHING_NAMETAG_VISIBILITY_AND_COLLISION, () -> {
|
||||
|
||||
for (TabPlayer p : tab.getPlayers()) {
|
||||
if (!p.isLoaded() || playersInDisabledWorlds.contains(p)) continue;
|
||||
//nametag visibility
|
||||
for (TabPlayer p : tab.getPlayers()) {
|
||||
if (!p.isLoaded() || isDisabledWorld(p.getWorldName())) continue;
|
||||
boolean invisible = p.hasInvisibilityPotion();
|
||||
if (invisible && !invisiblePlayers.contains(p.getName())) {
|
||||
invisiblePlayers.add(p.getName());
|
||||
updateTeamData(p);
|
||||
}
|
||||
if (!invisible && invisiblePlayers.contains(p.getName())) {
|
||||
invisiblePlayers.remove(p.getName());
|
||||
updateTeamData(p);
|
||||
}
|
||||
//cannot control collision rule on <1.9 servers in any way
|
||||
if (ProtocolVersion.SERVER_VERSION.getMinorVersion() >= 9) updateCollision(p);
|
||||
boolean invisible = p.hasInvisibilityPotion();
|
||||
if (invisible && !invisiblePlayers.contains(p.getName())) {
|
||||
invisiblePlayers.add(p.getName());
|
||||
updateTeamData(p);
|
||||
}
|
||||
if (!invisible && invisiblePlayers.contains(p.getName())) {
|
||||
invisiblePlayers.remove(p.getName());
|
||||
updateTeamData(p);
|
||||
}
|
||||
//cannot control collision rule on <1.9 servers in any way
|
||||
if (TAB.getInstance().getServerVersion().getMinorVersion() >= 9) updateCollision(p);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public boolean isDisabledWorld(String world) {
|
||||
return isDisabledWorld(disabledWorlds, world);
|
||||
}
|
||||
@@ -113,19 +116,19 @@ public class NameTag implements Loadable, Refreshable, LoginPacketListener, Quit
|
||||
if (p.hasTeamHandlingPaused()) return;
|
||||
if (p.getTeamName() == null) return;
|
||||
for (TabPlayer viewer : tab.getPlayers()) {
|
||||
viewer.sendCustomPacket(new PacketPlayOutScoreboardTeam(p.getTeamName()).setTeamOptions(69), TabFeature.NAMETAGS);
|
||||
viewer.sendCustomPacket(new PacketPlayOutScoreboardTeam(p.getTeamName()), TabFeature.NAMETAGS);
|
||||
}
|
||||
}
|
||||
|
||||
public void unregisterTeam(TabPlayer p, TabPlayer viewer) {
|
||||
if (p.hasTeamHandlingPaused()) return;
|
||||
viewer.sendCustomPacket(new PacketPlayOutScoreboardTeam(p.getTeamName()).setTeamOptions(69), TabFeature.NAMETAGS);
|
||||
viewer.sendCustomPacket(new PacketPlayOutScoreboardTeam(p.getTeamName()), TabFeature.NAMETAGS);
|
||||
}
|
||||
|
||||
public void registerTeam(TabPlayer p) {
|
||||
if (p.hasTeamHandlingPaused()) return;
|
||||
Property tagprefix = p.getProperty("tagprefix");
|
||||
Property tagsuffix = p.getProperty("tagsuffix");
|
||||
Property tagprefix = p.getProperty(PropertyUtils.TAGPREFIX);
|
||||
Property tagsuffix = p.getProperty(PropertyUtils.TAGSUFFIX);
|
||||
for (TabPlayer viewer : tab.getPlayers()) {
|
||||
String currentPrefix = tagprefix.getFormat(viewer);
|
||||
String currentSuffix = tagsuffix.getFormat(viewer);
|
||||
@@ -135,8 +138,8 @@ 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");
|
||||
Property tagprefix = p.getProperty(PropertyUtils.TAGPREFIX);
|
||||
Property tagsuffix = p.getProperty(PropertyUtils.TAGSUFFIX);
|
||||
String replacedPrefix = tagprefix.getFormat(viewer);
|
||||
String replacedSuffix = tagsuffix.getFormat(viewer);
|
||||
PacketAPI.registerScoreboardTeam(viewer, p.getTeamName(), replacedPrefix, replacedSuffix, getTeamVisibility(p, viewer), getCollision(p), Arrays.asList(p.getName()), null, TabFeature.NAMETAGS);
|
||||
@@ -144,7 +147,7 @@ public class NameTag implements Loadable, Refreshable, LoginPacketListener, Quit
|
||||
|
||||
public void updateTeam(TabPlayer p) {
|
||||
if (p.getTeamName() == null) return; //player not loaded yet
|
||||
String newName = sorting.getTeamName(p);
|
||||
String newName = getSorting().getTeamName(p);
|
||||
if (p.getTeamName().equals(newName)) {
|
||||
updateTeamData(p);
|
||||
} else {
|
||||
@@ -155,47 +158,52 @@ public class NameTag implements Loadable, Refreshable, LoginPacketListener, Quit
|
||||
}
|
||||
|
||||
public void updateTeamData(TabPlayer p) {
|
||||
Property tagprefix = p.getProperty("tagprefix");
|
||||
Property tagsuffix = p.getProperty("tagsuffix");
|
||||
Property tagprefix = p.getProperty(PropertyUtils.TAGPREFIX);
|
||||
Property tagsuffix = p.getProperty(PropertyUtils.TAGSUFFIX);
|
||||
for (TabPlayer viewer : tab.getPlayers()) {
|
||||
String currentPrefix = tagprefix.getFormat(viewer);
|
||||
String currentSuffix = tagsuffix.getFormat(viewer);
|
||||
boolean visible = getTeamVisibility(p, viewer);
|
||||
viewer.sendCustomPacket(new PacketPlayOutScoreboardTeam(p.getTeamName(), currentPrefix, currentSuffix, visible?"always":"never", getCollision(p)?"always":"never", 69), TabFeature.NAMETAGS);
|
||||
viewer.sendCustomPacket(new PacketPlayOutScoreboardTeam(p.getTeamName(), currentPrefix, currentSuffix, translate(visible), translate(getCollision(p)), 0), TabFeature.NAMETAGS);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateTeamData(TabPlayer p, TabPlayer viewer) {
|
||||
Property tagprefix = p.getProperty("tagprefix");
|
||||
Property tagsuffix = p.getProperty("tagsuffix");
|
||||
Property tagprefix = p.getProperty(PropertyUtils.TAGPREFIX);
|
||||
Property tagsuffix = p.getProperty(PropertyUtils.TAGSUFFIX);
|
||||
boolean visible = getTeamVisibility(p, viewer);
|
||||
String currentPrefix = tagprefix.getFormat(viewer);
|
||||
String currentSuffix = tagsuffix.getFormat(viewer);
|
||||
viewer.sendCustomPacket(new PacketPlayOutScoreboardTeam(p.getTeamName(), currentPrefix, currentSuffix, visible?"always":"never", getCollision(p)?"always":"never", 69), TabFeature.NAMETAGS);
|
||||
viewer.sendCustomPacket(new PacketPlayOutScoreboardTeam(p.getTeamName(), currentPrefix, currentSuffix, translate(visible), translate(getCollision(p)), 0), TabFeature.NAMETAGS);
|
||||
}
|
||||
|
||||
private String translate(boolean b) {
|
||||
return b ? "always" : "never";
|
||||
}
|
||||
|
||||
private void updateCollision(TabPlayer p) {
|
||||
if (TAB.getInstance().getFeatureManager().getNameTagFeature() == null) return;
|
||||
if (TAB.getInstance().getFeatureManager().getNameTagFeature() == null || !p.isOnline()) return;
|
||||
if (p.getCollisionRule() != null) {
|
||||
if (getCollision(p) != p.getCollisionRule()) {
|
||||
collision.put(p, p.getCollisionRule());
|
||||
collision.put(p.getName(), p.getCollisionRule());
|
||||
updateTeamData(p);
|
||||
}
|
||||
} else {
|
||||
boolean collision = !p.isDisguised() && revertedCollision.contains(p.getWorldName()) ? !collisionRule : collisionRule;
|
||||
if (this.collision.get(p) == null || this.getCollision(p) != collision) {
|
||||
this.collision.put(p, collision);
|
||||
boolean newCollision = !p.isDisguised() && revertedCollision.contains(p.getWorldName()) ? !collisionRule : collisionRule;
|
||||
if (collision.get(p.getName()) == null || getCollision(p) != newCollision) {
|
||||
collision.put(p.getName(), newCollision);
|
||||
updateTeamData(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean getCollision(TabPlayer p) {
|
||||
protected Boolean getCollision(TabPlayer p) {
|
||||
if (!p.isOnline()) return false;
|
||||
if (p.getCollisionRule() != null) return p.getCollisionRule();
|
||||
if (!collision.containsKey(p)) {
|
||||
collision.put(p, revertedCollision.contains(p.getWorldName()) ? !collisionRule : collisionRule);
|
||||
if (!collision.containsKey(p.getName())) {
|
||||
collision.put(p.getName(), revertedCollision.contains(p.getWorldName()) ? !collisionRule : collisionRule);
|
||||
}
|
||||
return collision.get(p);
|
||||
return collision.get(p.getName());
|
||||
}
|
||||
|
||||
|
||||
@@ -203,20 +211,20 @@ public class NameTag implements Loadable, Refreshable, LoginPacketListener, Quit
|
||||
public void onLoginPacket(TabPlayer packetReceiver) {
|
||||
for (TabPlayer all : tab.getPlayers()) {
|
||||
if (!all.isLoaded()) continue;
|
||||
if (!isDisabledWorld(all.getWorldName())) registerTeam(all, packetReceiver);
|
||||
if (!playersInDisabledWorlds.contains(all)) registerTeam(all, packetReceiver);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh(TabPlayer refreshed, boolean force) {
|
||||
if (isDisabledWorld(refreshed.getWorldName())) return;
|
||||
if (playersInDisabledWorlds.contains(refreshed)) return;
|
||||
boolean refresh;
|
||||
if (force) {
|
||||
updateProperties(refreshed);
|
||||
refresh = true;
|
||||
} else {
|
||||
boolean prefix = refreshed.getProperty("tagprefix").update();
|
||||
boolean suffix = refreshed.getProperty("tagsuffix").update();
|
||||
boolean prefix = refreshed.getProperty(PropertyUtils.TAGPREFIX).update();
|
||||
boolean suffix = refreshed.getProperty(PropertyUtils.TAGSUFFIX).update();
|
||||
refresh = prefix || suffix;
|
||||
}
|
||||
|
||||
@@ -225,23 +233,28 @@ public class NameTag implements Loadable, Refreshable, LoginPacketListener, Quit
|
||||
|
||||
@Override
|
||||
public void onJoin(TabPlayer connectedPlayer) {
|
||||
((ITabPlayer) connectedPlayer).setTeamName(sorting.getTeamName(connectedPlayer));
|
||||
((ITabPlayer) connectedPlayer).setTeamName(getSorting().getTeamName(connectedPlayer));
|
||||
updateProperties(connectedPlayer);
|
||||
collision.put(connectedPlayer, true);
|
||||
collision.put(connectedPlayer.getName(), true);
|
||||
for (TabPlayer all : tab.getPlayers()) {
|
||||
if (!all.isLoaded()) continue; //avoiding NPE when 2 players join at once
|
||||
if (all == connectedPlayer) continue; //already registered 3 lines above
|
||||
if (!isDisabledWorld(all.getWorldName())) registerTeam(all, connectedPlayer);
|
||||
if (!all.isLoaded() || all == connectedPlayer) continue; //avoiding double registration
|
||||
if (!playersInDisabledWorlds.contains(all)) {
|
||||
registerTeam(all, connectedPlayer);
|
||||
}
|
||||
}
|
||||
if (isDisabledWorld(disabledWorlds, connectedPlayer.getWorldName())) {
|
||||
playersInDisabledWorlds.add(connectedPlayer);
|
||||
return;
|
||||
}
|
||||
if (isDisabledWorld(connectedPlayer.getWorldName())) return;
|
||||
registerTeam(connectedPlayer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onQuit(TabPlayer disconnectedPlayer) {
|
||||
if (!isDisabledWorld(disconnectedPlayer.getWorldName())) unregisterTeam(disconnectedPlayer);
|
||||
if (!playersInDisabledWorlds.contains(disconnectedPlayer)) unregisterTeam(disconnectedPlayer);
|
||||
invisiblePlayers.remove(disconnectedPlayer.getName());
|
||||
collision.remove(disconnectedPlayer);
|
||||
collision.remove(disconnectedPlayer.getName());
|
||||
playersInDisabledWorlds.remove(disconnectedPlayer);
|
||||
for (TabPlayer all : tab.getPlayers()) {
|
||||
if (all == disconnectedPlayer) continue;
|
||||
all.showNametag(disconnectedPlayer.getUniqueId()); //clearing memory from API method
|
||||
@@ -250,10 +263,18 @@ public class NameTag implements Loadable, Refreshable, LoginPacketListener, Quit
|
||||
|
||||
@Override
|
||||
public void onWorldChange(TabPlayer p, String from, String to) {
|
||||
boolean disabledBefore = playersInDisabledWorlds.contains(p);
|
||||
boolean disabledNow = false;
|
||||
if (isDisabledWorld(disabledWorlds, p.getWorldName())) {
|
||||
disabledNow = true;
|
||||
playersInDisabledWorlds.add(p);
|
||||
} else {
|
||||
playersInDisabledWorlds.remove(p);
|
||||
}
|
||||
updateProperties(p);
|
||||
if (isDisabledWorld(to) && !isDisabledWorld(from)) {
|
||||
if (disabledNow && !disabledBefore) {
|
||||
unregisterTeam(p);
|
||||
} else if (!isDisabledWorld(to) && isDisabledWorld(from)) {
|
||||
} else if (!disabledNow && disabledBefore) {
|
||||
registerTeam(p);
|
||||
} else {
|
||||
updateTeam(p);
|
||||
@@ -262,16 +283,16 @@ public class NameTag implements Loadable, Refreshable, LoginPacketListener, Quit
|
||||
|
||||
@Override
|
||||
public void refreshUsedPlaceholders() {
|
||||
usedPlaceholders = new HashSet<>(tab.getConfiguration().config.getUsedPlaceholderIdentifiersRecursive("tagprefix", "tagsuffix"));
|
||||
usedPlaceholders = new HashSet<>(tab.getConfiguration().getConfig().getUsedPlaceholderIdentifiersRecursive(PropertyUtils.TAGPREFIX, PropertyUtils.TAGSUFFIX));
|
||||
for (TabPlayer p : tab.getPlayers()) {
|
||||
usedPlaceholders.addAll(tab.getPlaceholderManager().getUsedPlaceholderIdentifiersRecursive(
|
||||
p.getProperty("tagprefix").getCurrentRawValue(), p.getProperty("tagsuffix").getCurrentRawValue()));
|
||||
p.getProperty(PropertyUtils.TAGPREFIX).getCurrentRawValue(), p.getProperty(PropertyUtils.TAGSUFFIX).getCurrentRawValue()));
|
||||
}
|
||||
}
|
||||
|
||||
public void updateProperties(TabPlayer p) {
|
||||
p.loadPropertyFromConfig("tagprefix");
|
||||
p.loadPropertyFromConfig("tagsuffix");
|
||||
p.loadPropertyFromConfig(PropertyUtils.TAGPREFIX);
|
||||
p.loadPropertyFromConfig(PropertyUtils.TAGSUFFIX);
|
||||
}
|
||||
|
||||
public boolean getTeamVisibility(TabPlayer p, TabPlayer viewer) {
|
||||
@@ -283,4 +304,12 @@ public class NameTag implements Loadable, Refreshable, LoginPacketListener, Quit
|
||||
public TabFeature getFeatureType() {
|
||||
return TabFeature.NAMETAGS;
|
||||
}
|
||||
|
||||
public Sorting getSorting() {
|
||||
return sorting;
|
||||
}
|
||||
|
||||
public Set<TabPlayer> getPlayersInDisabledWorlds(){
|
||||
return playersInDisabledWorlds;
|
||||
}
|
||||
}
|
||||
@@ -24,15 +24,15 @@ public class PingSpoof implements PlayerInfoPacketListener, Loadable {
|
||||
* Constructs new instance and loads config options
|
||||
*/
|
||||
public PingSpoof() {
|
||||
value = TAB.getInstance().getConfiguration().config.getInt("ping-spoof.value", 0);
|
||||
value = TAB.getInstance().getConfiguration().getConfig().getInt("ping-spoof.value", 0);
|
||||
TAB.getInstance().debug(String.format("Loaded PingSpoof feature with parameters value=%s", value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSend(TabPlayer receiver, PacketPlayOutPlayerInfo info) {
|
||||
if (info.action != EnumPlayerInfoAction.UPDATE_LATENCY && info.action != EnumPlayerInfoAction.ADD_PLAYER) return;
|
||||
for (PlayerInfoData playerInfoData : info.entries) {
|
||||
playerInfoData.latency = value;
|
||||
if (info.getAction() != EnumPlayerInfoAction.UPDATE_LATENCY && info.getAction() != EnumPlayerInfoAction.ADD_PLAYER) return;
|
||||
for (PlayerInfoData playerInfoData : info.getEntries()) {
|
||||
playerInfoData.setLatency(value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ public class PingSpoof implements PlayerInfoPacketListener, Loadable {
|
||||
}
|
||||
|
||||
private void updateAll(boolean realPing) {
|
||||
List<PlayerInfoData> list = new ArrayList<PlayerInfoData>();
|
||||
List<PlayerInfoData> list = new ArrayList<>();
|
||||
for (TabPlayer p : TAB.getInstance().getPlayers()) {
|
||||
list.add(new PlayerInfoData(p.getUniqueId(), realPing ? (int) p.getPing() : 0));
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import me.neznamy.tab.shared.features.types.event.JoinEventListener;
|
||||
public abstract class PipelineInjector implements JoinEventListener, Loadable {
|
||||
|
||||
//name of the pipeline decoder injected in netty
|
||||
public final String DECODER_NAME = "TAB";
|
||||
public static final String DECODER_NAME = "TAB";
|
||||
|
||||
//tab instance
|
||||
protected TAB tab;
|
||||
@@ -35,10 +35,10 @@ public abstract class PipelineInjector implements JoinEventListener, Loadable {
|
||||
* Constructs new instance
|
||||
* @param tab
|
||||
*/
|
||||
public PipelineInjector(TAB tab) {
|
||||
protected PipelineInjector(TAB tab) {
|
||||
this.tab = tab;
|
||||
antiOverrideTeams = tab.getConfiguration().config.getBoolean("anti-override.scoreboard-teams", true);
|
||||
antiOverrideObjectives = tab.getConfiguration().config.getBoolean("anti-override.scoreboard-objectives", true);
|
||||
antiOverrideTeams = tab.getConfiguration().getConfig().getBoolean("anti-override.scoreboard-teams", true);
|
||||
antiOverrideObjectives = tab.getConfiguration().getConfig().getBoolean("anti-override.scoreboard-objectives", true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,7 +78,7 @@ public abstract class PipelineInjector implements JoinEventListener, Loadable {
|
||||
//not logging the same message for every online player who received the packet
|
||||
if (lastTeamOverrideMessage == null || !message.equals(lastTeamOverrideMessage)) {
|
||||
lastTeamOverrideMessage = message;
|
||||
tab.getErrorManager().printError(message, null, false, tab.getErrorManager().antiOverrideLog);
|
||||
tab.getErrorManager().printError(message, null, false, tab.getErrorManager().getAntiOverrideLog());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,16 +37,16 @@ public class PlaceholderManager implements JoinEventListener, QuitEventListener,
|
||||
private final Pattern placeholderPattern = Pattern.compile("%([^%]*)%");
|
||||
|
||||
private TAB tab;
|
||||
public int defaultRefresh;
|
||||
public Map<String, Integer> serverPlaceholderRefreshIntervals = new HashMap<String, Integer>();
|
||||
public Map<String, Integer> playerPlaceholderRefreshIntervals = new HashMap<String, Integer>();
|
||||
private Map<String, Integer> relationalPlaceholderRefreshIntervals = new HashMap<String, Integer>();
|
||||
private int defaultRefresh;
|
||||
private Map<String, Integer> serverPlaceholderRefreshIntervals = new HashMap<>();
|
||||
private Map<String, Integer> playerPlaceholderRefreshIntervals = new HashMap<>();
|
||||
private Map<String, Integer> relationalPlaceholderRefreshIntervals = new HashMap<>();
|
||||
|
||||
//all placeholders used in all configuration files + API, including invalid ones
|
||||
public Set<String> allUsedPlaceholderIdentifiers = new HashSet<String>();
|
||||
private Set<String> allUsedPlaceholderIdentifiers = new HashSet<>();
|
||||
|
||||
//plugin internals + PAPI + API
|
||||
public Map<String, Placeholder> registeredPlaceholders = new HashMap<String, Placeholder>();
|
||||
private Map<String, Placeholder> registeredPlaceholders = new HashMap<>();
|
||||
|
||||
private List<PlaceholderRegistry> registry = new ArrayList<>();
|
||||
|
||||
@@ -55,36 +55,33 @@ public class PlaceholderManager implements JoinEventListener, QuitEventListener,
|
||||
|
||||
public PlaceholderManager(TAB tab){
|
||||
this.tab = tab;
|
||||
findAllUsed(tab.getConfiguration().config.getValues());
|
||||
findAllUsed(tab.getConfiguration().animation.getValues());
|
||||
findAllUsed(tab.getConfiguration().bossbar.getValues());
|
||||
if (tab.getConfiguration().premiumconfig != null) findAllUsed(tab.getConfiguration().premiumconfig.getValues());
|
||||
findAllUsed(tab.getConfiguration().getConfig().getValues());
|
||||
findAllUsed(tab.getConfiguration().getAnimationFile().getValues());
|
||||
findAllUsed(tab.getConfiguration().getBossbarConfig().getValues());
|
||||
if (tab.getConfiguration().getPremiumConfig() != null) findAllUsed(tab.getConfiguration().getPremiumConfig().getValues());
|
||||
loadRefreshIntervals();
|
||||
AtomicInteger atomic = new AtomicInteger();
|
||||
tab.getCPUManager().startRepeatingMeasuredTask(50, "refreshing placeholders", getFeatureType(), UsageType.REPEATING_TASK, new Runnable() {
|
||||
tab.getCPUManager().startRepeatingMeasuredTask(50, "refreshing placeholders", getFeatureType(), UsageType.REPEATING_TASK, () -> {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
int loopTime = atomic.addAndGet(50);
|
||||
if (placeholderUsage == null) return; //plugin still starting up
|
||||
Map<TabPlayer, Set<Refreshable>> update = null; //not initializing if not needed
|
||||
Map<TabPlayer, Set<Refreshable>> forceUpdate = null;
|
||||
boolean somethingChanged = false;
|
||||
for (String identifier : allUsedPlaceholderIdentifiers) {
|
||||
Placeholder placeholder = getPlaceholder(identifier);
|
||||
if (placeholder == null || loopTime % placeholder.getRefresh() != 0) continue;
|
||||
if (placeholder instanceof RelationalPlaceholder) {
|
||||
if (forceUpdate == null) forceUpdate = new HashMap<TabPlayer, Set<Refreshable>>();
|
||||
if (updateRelationalPlaceholder((RelationalPlaceholder) placeholder, forceUpdate)) somethingChanged = true;
|
||||
}
|
||||
if (update == null) {
|
||||
update = new HashMap<TabPlayer, Set<Refreshable>>();
|
||||
}
|
||||
if (placeholder instanceof PlayerPlaceholder && updatePlayerPlaceholder((PlayerPlaceholder) placeholder, update)) somethingChanged = true;
|
||||
if (placeholder instanceof ServerPlaceholder && updateServerPlaceholder((ServerPlaceholder) placeholder, update)) somethingChanged = true;
|
||||
int loopTime = atomic.addAndGet(50);
|
||||
if (placeholderUsage == null) return; //plugin still starting up
|
||||
Map<TabPlayer, Set<Refreshable>> update = null; //not initializing if not needed
|
||||
Map<TabPlayer, Set<Refreshable>> forceUpdate = null;
|
||||
boolean somethingChanged = false;
|
||||
for (String identifier : getAllUsedPlaceholderIdentifiers()) {
|
||||
Placeholder placeholder = getPlaceholder(identifier);
|
||||
if (placeholder == null || loopTime % placeholder.getRefresh() != 0) continue;
|
||||
if (placeholder instanceof RelationalPlaceholder) {
|
||||
if (forceUpdate == null) forceUpdate = new HashMap<>();
|
||||
if (updateRelationalPlaceholder((RelationalPlaceholder) placeholder, forceUpdate)) somethingChanged = true;
|
||||
}
|
||||
if (somethingChanged) refresh(forceUpdate, update);
|
||||
if (update == null) {
|
||||
update = new HashMap<>();
|
||||
}
|
||||
if (placeholder instanceof PlayerPlaceholder && updatePlayerPlaceholder((PlayerPlaceholder) placeholder, update)) somethingChanged = true;
|
||||
if (placeholder instanceof ServerPlaceholder && updateServerPlaceholder((ServerPlaceholder) placeholder, update)) somethingChanged = true;
|
||||
}
|
||||
if (somethingChanged) refresh(forceUpdate, update);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -96,12 +93,12 @@ public class PlaceholderManager implements JoinEventListener, QuitEventListener,
|
||||
for (TabPlayer p2 : tab.getPlayers()) {
|
||||
if (!p2.isLoaded()) continue;
|
||||
if (placeholder.update(p1, p2)) {
|
||||
if (!forceUpdate.containsKey(p2)) forceUpdate.put(p2, new HashSet<Refreshable>());
|
||||
if (!forceUpdate.containsKey(p2)) forceUpdate.put(p2, new HashSet<>());
|
||||
forceUpdate.get(p2).addAll(placeholderUsage.get(placeholder.getIdentifier()));
|
||||
somethingChanged = true;
|
||||
}
|
||||
if (placeholder.update(p2, p1)) {
|
||||
if (!forceUpdate.containsKey(p1)) forceUpdate.put(p1, new HashSet<Refreshable>());
|
||||
if (!forceUpdate.containsKey(p1)) forceUpdate.put(p1, new HashSet<>());
|
||||
forceUpdate.get(p1).addAll(placeholderUsage.get(placeholder.getIdentifier()));
|
||||
somethingChanged = true;
|
||||
}
|
||||
@@ -117,7 +114,7 @@ public class PlaceholderManager implements JoinEventListener, QuitEventListener,
|
||||
for (TabPlayer all : tab.getPlayers()) {
|
||||
if (!all.isLoaded()) continue;
|
||||
if (placeholder.update(all)) {
|
||||
if (!update.containsKey(all)) update.put(all, new HashSet<Refreshable>());
|
||||
update.computeIfAbsent(all, k -> new HashSet<>());
|
||||
update.get(all).addAll(placeholderUsage.get(placeholder.getIdentifier()));
|
||||
somethingChanged = true;
|
||||
}
|
||||
@@ -133,7 +130,7 @@ public class PlaceholderManager implements JoinEventListener, QuitEventListener,
|
||||
somethingChanged = true;
|
||||
for (TabPlayer all : tab.getPlayers()) {
|
||||
if (!all.isLoaded()) continue;
|
||||
if (!update.containsKey(all)) update.put(all, new HashSet<Refreshable>());
|
||||
update.computeIfAbsent(all, k -> new HashSet<>());
|
||||
update.get(all).addAll(placeholderUsage.get(placeholder.getIdentifier()));
|
||||
}
|
||||
}
|
||||
@@ -142,20 +139,20 @@ public class PlaceholderManager implements JoinEventListener, QuitEventListener,
|
||||
}
|
||||
|
||||
private void loadRefreshIntervals() {
|
||||
for (Object category : tab.getConfiguration().config.getConfigurationSection("placeholderapi-refresh-intervals").keySet()) {
|
||||
for (Object category : tab.getConfiguration().getConfig().getConfigurationSection("placeholderapi-refresh-intervals").keySet()) {
|
||||
if (!Arrays.asList("default-refresh-interval", "server", "player", "relational").contains(category.toString())) {
|
||||
tab.getErrorManager().startupWarn("Unknown placeholder category \"" + category + "\". Valid categories are \"server\", \"player\" and \"relational\"");
|
||||
}
|
||||
}
|
||||
defaultRefresh = tab.getConfiguration().config.getInt("placeholderapi-refresh-intervals.default-refresh-interval", 100);
|
||||
for (Entry<Object, Object> placeholder : tab.getConfiguration().config.getConfigurationSection("placeholderapi-refresh-intervals.server").entrySet()) {
|
||||
serverPlaceholderRefreshIntervals.put(placeholder.getKey().toString(), tab.getErrorManager().parseInteger(placeholder.getValue().toString(), defaultRefresh, "refresh interval"));
|
||||
defaultRefresh = tab.getConfiguration().getConfig().getInt("placeholderapi-refresh-intervals.default-refresh-interval", 100);
|
||||
for (Entry<Object, Object> placeholder : tab.getConfiguration().getConfig().getConfigurationSection("placeholderapi-refresh-intervals.server").entrySet()) {
|
||||
getServerPlaceholderRefreshIntervals().put(placeholder.getKey().toString(), tab.getErrorManager().parseInteger(placeholder.getValue().toString(), getDefaultRefresh(), "refresh interval of server placeholder"));
|
||||
}
|
||||
for (Entry<Object, Object> placeholder : tab.getConfiguration().config.getConfigurationSection("placeholderapi-refresh-intervals.player").entrySet()) {
|
||||
playerPlaceholderRefreshIntervals.put(placeholder.getKey().toString(), tab.getErrorManager().parseInteger(placeholder.getValue().toString(), defaultRefresh, "refresh interval"));
|
||||
for (Entry<Object, Object> placeholder : tab.getConfiguration().getConfig().getConfigurationSection("placeholderapi-refresh-intervals.player").entrySet()) {
|
||||
getPlayerPlaceholderRefreshIntervals().put(placeholder.getKey().toString(), tab.getErrorManager().parseInteger(placeholder.getValue().toString(), getDefaultRefresh(), "refresh interval of player placeholder"));
|
||||
}
|
||||
for (Entry<Object, Object> placeholder : tab.getConfiguration().config.getConfigurationSection("placeholderapi-refresh-intervals.relational").entrySet()) {
|
||||
relationalPlaceholderRefreshIntervals.put(placeholder.getKey().toString(), tab.getErrorManager().parseInteger(placeholder.getValue().toString(), defaultRefresh, "refresh interval"));
|
||||
for (Entry<Object, Object> placeholder : tab.getConfiguration().getConfig().getConfigurationSection("placeholderapi-refresh-intervals.relational").entrySet()) {
|
||||
relationalPlaceholderRefreshIntervals.put(placeholder.getKey().toString(), tab.getErrorManager().parseInteger(placeholder.getValue().toString(), getDefaultRefresh(), "refresh interval of relational placeholder"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,17 +165,17 @@ public class PlaceholderManager implements JoinEventListener, QuitEventListener,
|
||||
}
|
||||
long startRefreshTime = System.nanoTime();
|
||||
if (forceUpdate != null)
|
||||
for (TabPlayer p : forceUpdate.keySet()) {
|
||||
for (Refreshable r : forceUpdate.get(p)) {
|
||||
for (Entry<TabPlayer, Set<Refreshable>> entry : forceUpdate.entrySet()) {
|
||||
for (Refreshable r : entry.getValue()) {
|
||||
long startTime = System.nanoTime();
|
||||
r.refresh(p, true);
|
||||
r.refresh(entry.getKey(), true);
|
||||
tab.getCPUManager().addTime(r.getFeatureType(), UsageType.REFRESHING, System.nanoTime()-startTime);
|
||||
}
|
||||
}
|
||||
for (TabPlayer p : update.keySet()) {
|
||||
for (Refreshable r : update.get(p)) {
|
||||
for (Entry<TabPlayer, Set<Refreshable>> entry : update.entrySet()) {
|
||||
for (Refreshable r : entry.getValue()) {
|
||||
long startTime = System.nanoTime();
|
||||
r.refresh(p, false);
|
||||
r.refresh(entry.getKey(), false);
|
||||
tab.getCPUManager().addTime(r.getFeatureType(), UsageType.REFRESHING, System.nanoTime()-startTime);
|
||||
}
|
||||
}
|
||||
@@ -187,16 +184,16 @@ public class PlaceholderManager implements JoinEventListener, QuitEventListener,
|
||||
}
|
||||
|
||||
public void refreshPlaceholderUsage() {
|
||||
Map<String, Set<Refreshable>> placeholderUsage = new HashMap<>();
|
||||
for (String placeholder : allUsedPlaceholderIdentifiers) {
|
||||
Set<Refreshable> set = new HashSet<Refreshable>();
|
||||
Map<String, Set<Refreshable>> placeholderUsage0 = new HashMap<>();
|
||||
for (String placeholder : getAllUsedPlaceholderIdentifiers()) {
|
||||
Set<Refreshable> set = new HashSet<>();
|
||||
for (Feature r : tab.getFeatureManager().getAllFeatures()) {
|
||||
if (!(r instanceof Refreshable)) continue;
|
||||
if (((Refreshable)r).getUsedPlaceholders().contains(placeholder)) set.add((Refreshable) r);
|
||||
}
|
||||
placeholderUsage.put(placeholder, set);
|
||||
placeholderUsage0.put(placeholder, set);
|
||||
}
|
||||
this.placeholderUsage = placeholderUsage;
|
||||
placeholderUsage = placeholderUsage0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -214,7 +211,7 @@ public class PlaceholderManager implements JoinEventListener, QuitEventListener,
|
||||
|
||||
@Override
|
||||
public void onJoin(TabPlayer connectedPlayer) {
|
||||
for (String identifier : allUsedPlaceholderIdentifiers) {
|
||||
for (String identifier : getAllUsedPlaceholderIdentifiers()) {
|
||||
Placeholder pl = getPlaceholder(identifier);
|
||||
if (pl instanceof RelationalPlaceholder) {
|
||||
for (TabPlayer all : tab.getPlayers()) {
|
||||
@@ -230,17 +227,17 @@ public class PlaceholderManager implements JoinEventListener, QuitEventListener,
|
||||
|
||||
@Override
|
||||
public void onQuit(TabPlayer disconnectedPlayer) {
|
||||
for (String identifier : allUsedPlaceholderIdentifiers) {
|
||||
for (String identifier : getAllUsedPlaceholderIdentifiers()) {
|
||||
Placeholder pl = getPlaceholder(identifier);
|
||||
if (pl instanceof RelationalPlaceholder) {
|
||||
for (TabPlayer all : tab.getPlayers()) {
|
||||
((RelationalPlaceholder)pl).lastValue.remove(all.getName() + "-" + disconnectedPlayer.getName());
|
||||
((RelationalPlaceholder)pl).lastValue.remove(disconnectedPlayer.getName() + "-" + all.getName());
|
||||
((RelationalPlaceholder)pl).getLastValues().remove(all.getName() + "-" + disconnectedPlayer.getName());
|
||||
((RelationalPlaceholder)pl).getLastValues().remove(disconnectedPlayer.getName() + "-" + all.getName());
|
||||
}
|
||||
}
|
||||
if (pl instanceof PlayerPlaceholder) {
|
||||
((PlayerPlaceholder)pl).lastValue.remove(disconnectedPlayer.getName());
|
||||
((PlayerPlaceholder)pl).forceUpdate.remove(disconnectedPlayer.getName());
|
||||
((PlayerPlaceholder)pl).getLastValues().remove(disconnectedPlayer.getName());
|
||||
((PlayerPlaceholder)pl).getForceUpdate().remove(disconnectedPlayer.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -251,11 +248,11 @@ public class PlaceholderManager implements JoinEventListener, QuitEventListener,
|
||||
public void registerPlaceholders() {
|
||||
for (PlaceholderRegistry r : registry) {
|
||||
for (Placeholder p : r.registerPlaceholders()) {
|
||||
registeredPlaceholders.put(p.getIdentifier(), p);
|
||||
registerPlaceholder(p);
|
||||
}
|
||||
}
|
||||
registeredPlaceholders.putAll(TABAPI.getAPIPlaceholders());
|
||||
for (String placeholder : allUsedPlaceholderIdentifiers) {
|
||||
TABAPI.getAPIPlaceholders().values().forEach(this::registerPlaceholder);
|
||||
for (String placeholder : getAllUsedPlaceholderIdentifiers()) {
|
||||
categorizeUsedPlaceholder(placeholder);
|
||||
}
|
||||
}
|
||||
@@ -264,7 +261,7 @@ public class PlaceholderManager implements JoinEventListener, QuitEventListener,
|
||||
if (relationalPlaceholderRefreshIntervals.containsKey(identifier)) {
|
||||
return relationalPlaceholderRefreshIntervals.get(identifier);
|
||||
} else {
|
||||
return defaultRefresh;
|
||||
return getDefaultRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,17 +274,17 @@ public class PlaceholderManager implements JoinEventListener, QuitEventListener,
|
||||
}
|
||||
|
||||
public List<String> getUsedPlaceholderIdentifiersRecursive(String... strings){
|
||||
List<String> base = new ArrayList<String>();
|
||||
List<String> base = new ArrayList<>();
|
||||
for (String string : strings) {
|
||||
for (String s : detectAll(string)) {
|
||||
for (String s : detectAll(color(string))) {
|
||||
if (!base.contains(s)) base.add(s);
|
||||
}
|
||||
}
|
||||
for (String placeholder : new HashSet<String>(base)) {
|
||||
for (String placeholder : new HashSet<>(base)) {
|
||||
Placeholder pl = TAB.getInstance().getPlaceholderManager().getPlaceholder(placeholder);
|
||||
if (pl == null) continue;
|
||||
for (String nestedString : pl.getNestedStrings()) {
|
||||
base.addAll(getUsedPlaceholderIdentifiersRecursive(nestedString));
|
||||
base.addAll(getUsedPlaceholderIdentifiersRecursive(color(nestedString)));
|
||||
}
|
||||
}
|
||||
return base;
|
||||
@@ -317,7 +314,7 @@ public class PlaceholderManager implements JoinEventListener, QuitEventListener,
|
||||
}
|
||||
if (object instanceof String) {
|
||||
for (String placeholder : detectAll((String) object)) {
|
||||
allUsedPlaceholderIdentifiers.add(placeholder);
|
||||
getAllUsedPlaceholderIdentifiers().add(color(placeholder));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -333,13 +330,14 @@ public class PlaceholderManager implements JoinEventListener, QuitEventListener,
|
||||
}
|
||||
|
||||
public void registerPlaceholder(Placeholder placeholder) {
|
||||
if (placeholder == null) throw new IllegalArgumentException("placeholder cannot be null");
|
||||
registeredPlaceholders.put(placeholder.getIdentifier(), placeholder);
|
||||
}
|
||||
|
||||
public void checkForRegistration(String... texts) {
|
||||
for (String text : texts) {
|
||||
for (String identifier : detectAll(text)) {
|
||||
allUsedPlaceholderIdentifiers.add(identifier);
|
||||
getAllUsedPlaceholderIdentifiers().add(identifier);
|
||||
categorizeUsedPlaceholder(identifier);
|
||||
}
|
||||
}
|
||||
@@ -384,4 +382,20 @@ public class PlaceholderManager implements JoinEventListener, QuitEventListener,
|
||||
public TabFeature getFeatureType() {
|
||||
return TabFeature.PLACEHOLDER_REFRESHING;
|
||||
}
|
||||
|
||||
public Set<String> getAllUsedPlaceholderIdentifiers() {
|
||||
return allUsedPlaceholderIdentifiers;
|
||||
}
|
||||
|
||||
public Map<String, Integer> getServerPlaceholderRefreshIntervals() {
|
||||
return serverPlaceholderRefreshIntervals;
|
||||
}
|
||||
|
||||
public Map<String, Integer> getPlayerPlaceholderRefreshIntervals() {
|
||||
return playerPlaceholderRefreshIntervals;
|
||||
}
|
||||
|
||||
public int getDefaultRefresh() {
|
||||
return defaultRefresh;
|
||||
}
|
||||
}
|
||||
@@ -8,12 +8,14 @@ import java.util.Set;
|
||||
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import me.neznamy.tab.shared.Property;
|
||||
import me.neznamy.tab.shared.PropertyUtils;
|
||||
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.Refreshable;
|
||||
import me.neznamy.tab.shared.features.types.event.JoinEventListener;
|
||||
import me.neznamy.tab.shared.features.types.event.QuitEventListener;
|
||||
import me.neznamy.tab.shared.features.types.event.WorldChangeListener;
|
||||
import me.neznamy.tab.shared.features.types.packet.PlayerInfoPacketListener;
|
||||
import me.neznamy.tab.shared.packets.IChatBaseComponent;
|
||||
@@ -24,21 +26,22 @@ import me.neznamy.tab.shared.packets.PacketPlayOutPlayerInfo.PlayerInfoData;
|
||||
/**
|
||||
* Feature handler for tablist prefix/name/suffix
|
||||
*/
|
||||
public class Playerlist implements JoinEventListener, Loadable, WorldChangeListener, Refreshable {
|
||||
public class Playerlist implements JoinEventListener, QuitEventListener, Loadable, WorldChangeListener, Refreshable {
|
||||
|
||||
private TAB tab;
|
||||
private Set<String> usedPlaceholders;
|
||||
public List<String> disabledWorlds;
|
||||
private List<String> disabledWorlds;
|
||||
private boolean antiOverrideNames;
|
||||
private boolean antiOverrideTablist;
|
||||
private boolean disabling = false;
|
||||
private Set<TabPlayer> playersInDisabledWorlds = new HashSet<>();
|
||||
|
||||
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) && tab.getFeatureManager().isFeatureEnabled("injection");
|
||||
disabledWorlds = tab.getConfiguration().getConfig().getStringList("disable-features-in-"+tab.getPlatform().getSeparatorType()+"s.tablist-names", Arrays.asList("disabled" + tab.getPlatform().getSeparatorType()));
|
||||
antiOverrideNames = tab.getConfiguration().getConfig().getBoolean("anti-override.usernames", true) && tab.getFeatureManager().isFeatureEnabled("injection");
|
||||
refreshUsedPlaceholders();
|
||||
antiOverrideTablist = tab.getConfiguration().config.getBoolean("anti-override.tablist-names", true) && tab.getFeatureManager().isFeatureEnabled("injection");
|
||||
antiOverrideTablist = tab.getConfiguration().getConfig().getBoolean("anti-override.tablist-names", true) && tab.getFeatureManager().isFeatureEnabled("injection");
|
||||
if (antiOverrideTablist) {
|
||||
tab.getFeatureManager().registerFeature("playerlist_info", new PlayerInfoPacketListener() {
|
||||
|
||||
@@ -50,17 +53,15 @@ public class Playerlist implements JoinEventListener, Loadable, WorldChangeListe
|
||||
@Override
|
||||
public void onPacketSend(TabPlayer receiver, PacketPlayOutPlayerInfo info) {
|
||||
if (disabling) return;
|
||||
boolean UPDATE_NAME = info.action == EnumPlayerInfoAction.UPDATE_DISPLAY_NAME;
|
||||
boolean ADD = info.action == EnumPlayerInfoAction.ADD_PLAYER;
|
||||
if (!UPDATE_NAME && !ADD) return;
|
||||
for (PlayerInfoData playerInfoData : info.entries) {
|
||||
TabPlayer packetPlayer = tab.getPlayerByTablistUUID(playerInfoData.uniqueId);
|
||||
if (packetPlayer != null && !isDisabledWorld(disabledWorlds, packetPlayer.getWorldName())) {
|
||||
playerInfoData.displayName = getTabFormat(packetPlayer, receiver);
|
||||
if (info.getAction() != EnumPlayerInfoAction.UPDATE_DISPLAY_NAME && info.getAction() != EnumPlayerInfoAction.ADD_PLAYER) return;
|
||||
for (PlayerInfoData playerInfoData : info.getEntries()) {
|
||||
TabPlayer packetPlayer = tab.getPlayerByTablistUUID(playerInfoData.getUniqueId());
|
||||
if (packetPlayer != null && !playersInDisabledWorlds.contains(packetPlayer)) {
|
||||
playerInfoData.setDisplayName(getTabFormat(packetPlayer, receiver));
|
||||
//preventing plugins from changing player name as nametag feature would not work correctly
|
||||
if (ADD && tab.getFeatureManager().getNameTagFeature() != null && !playerInfoData.name.equals(packetPlayer.getName()) && antiOverrideNames) {
|
||||
tab.getErrorManager().printError("A plugin tried to change name of " + packetPlayer.getName() + " to \"" + playerInfoData.name + "\" for viewer " + receiver.getName(), null, false, tab.getErrorManager().antiOverrideLog);
|
||||
playerInfoData.name = packetPlayer.getName();
|
||||
if (info.getAction() == EnumPlayerInfoAction.ADD_PLAYER && tab.getFeatureManager().getNameTagFeature() != null && !playerInfoData.getName().equals(packetPlayer.getName()) && antiOverrideNames) {
|
||||
tab.getErrorManager().printError("A plugin tried to change name of " + packetPlayer.getName() + " to \"" + playerInfoData.getName() + "\" for viewer " + receiver.getName(), null, false, tab.getErrorManager().getAntiOverrideLog());
|
||||
playerInfoData.setName(packetPlayer.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -68,13 +69,17 @@ public class Playerlist implements JoinEventListener, Loadable, WorldChangeListe
|
||||
|
||||
});
|
||||
}
|
||||
tab.debug(String.format("Loaded Playerlist feature with parameters disabledWorlds=%s, antiOverrideTablist=%s", disabledWorlds, antiOverrideTablist));
|
||||
tab.debug(String.format("Loaded Playerlist feature with parameters disabledWorlds=%s, antiOverrideTablist=%s", getDisabledWorlds(), antiOverrideTablist));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(){
|
||||
for (TabPlayer all : tab.getPlayers()) {
|
||||
if (isDisabledWorld(disabledWorlds, all.getWorldName())) updateProperties(all);
|
||||
if (isDisabledWorld(disabledWorlds, all.getWorldName())) {
|
||||
playersInDisabledWorlds.add(all);
|
||||
updateProperties(all);
|
||||
return;
|
||||
}
|
||||
refresh(all, true);
|
||||
}
|
||||
}
|
||||
@@ -82,9 +87,9 @@ public class Playerlist implements JoinEventListener, Loadable, WorldChangeListe
|
||||
@Override
|
||||
public void unload(){
|
||||
disabling = true;
|
||||
List<PlayerInfoData> updatedPlayers = new ArrayList<PlayerInfoData>();
|
||||
List<PlayerInfoData> updatedPlayers = new ArrayList<>();
|
||||
for (TabPlayer p : tab.getPlayers()) {
|
||||
if (!isDisabledWorld(disabledWorlds, p.getWorldName())) updatedPlayers.add(new PlayerInfoData(p.getTablistUUID()));
|
||||
if (!playersInDisabledWorlds.contains(p)) 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());
|
||||
@@ -93,8 +98,16 @@ public class Playerlist implements JoinEventListener, Loadable, WorldChangeListe
|
||||
|
||||
@Override
|
||||
public void onWorldChange(TabPlayer p, String from, String to) {
|
||||
if (isDisabledWorld(disabledWorlds, to)) {
|
||||
if (!isDisabledWorld(disabledWorlds, from)) {
|
||||
boolean disabledBefore = playersInDisabledWorlds.contains(p);
|
||||
boolean disabledNow = false;
|
||||
if (isDisabledWorld(disabledWorlds, p.getWorldName())) {
|
||||
disabledNow = true;
|
||||
playersInDisabledWorlds.add(p);
|
||||
} else {
|
||||
playersInDisabledWorlds.remove(p);
|
||||
}
|
||||
if (disabledNow) {
|
||||
if (!disabledBefore) {
|
||||
for (TabPlayer viewer : tab.getPlayers()) {
|
||||
if (viewer.getVersion().getMinorVersion() < 8) continue;
|
||||
viewer.sendCustomPacket(new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.UPDATE_DISPLAY_NAME, new PlayerInfoData(p.getTablistUUID())));
|
||||
@@ -106,11 +119,10 @@ public class Playerlist implements JoinEventListener, Loadable, WorldChangeListe
|
||||
}
|
||||
|
||||
public IChatBaseComponent getTabFormat(TabPlayer p, TabPlayer viewer) {
|
||||
Property prefix = p.getProperty("tabprefix");
|
||||
Property name = p.getProperty("customtabname");
|
||||
Property suffix = p.getProperty("tabsuffix");
|
||||
Property prefix = p.getProperty(PropertyUtils.TABPREFIX);
|
||||
Property name = p.getProperty(PropertyUtils.CUSTOMTABNAME);
|
||||
Property suffix = p.getProperty(PropertyUtils.TABSUFFIX);
|
||||
if (prefix == null || name == null || suffix == null) {
|
||||
// tab.errorManager.printError("TabFormat not initialized for " + p.getName());
|
||||
return null;
|
||||
}
|
||||
String format;
|
||||
@@ -124,21 +136,21 @@ public class Playerlist implements JoinEventListener, Loadable, WorldChangeListe
|
||||
}
|
||||
@Override
|
||||
public void refresh(TabPlayer refreshed, boolean force) {
|
||||
if (isDisabledWorld(disabledWorlds, refreshed.getWorldName())) return;
|
||||
if (playersInDisabledWorlds.contains(refreshed)) return;
|
||||
boolean refresh;
|
||||
if (force) {
|
||||
updateProperties(refreshed);
|
||||
refresh = true;
|
||||
} else {
|
||||
boolean prefix = refreshed.getProperty("tabprefix").update();
|
||||
boolean name = refreshed.getProperty("customtabname").update();
|
||||
boolean suffix = refreshed.getProperty("tabsuffix").update();
|
||||
boolean prefix = refreshed.getProperty(PropertyUtils.TABPREFIX).update();
|
||||
boolean name = refreshed.getProperty(PropertyUtils.CUSTOMTABNAME).update();
|
||||
boolean suffix = refreshed.getProperty(PropertyUtils.TABSUFFIX).update();
|
||||
refresh = prefix || name || suffix;
|
||||
}
|
||||
if (refresh) {
|
||||
Property prefix = refreshed.getProperty("tabprefix");
|
||||
Property name = refreshed.getProperty("customtabname");
|
||||
Property suffix = refreshed.getProperty("tabsuffix");
|
||||
Property prefix = refreshed.getProperty(PropertyUtils.TABPREFIX);
|
||||
Property name = refreshed.getProperty(PropertyUtils.CUSTOMTABNAME);
|
||||
Property suffix = refreshed.getProperty(PropertyUtils.TABSUFFIX);
|
||||
for (TabPlayer viewer : tab.getPlayers()) {
|
||||
if (viewer.getVersion().getMinorVersion() < 8) continue;
|
||||
String format;
|
||||
@@ -153,9 +165,9 @@ public class Playerlist implements JoinEventListener, Loadable, WorldChangeListe
|
||||
}
|
||||
}
|
||||
private void updateProperties(TabPlayer p) {
|
||||
p.loadPropertyFromConfig("tabprefix");
|
||||
p.loadPropertyFromConfig("customtabname", p.getName());
|
||||
p.loadPropertyFromConfig("tabsuffix");
|
||||
p.loadPropertyFromConfig(PropertyUtils.TABPREFIX);
|
||||
p.loadPropertyFromConfig(PropertyUtils.CUSTOMTABNAME, p.getName());
|
||||
p.loadPropertyFromConfig(PropertyUtils.TABSUFFIX);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -165,11 +177,15 @@ public class Playerlist implements JoinEventListener, Loadable, WorldChangeListe
|
||||
|
||||
@Override
|
||||
public void onJoin(TabPlayer connectedPlayer) {
|
||||
if (isDisabledWorld(disabledWorlds, connectedPlayer.getWorldName())) updateProperties(connectedPlayer);
|
||||
if (isDisabledWorld(disabledWorlds, connectedPlayer.getWorldName())) {
|
||||
playersInDisabledWorlds.add(connectedPlayer);
|
||||
updateProperties(connectedPlayer);
|
||||
return;
|
||||
}
|
||||
Runnable r = () -> {
|
||||
refresh(connectedPlayer, true);
|
||||
if (connectedPlayer.getVersion().getMinorVersion() < 8) return;
|
||||
List<PlayerInfoData> list = new ArrayList<PlayerInfoData>();
|
||||
List<PlayerInfoData> list = new ArrayList<>();
|
||||
for (TabPlayer all : tab.getPlayers()) {
|
||||
if (all == connectedPlayer) continue; //already sent 4 lines above
|
||||
list.add(new PlayerInfoData(all.getTablistUUID(), getTabFormat(all, connectedPlayer)));
|
||||
@@ -183,10 +199,10 @@ public class Playerlist implements JoinEventListener, Loadable, WorldChangeListe
|
||||
|
||||
@Override
|
||||
public void refreshUsedPlaceholders() {
|
||||
usedPlaceholders = new HashSet<>(tab.getConfiguration().config.getUsedPlaceholderIdentifiersRecursive("tabprefix", "customtabname", "tabsuffix"));
|
||||
usedPlaceholders = new HashSet<>(tab.getConfiguration().getConfig().getUsedPlaceholderIdentifiersRecursive(PropertyUtils.TABPREFIX, PropertyUtils.CUSTOMTABNAME, PropertyUtils.TABSUFFIX));
|
||||
for (TabPlayer p : tab.getPlayers()) {
|
||||
usedPlaceholders.addAll(tab.getPlaceholderManager().getUsedPlaceholderIdentifiersRecursive(p.getProperty("tabprefix").getCurrentRawValue(),
|
||||
p.getProperty("customtabname").getCurrentRawValue(), p.getProperty("tabsuffix").getCurrentRawValue()));
|
||||
usedPlaceholders.addAll(tab.getPlaceholderManager().getUsedPlaceholderIdentifiersRecursive(p.getProperty(PropertyUtils.TABPREFIX).getCurrentRawValue(),
|
||||
p.getProperty(PropertyUtils.CUSTOMTABNAME).getCurrentRawValue(), p.getProperty(PropertyUtils.TABSUFFIX).getCurrentRawValue()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,4 +210,13 @@ public class Playerlist implements JoinEventListener, Loadable, WorldChangeListe
|
||||
public TabFeature getFeatureType() {
|
||||
return TabFeature.TABLIST_NAMES;
|
||||
}
|
||||
|
||||
public List<String> getDisabledWorlds() {
|
||||
return disabledWorlds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onQuit(TabPlayer disconnectedPlayer) {
|
||||
playersInDisabledWorlds.remove(disconnectedPlayer);
|
||||
}
|
||||
}
|
||||
@@ -55,8 +55,8 @@ public interface PluginMessageHandler {
|
||||
long cpu = in.readLong();
|
||||
PlayerPlaceholder pl = (PlayerPlaceholder) TAB.getInstance().getPlaceholderManager().getPlaceholder(placeholder); //all bridge placeholders are marked as player
|
||||
if (pl != null) {
|
||||
pl.lastValue.put(player.getName(), output);
|
||||
pl.forceUpdate.add(player.getName());
|
||||
pl.getLastValues().put(player.getName(), output);
|
||||
pl.getForceUpdate().add(player.getName());
|
||||
TAB.getInstance().getCPUManager().addBridgePlaceholderTime(pl.getIdentifier(), cpu);
|
||||
} else {
|
||||
TAB.getInstance().debug("Received output for unknown placeholder " + placeholder);
|
||||
|
||||
@@ -27,18 +27,18 @@ public class SpectatorFix implements PlayerInfoPacketListener, Loadable {
|
||||
* Constructs new instance and loads config options
|
||||
*/
|
||||
public SpectatorFix() {
|
||||
allowBypass = TAB.getInstance().getConfiguration().config.getBoolean("allow-spectator-bypass-permission", false);
|
||||
allowBypass = TAB.getInstance().getConfiguration().getConfig().getBoolean("allow-spectator-bypass-permission", false);
|
||||
TAB.getInstance().debug(String.format("Loaded SpectatorFix feature with parameters allowBypass=%s", allowBypass));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSend(TabPlayer receiver, PacketPlayOutPlayerInfo info) {
|
||||
if (allowBypass && receiver.hasPermission("tab.spectatorbypass")) return;
|
||||
if (info.action != EnumPlayerInfoAction.UPDATE_GAME_MODE && info.action != EnumPlayerInfoAction.ADD_PLAYER) return;
|
||||
for (PlayerInfoData playerInfoData : info.entries) {
|
||||
if (playerInfoData.gameMode == EnumGamemode.SPECTATOR) {
|
||||
TabPlayer changed = TAB.getInstance().getPlayerByTablistUUID(playerInfoData.uniqueId);
|
||||
if (changed != receiver) playerInfoData.gameMode = EnumGamemode.CREATIVE;
|
||||
if (info.getAction() != EnumPlayerInfoAction.UPDATE_GAME_MODE && info.getAction() != EnumPlayerInfoAction.ADD_PLAYER) return;
|
||||
for (PlayerInfoData playerInfoData : info.getEntries()) {
|
||||
if (playerInfoData.getGameMode() == EnumGamemode.SPECTATOR) {
|
||||
TabPlayer changed = TAB.getInstance().getPlayerByTablistUUID(playerInfoData.getUniqueId());
|
||||
if (changed != receiver) playerInfoData.setGameMode(EnumGamemode.CREATIVE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -61,7 +61,7 @@ public class SpectatorFix implements PlayerInfoPacketListener, Loadable {
|
||||
private void updateAll(boolean realGamemode) {
|
||||
for (TabPlayer p : TAB.getInstance().getPlayers()) {
|
||||
if (allowBypass && p.hasPermission("tab.spectatorbypass")) continue;
|
||||
List<PlayerInfoData> list = new ArrayList<PlayerInfoData>();
|
||||
List<PlayerInfoData> list = new ArrayList<>();
|
||||
for (TabPlayer target : TAB.getInstance().getPlayers()) {
|
||||
if (p == target) continue;
|
||||
list.add(new PlayerInfoData(p.getUniqueId(), realGamemode ? EnumGamemode.values()[p.getGamemode()+1] : EnumGamemode.CREATIVE));
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package me.neznamy.tab.shared.features;
|
||||
|
||||
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.PacketAPI;
|
||||
@@ -10,6 +12,7 @@ import me.neznamy.tab.shared.cpu.TabFeature;
|
||||
import me.neznamy.tab.shared.features.types.Loadable;
|
||||
import me.neznamy.tab.shared.features.types.Refreshable;
|
||||
import me.neznamy.tab.shared.features.types.event.JoinEventListener;
|
||||
import me.neznamy.tab.shared.features.types.event.QuitEventListener;
|
||||
import me.neznamy.tab.shared.features.types.event.WorldChangeListener;
|
||||
import me.neznamy.tab.shared.features.types.packet.DisplayObjectivePacketListener;
|
||||
import me.neznamy.tab.shared.features.types.packet.LoginPacketListener;
|
||||
@@ -22,24 +25,24 @@ import me.neznamy.tab.shared.packets.PacketPlayOutScoreboardScore.Action;
|
||||
/**
|
||||
* Feature handler for tablist objective feature
|
||||
*/
|
||||
public class TabObjective implements Loadable, JoinEventListener, WorldChangeListener, Refreshable, LoginPacketListener, DisplayObjectivePacketListener {
|
||||
public class TabObjective implements Loadable, JoinEventListener, QuitEventListener, WorldChangeListener, Refreshable, LoginPacketListener, DisplayObjectivePacketListener {
|
||||
|
||||
public static final String ObjectiveName = "TAB-YellowNumber";
|
||||
public static final int DisplaySlot = 0;
|
||||
|
||||
private final String propertyName = "tablist-objective";
|
||||
private final String title = "ms";
|
||||
public static final String OBJECTIVE_NAME = "TAB-YellowNumber";
|
||||
public static final int DISPLAY_SLOT = 0;
|
||||
private static final String PROPERTY_NAME = "tablist-objective";
|
||||
private static final String TITLE = "ms";
|
||||
|
||||
private TAB tab;
|
||||
private String rawValue;
|
||||
private EnumScoreboardHealthDisplay displayType;
|
||||
private List<String> usedPlaceholders;
|
||||
private List<String> disabledWorlds;
|
||||
private Set<TabPlayer> playersInDisabledWorlds = new HashSet<>();
|
||||
|
||||
public TabObjective(TAB tab) {
|
||||
this.tab = tab;
|
||||
rawValue = tab.getConfiguration().config.getString("yellow-number-in-tablist", "%ping%");
|
||||
disabledWorlds = tab.getConfiguration().config.getStringList("disable-features-in-"+tab.getPlatform().getSeparatorType()+"s.yellow-number", Arrays.asList("disabled" + tab.getPlatform().getSeparatorType()));
|
||||
rawValue = tab.getConfiguration().getConfig().getString("yellow-number-in-tablist", "%ping%");
|
||||
disabledWorlds = tab.getConfiguration().getConfig().getStringList("disable-features-in-"+tab.getPlatform().getSeparatorType()+"s.yellow-number", Arrays.asList("disabled" + tab.getPlatform().getSeparatorType()));
|
||||
refreshUsedPlaceholders();
|
||||
if (rawValue.equals("%health%") || rawValue.equals("%player_health%") || rawValue.equals("%player_health_rounded%")) {
|
||||
displayType = EnumScoreboardHealthDisplay.HEARTS;
|
||||
@@ -52,13 +55,16 @@ public class TabObjective implements Loadable, JoinEventListener, WorldChangeLis
|
||||
@Override
|
||||
public void load() {
|
||||
for (TabPlayer loaded : tab.getPlayers()){
|
||||
loaded.setProperty(propertyName, rawValue);
|
||||
if (isDisabledWorld(disabledWorlds, loaded.getWorldName())) continue;
|
||||
PacketAPI.registerScoreboardObjective(loaded, ObjectiveName, title, DisplaySlot, displayType, getFeatureType());
|
||||
loaded.setProperty(PROPERTY_NAME, rawValue);
|
||||
if (isDisabledWorld(disabledWorlds, loaded.getWorldName())) {
|
||||
playersInDisabledWorlds.add(loaded);
|
||||
continue;
|
||||
}
|
||||
PacketAPI.registerScoreboardObjective(loaded, OBJECTIVE_NAME, TITLE, DISPLAY_SLOT, displayType, getFeatureType());
|
||||
}
|
||||
for (TabPlayer viewer : tab.getPlayers()){
|
||||
for (TabPlayer target : tab.getPlayers()){
|
||||
viewer.sendCustomPacket(new PacketPlayOutScoreboardScore(Action.CHANGE, ObjectiveName, target.getName(), getValue(target)), getFeatureType());
|
||||
viewer.sendCustomPacket(new PacketPlayOutScoreboardScore(Action.CHANGE, OBJECTIVE_NAME, target.getName(), getValue(target)), getFeatureType());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -66,45 +72,54 @@ public class TabObjective implements Loadable, JoinEventListener, WorldChangeLis
|
||||
@Override
|
||||
public void unload() {
|
||||
for (TabPlayer p : tab.getPlayers()){
|
||||
if (isDisabledWorld(disabledWorlds, p.getWorldName())) continue;
|
||||
p.sendCustomPacket(new PacketPlayOutScoreboardObjective(ObjectiveName), getFeatureType());
|
||||
if (playersInDisabledWorlds.contains(p)) continue;
|
||||
p.sendCustomPacket(new PacketPlayOutScoreboardObjective(OBJECTIVE_NAME), getFeatureType());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onJoin(TabPlayer connectedPlayer) {
|
||||
connectedPlayer.setProperty(propertyName, rawValue);
|
||||
if (isDisabledWorld(disabledWorlds, connectedPlayer.getWorldName())) return;
|
||||
PacketAPI.registerScoreboardObjective(connectedPlayer, ObjectiveName, title, DisplaySlot, displayType, getFeatureType());
|
||||
connectedPlayer.setProperty(PROPERTY_NAME, rawValue);
|
||||
if (isDisabledWorld(disabledWorlds, connectedPlayer.getWorldName())) {
|
||||
playersInDisabledWorlds.add(connectedPlayer);
|
||||
return;
|
||||
}
|
||||
PacketAPI.registerScoreboardObjective(connectedPlayer, OBJECTIVE_NAME, TITLE, DISPLAY_SLOT, displayType, getFeatureType());
|
||||
int value = getValue(connectedPlayer);
|
||||
for (TabPlayer all : tab.getPlayers()){
|
||||
all.sendCustomPacket(new PacketPlayOutScoreboardScore(Action.CHANGE, ObjectiveName, connectedPlayer.getName(), value), getFeatureType());
|
||||
if (all.isLoaded()) connectedPlayer.sendCustomPacket(new PacketPlayOutScoreboardScore(Action.CHANGE, ObjectiveName, all.getName(), getValue(all)), getFeatureType());
|
||||
all.sendCustomPacket(new PacketPlayOutScoreboardScore(Action.CHANGE, OBJECTIVE_NAME, connectedPlayer.getName(), value), getFeatureType());
|
||||
if (all.isLoaded()) connectedPlayer.sendCustomPacket(new PacketPlayOutScoreboardScore(Action.CHANGE, OBJECTIVE_NAME, all.getName(), getValue(all)), getFeatureType());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWorldChange(TabPlayer p, String from, String to) {
|
||||
if (isDisabledWorld(disabledWorlds, p.getWorldName()) && !isDisabledWorld(disabledWorlds, from)) {
|
||||
p.sendCustomPacket(new PacketPlayOutScoreboardObjective(ObjectiveName), getFeatureType());
|
||||
return;
|
||||
boolean disabledBefore = playersInDisabledWorlds.contains(p);
|
||||
boolean disabledNow = false;
|
||||
if (isDisabledWorld(disabledWorlds, p.getWorldName())) {
|
||||
disabledNow = true;
|
||||
playersInDisabledWorlds.add(p);
|
||||
} else {
|
||||
playersInDisabledWorlds.remove(p);
|
||||
}
|
||||
if (!isDisabledWorld(disabledWorlds, p.getWorldName()) && isDisabledWorld(disabledWorlds, from)) {
|
||||
if (disabledNow && !disabledBefore) {
|
||||
p.sendCustomPacket(new PacketPlayOutScoreboardObjective(OBJECTIVE_NAME), getFeatureType());
|
||||
}
|
||||
if (!disabledNow && disabledBefore) {
|
||||
onJoin(p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private int getValue(TabPlayer p) {
|
||||
return tab.getErrorManager().parseInteger(p.getProperty(propertyName).updateAndGet(), 0, "yellow number");
|
||||
return tab.getErrorManager().parseInteger(p.getProperty(PROPERTY_NAME).updateAndGet(), 0, "yellow number");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh(TabPlayer refreshed, boolean force) {
|
||||
if (isDisabledWorld(disabledWorlds, refreshed.getWorldName())) return;
|
||||
if (playersInDisabledWorlds.contains(refreshed)) return;
|
||||
int value = getValue(refreshed);
|
||||
for (TabPlayer all : tab.getPlayers()) {
|
||||
all.sendCustomPacket(new PacketPlayOutScoreboardScore(Action.CHANGE, ObjectiveName, refreshed.getName(), value), getFeatureType());
|
||||
all.sendCustomPacket(new PacketPlayOutScoreboardScore(Action.CHANGE, OBJECTIVE_NAME, refreshed.getName(), value), getFeatureType());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,20 +140,25 @@ public class TabObjective implements Loadable, JoinEventListener, WorldChangeLis
|
||||
|
||||
@Override
|
||||
public void onLoginPacket(TabPlayer packetReceiver) {
|
||||
if (isDisabledWorld(disabledWorlds, packetReceiver.getWorldName())) return;
|
||||
PacketAPI.registerScoreboardObjective(packetReceiver, ObjectiveName, title, DisplaySlot, displayType, getFeatureType());
|
||||
if (playersInDisabledWorlds.contains(packetReceiver)) return;
|
||||
PacketAPI.registerScoreboardObjective(packetReceiver, OBJECTIVE_NAME, TITLE, DISPLAY_SLOT, displayType, getFeatureType());
|
||||
for (TabPlayer all : tab.getPlayers()){
|
||||
if (all.isLoaded()) packetReceiver.sendCustomPacket(new PacketPlayOutScoreboardScore(Action.CHANGE, ObjectiveName, all.getName(), getValue(all)), getFeatureType());
|
||||
if (all.isLoaded()) packetReceiver.sendCustomPacket(new PacketPlayOutScoreboardScore(Action.CHANGE, OBJECTIVE_NAME, all.getName(), getValue(all)), getFeatureType());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPacketSend(TabPlayer receiver, PacketPlayOutScoreboardDisplayObjective packet) {
|
||||
if (isDisabledWorld(disabledWorlds, receiver.getWorldName())) return false;
|
||||
if (packet.slot == DisplaySlot && !packet.objectiveName.equals(ObjectiveName)) {
|
||||
tab.getErrorManager().printError("Something just tried to register objective \"" + packet.objectiveName + "\" in position " + packet.slot + " (playerlist)", null, false, tab.getErrorManager().antiOverrideLog);
|
||||
if (playersInDisabledWorlds.contains(receiver)) return false;
|
||||
if (packet.getSlot() == DISPLAY_SLOT && !packet.getObjectiveName().equals(OBJECTIVE_NAME)) {
|
||||
tab.getErrorManager().printError("Something just tried to register objective \"" + packet.getObjectiveName() + "\" in position " + packet.getSlot() + " (playerlist)", null, false, tab.getErrorManager().getAntiOverrideLog());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onQuit(TabPlayer disconnectedPlayer) {
|
||||
playersInDisabledWorlds.remove(disconnectedPlayer);
|
||||
}
|
||||
}
|
||||
@@ -13,26 +13,22 @@ import me.neznamy.tab.shared.TAB;
|
||||
public class UpdateChecker {
|
||||
|
||||
//separate field to prevent false flag on pre releases
|
||||
private final String currentRelease = "2.9.0";
|
||||
private String currentRelease = "2.9.2";
|
||||
|
||||
public UpdateChecker(TAB tab) {
|
||||
new Thread(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
HttpURLConnection con = (HttpURLConnection) new URL("https://api.spigotmc.org/legacy/update.php?resource=57806").openConnection();
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
|
||||
String versionString = br.readLine();
|
||||
br.close();
|
||||
con.disconnect();
|
||||
if (!versionString.equals(currentRelease)) {
|
||||
tab.getPlatform().sendConsoleMessage("&a[TAB] Version " + versionString + " is out! Your version: " + tab.getPluginVersion(), true);
|
||||
tab.getPlatform().sendConsoleMessage("&a[TAB] Get the update at https://www.spigotmc.org/resources/57806/", true);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
tab.debug("&cFailed to check for updates (" + e.getClass().getSimpleName() + ": " + e.getMessage() + ")");
|
||||
new Thread(() -> {
|
||||
try {
|
||||
HttpURLConnection con = (HttpURLConnection) new URL("https://api.spigotmc.org/legacy/update.php?resource=57806").openConnection();
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
|
||||
String versionString = br.readLine();
|
||||
br.close();
|
||||
con.disconnect();
|
||||
if (!versionString.equals(currentRelease)) {
|
||||
tab.getPlatform().sendConsoleMessage("&a[TAB] Version " + versionString + " is out! Your version: " + tab.getPluginVersion(), true);
|
||||
tab.getPlatform().sendConsoleMessage("&a[TAB] Get the update at https://www.spigotmc.org/resources/57806/", true);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
tab.debug("&cFailed to check for updates (" + e.getClass().getSimpleName() + ": " + e.getMessage() + ")");
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
@@ -3,8 +3,10 @@ package me.neznamy.tab.shared.features.bossbar;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -15,49 +17,52 @@ import me.neznamy.tab.shared.cpu.UsageType;
|
||||
import me.neznamy.tab.shared.features.types.Loadable;
|
||||
import me.neznamy.tab.shared.features.types.event.CommandListener;
|
||||
import me.neznamy.tab.shared.features.types.event.JoinEventListener;
|
||||
import me.neznamy.tab.shared.features.types.event.QuitEventListener;
|
||||
import me.neznamy.tab.shared.features.types.event.WorldChangeListener;
|
||||
import me.neznamy.tab.shared.placeholders.ServerPlaceholder;
|
||||
|
||||
/**
|
||||
* Class for handling bossbar feature
|
||||
*/
|
||||
public class BossBar implements Loadable, JoinEventListener, WorldChangeListener, CommandListener {
|
||||
public class BossBar implements Loadable, JoinEventListener, QuitEventListener, WorldChangeListener, CommandListener {
|
||||
|
||||
//tab instance
|
||||
private TAB tab;
|
||||
|
||||
//default bossbars
|
||||
public List<String> defaultBars;
|
||||
private List<String> defaultBars;
|
||||
|
||||
//per-world / per-server bossbars
|
||||
public Map<String, List<String>> perWorld;
|
||||
private Map<String, List<String>> perWorld;
|
||||
|
||||
//registered bossbars
|
||||
public Map<String, BossBarLine> lines = new HashMap<String, BossBarLine>();
|
||||
private Map<String, BossBarLine> lines = new HashMap<>();
|
||||
|
||||
//toggle command
|
||||
private String toggleCommand;
|
||||
|
||||
//list of currently running bossbar announcements
|
||||
public List<String> announcements = new ArrayList<String>();
|
||||
private List<String> announcements = new ArrayList<>();
|
||||
|
||||
//saving toggle choice into file
|
||||
public boolean remember_toggle_choice;
|
||||
private boolean rememberToggleChoice;
|
||||
|
||||
//players with toggled bossbar
|
||||
public List<String> bossbar_off_players = new ArrayList<String>();
|
||||
private List<String> bossbarOffPlayers = new ArrayList<>();
|
||||
|
||||
//if permission is required to toggle
|
||||
public boolean permToToggle;
|
||||
private boolean permToToggle;
|
||||
|
||||
//list of worlds / servers where bossbar feature is disabled entirely
|
||||
private List<String> disabledWorlds;
|
||||
|
||||
//time when bossbar announce ends, used for placeholder
|
||||
public long announceEndTime;
|
||||
private long announceEndTime;
|
||||
|
||||
//if bossbar is hidden by default until toggle command is used
|
||||
private boolean hiddenByDefault;
|
||||
|
||||
private Set<TabPlayer> playersInDisabledWorlds = new HashSet<>();
|
||||
|
||||
/**
|
||||
* Constructs new instance and loads configuration
|
||||
@@ -65,44 +70,44 @@ public class BossBar implements Loadable, JoinEventListener, WorldChangeListener
|
||||
*/
|
||||
public BossBar(TAB tab) {
|
||||
this.tab = tab;
|
||||
disabledWorlds = tab.getConfiguration().config.getStringList("disable-features-in-"+tab.getPlatform().getSeparatorType()+"s.bossbar", Arrays.asList("disabled" + tab.getPlatform().getSeparatorType()));
|
||||
toggleCommand = tab.getConfiguration().bossbar.getString("bossbar-toggle-command", "/bossbar");
|
||||
defaultBars = tab.getConfiguration().bossbar.getStringList("default-bars", new ArrayList<String>());
|
||||
permToToggle = tab.getConfiguration().bossbar.getBoolean("permission-required-to-toggle", false);
|
||||
hiddenByDefault = tab.getConfiguration().bossbar.getBoolean("hidden-by-default", false);
|
||||
perWorld = tab.getConfiguration().bossbar.getConfigurationSection("per-world");
|
||||
for (Object bar : tab.getConfiguration().bossbar.getConfigurationSection("bars").keySet()){
|
||||
lines.put(bar.toString(), BossBarLine.fromConfig(bar.toString()));
|
||||
disabledWorlds = tab.getConfiguration().getConfig().getStringList("disable-features-in-"+tab.getPlatform().getSeparatorType()+"s.bossbar", Arrays.asList("disabled" + tab.getPlatform().getSeparatorType()));
|
||||
toggleCommand = tab.getConfiguration().getBossbarConfig().getString("bossbar-toggle-command", "/bossbar");
|
||||
defaultBars = tab.getConfiguration().getBossbarConfig().getStringList("default-bars", new ArrayList<>());
|
||||
permToToggle = tab.getConfiguration().getBossbarConfig().getBoolean("permission-required-to-toggle", false);
|
||||
hiddenByDefault = tab.getConfiguration().getBossbarConfig().getBoolean("hidden-by-default", false);
|
||||
perWorld = tab.getConfiguration().getBossbarConfig().getConfigurationSection("per-world");
|
||||
for (Object bar : tab.getConfiguration().getBossbarConfig().getConfigurationSection("bars").keySet()){
|
||||
getLines().put(bar.toString(), BossBarLine.fromConfig(bar.toString()));
|
||||
}
|
||||
for (String bar : new ArrayList<String>(defaultBars)) {
|
||||
if (lines.get(bar) == null) {
|
||||
for (String bar : new ArrayList<>(defaultBars)) {
|
||||
if (getLines().get(bar) == null) {
|
||||
tab.getErrorManager().startupWarn("BossBar \"&e" + bar + "&c\" is defined as default bar, but does not exist! &bIgnoring.");
|
||||
defaultBars.remove(bar);
|
||||
}
|
||||
}
|
||||
for (Entry<String, List<String>> entry : perWorld.entrySet()) {
|
||||
List<String> bars = entry.getValue();
|
||||
for (String bar : new ArrayList<String>(bars)) {
|
||||
if (lines.get(bar) == null) {
|
||||
for (String bar : new ArrayList<>(bars)) {
|
||||
if (getLines().get(bar) == null) {
|
||||
tab.getErrorManager().startupWarn("BossBar \"&e" + bar + "&c\" is defined as per-world bar in world &e" + entry.getKey() + "&c, but does not exist! &bIgnoring.");
|
||||
bars.remove(bar);
|
||||
}
|
||||
}
|
||||
}
|
||||
remember_toggle_choice = tab.getConfiguration().bossbar.getBoolean("remember-toggle-choice", false);
|
||||
if (remember_toggle_choice) {
|
||||
bossbar_off_players = tab.getConfiguration().getPlayerData("bossbar-off");
|
||||
rememberToggleChoice = tab.getConfiguration().getBossbarConfig().getBoolean("remember-toggle-choice", false);
|
||||
if (isRememberToggleChoice()) {
|
||||
bossbarOffPlayers = tab.getConfiguration().getPlayerData("bossbar-off");
|
||||
}
|
||||
TAB.getInstance().getPlaceholderManager().allUsedPlaceholderIdentifiers.add("%countdown%");
|
||||
TAB.getInstance().getPlaceholderManager().getAllUsedPlaceholderIdentifiers().add("%countdown%");
|
||||
TAB.getInstance().getPlaceholderManager().registerPlaceholder(new ServerPlaceholder("%countdown%", 100) {
|
||||
|
||||
@Override
|
||||
public String get() {
|
||||
return String.valueOf((announceEndTime - System.currentTimeMillis()) / 1000);
|
||||
return String.valueOf((getAnnounceEndTime() - System.currentTimeMillis()) / 1000);
|
||||
}
|
||||
});
|
||||
tab.debug(String.format("Loaded Bossbar feature with parameters disabledWorlds=%s, toggleCommand=%s, defaultBars=%s, permToToggle=%s, hiddenByDefault=%s, perWorld=%s, remember_toggle_choice=%s",
|
||||
disabledWorlds, toggleCommand, defaultBars, permToToggle, hiddenByDefault, perWorld, remember_toggle_choice));
|
||||
disabledWorlds, toggleCommand, defaultBars, isPermToToggle(), hiddenByDefault, perWorld, isRememberToggleChoice()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -110,19 +115,18 @@ public class BossBar implements Loadable, JoinEventListener, WorldChangeListener
|
||||
for (TabPlayer p : tab.getPlayers()) {
|
||||
onJoin(p);
|
||||
}
|
||||
tab.getCPUManager().startRepeatingMeasuredTask(1000, "refreshing bossbar permissions", getFeatureType(), UsageType.REPEATING_TASK, new Runnable() {
|
||||
public void run() {
|
||||
for (TabPlayer p : tab.getPlayers()) {
|
||||
if (!p.hasBossbarVisible() || isDisabledWorld(disabledWorlds, p.getWorldName())) continue;
|
||||
for (BossBarLine bar : p.getActiveBossBars().toArray(new BossBarLine[0])) {
|
||||
if (!bar.isConditionMet(p)) {
|
||||
bar.remove(p);
|
||||
p.getActiveBossBars().remove(bar);
|
||||
}
|
||||
tab.getCPUManager().startRepeatingMeasuredTask(1000, "refreshing bossbar permissions", getFeatureType(), UsageType.REPEATING_TASK, () -> {
|
||||
|
||||
for (TabPlayer p : tab.getPlayers()) {
|
||||
if (!p.hasBossbarVisible() || playersInDisabledWorlds.contains(p)) continue;
|
||||
for (BossBarLine bar : p.getActiveBossBars().toArray(new BossBarLine[0])) {
|
||||
if (!bar.isConditionMet(p)) {
|
||||
bar.remove(p);
|
||||
p.getActiveBossBars().remove(bar);
|
||||
}
|
||||
showBossBars(p, defaultBars);
|
||||
showBossBars(p, perWorld.get(p.getWorldName()));
|
||||
}
|
||||
showBossBars(p, defaultBars);
|
||||
showBossBars(p, perWorld.get(tab.getConfiguration().getWorldGroupOf(perWorld.keySet(), p.getWorldName())));
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -134,16 +138,25 @@ public class BossBar implements Loadable, JoinEventListener, WorldChangeListener
|
||||
p.removeBossBar(line);
|
||||
}
|
||||
}
|
||||
lines.clear();
|
||||
getLines().clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onJoin(TabPlayer connectedPlayer) {
|
||||
connectedPlayer.setBossbarVisible(!bossbar_off_players.contains(connectedPlayer.getName()) && !hiddenByDefault, false);
|
||||
if (isDisabledWorld(disabledWorlds, connectedPlayer.getWorldName())) {
|
||||
playersInDisabledWorlds.add(connectedPlayer);
|
||||
return;
|
||||
}
|
||||
connectedPlayer.setBossbarVisible(!getBossbarOffPlayers().contains(connectedPlayer.getName()) && !hiddenByDefault, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWorldChange(TabPlayer p, String from, String to) {
|
||||
if (isDisabledWorld(disabledWorlds, p.getWorldName())) {
|
||||
playersInDisabledWorlds.add(p);
|
||||
} else {
|
||||
playersInDisabledWorlds.remove(p);
|
||||
}
|
||||
for (me.neznamy.tab.api.bossbar.BossBar line : p.getActiveBossBars().toArray(new me.neznamy.tab.api.bossbar.BossBar[0])) {
|
||||
p.removeBossBar(line);
|
||||
}
|
||||
@@ -153,7 +166,7 @@ public class BossBar implements Loadable, JoinEventListener, WorldChangeListener
|
||||
@Override
|
||||
public boolean onCommand(TabPlayer sender, String message) {
|
||||
if (message.equalsIgnoreCase(toggleCommand)) {
|
||||
tab.command.execute(sender, new String[] {"bossbar"});
|
||||
tab.getCommand().execute(sender, new String[] {"bossbar"});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -165,10 +178,10 @@ public class BossBar implements Loadable, JoinEventListener, WorldChangeListener
|
||||
*/
|
||||
public void detectBossBarsAndSend(TabPlayer p) {
|
||||
p.getActiveBossBars().clear();
|
||||
if (isDisabledWorld(disabledWorlds, p.getWorldName()) || !p.hasBossbarVisible()) return;
|
||||
if (playersInDisabledWorlds.contains(p) || !p.hasBossbarVisible()) return;
|
||||
showBossBars(p, defaultBars);
|
||||
showBossBars(p, announcements);
|
||||
showBossBars(p, perWorld.get(p.getWorldName()));
|
||||
showBossBars(p, getAnnouncements());
|
||||
showBossBars(p, perWorld.get(tab.getConfiguration().getWorldGroupOf(perWorld.keySet(), p.getWorldName())));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -179,7 +192,7 @@ public class BossBar implements Loadable, JoinEventListener, WorldChangeListener
|
||||
private void showBossBars(TabPlayer p, List<String> bars) {
|
||||
if (bars == null) return;
|
||||
for (String defaultBar : bars) {
|
||||
BossBarLine bar = lines.get(defaultBar);
|
||||
BossBarLine bar = getLines().get(defaultBar);
|
||||
if (bar.isConditionMet(p) && !p.getActiveBossBars().contains(bar)) {
|
||||
bar.create(p);
|
||||
p.getActiveBossBars().add(bar);
|
||||
@@ -198,9 +211,42 @@ public class BossBar implements Loadable, JoinEventListener, WorldChangeListener
|
||||
* @return bossbar with specified uuid
|
||||
*/
|
||||
public BossBarLine getLine(UUID id) {
|
||||
for (BossBarLine line : lines.values()) {
|
||||
if (line.uuid == id) return line;
|
||||
for (BossBarLine line : getLines().values()) {
|
||||
if (line.getUuid() == id) return line;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<String> getBossbarOffPlayers() {
|
||||
return bossbarOffPlayers;
|
||||
}
|
||||
|
||||
public boolean isRememberToggleChoice() {
|
||||
return rememberToggleChoice;
|
||||
}
|
||||
|
||||
public Map<String, BossBarLine> getLines() {
|
||||
return lines;
|
||||
}
|
||||
|
||||
public List<String> getAnnouncements() {
|
||||
return announcements;
|
||||
}
|
||||
|
||||
public long getAnnounceEndTime() {
|
||||
return announceEndTime;
|
||||
}
|
||||
|
||||
public void setAnnounceEndTime(long announceEndTime) {
|
||||
this.announceEndTime = announceEndTime;
|
||||
}
|
||||
|
||||
public boolean isPermToToggle() {
|
||||
return permToToggle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onQuit(TabPlayer disconnectedPlayer) {
|
||||
playersInDisabledWorlds.remove(disconnectedPlayer);
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import java.util.UUID;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import me.neznamy.tab.api.bossbar.BarColor;
|
||||
import me.neznamy.tab.api.bossbar.BarStyle;
|
||||
import me.neznamy.tab.shared.PropertyUtils;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.cpu.TabFeature;
|
||||
import me.neznamy.tab.shared.packets.PacketPlayOutBoss;
|
||||
@@ -16,25 +17,25 @@ import me.neznamy.tab.shared.placeholders.conditions.Condition;
|
||||
public class BossBarLine implements me.neznamy.tab.api.bossbar.BossBar {
|
||||
|
||||
//bossbar name
|
||||
public String name;
|
||||
private String name;
|
||||
|
||||
//display condition
|
||||
public Condition displayCondition;
|
||||
private Condition displayCondition;
|
||||
|
||||
//uuid
|
||||
public UUID uuid;
|
||||
private UUID uuid;
|
||||
|
||||
//bossbar style
|
||||
public String style;
|
||||
private String style;
|
||||
|
||||
//bossbar color
|
||||
public String color;
|
||||
private String color;
|
||||
|
||||
//bossbar title
|
||||
public String title;
|
||||
private String title;
|
||||
|
||||
//bossabr progress
|
||||
public String progress;
|
||||
private String progress;
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters
|
||||
@@ -104,16 +105,16 @@ public class BossBarLine implements me.neznamy.tab.api.bossbar.BossBar {
|
||||
* @param to - player to send bossbar to
|
||||
*/
|
||||
public void create(TabPlayer to){
|
||||
to.setProperty("bossbar-title-" + name, title);
|
||||
to.setProperty("bossbar-progress-" + name, progress);
|
||||
to.setProperty("bossbar-color-" + name, color);
|
||||
to.setProperty("bossbar-style-" + name, style);
|
||||
to.setProperty(PropertyUtils.bossbarTitle(name), title);
|
||||
to.setProperty(PropertyUtils.bossbarProgress(name), progress);
|
||||
to.setProperty(PropertyUtils.bossbarColor(name), color);
|
||||
to.setProperty(PropertyUtils.bossbarStyle(name), style);
|
||||
to.sendCustomPacket(new PacketPlayOutBoss(
|
||||
uuid,
|
||||
to.getProperty("bossbar-title-" + name).get(),
|
||||
(float)parseProgress(to.getProperty("bossbar-progress-" + name).get())/100,
|
||||
parseColor(to.getProperty("bossbar-color-" + name).get()),
|
||||
parseStyle(to.getProperty("bossbar-style-" + name).get())
|
||||
getUuid(),
|
||||
to.getProperty(PropertyUtils.bossbarTitle(name)).get(),
|
||||
parseProgress(to.getProperty(PropertyUtils.bossbarProgress(name)).get())/100,
|
||||
parseColor(to.getProperty(PropertyUtils.bossbarColor(name)).get()),
|
||||
parseStyle(to.getProperty(PropertyUtils.bossbarStyle(name)).get())
|
||||
), TabFeature.BOSSBAR
|
||||
);
|
||||
}
|
||||
@@ -123,7 +124,7 @@ public class BossBarLine implements me.neznamy.tab.api.bossbar.BossBar {
|
||||
* @param to - player to remove bossbar from
|
||||
*/
|
||||
public void remove(TabPlayer to) {
|
||||
to.sendCustomPacket(new PacketPlayOutBoss(uuid), TabFeature.BOSSBAR);
|
||||
to.sendCustomPacket(new PacketPlayOutBoss(getUuid()), TabFeature.BOSSBAR);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -133,7 +134,7 @@ public class BossBarLine implements me.neznamy.tab.api.bossbar.BossBar {
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId() {
|
||||
return uuid;
|
||||
return getUuid();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -142,8 +143,8 @@ public class BossBarLine implements me.neznamy.tab.api.bossbar.BossBar {
|
||||
TAB.getInstance().getPlaceholderManager().checkForRegistration(title);
|
||||
for (TabPlayer p : TAB.getInstance().getPlayers()) {
|
||||
if (p.getActiveBossBars().contains(this)) {
|
||||
p.setProperty("bossbar-title-" + name, title);
|
||||
p.sendCustomPacket(new PacketPlayOutBoss(uuid, p.getProperty("bossbar-title-" + name).get()), TabFeature.BOSSBAR);
|
||||
p.setProperty(PropertyUtils.bossbarTitle(name), title);
|
||||
p.sendCustomPacket(new PacketPlayOutBoss(getUuid(), p.getProperty(PropertyUtils.bossbarTitle(name)).get()), TabFeature.BOSSBAR);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -154,8 +155,8 @@ public class BossBarLine implements me.neznamy.tab.api.bossbar.BossBar {
|
||||
TAB.getInstance().getPlaceholderManager().checkForRegistration(progress);
|
||||
for (TabPlayer p : TAB.getInstance().getPlayers()) {
|
||||
if (p.getActiveBossBars().contains(this)) {
|
||||
p.setProperty("bossbar-progress-" + name, progress);
|
||||
p.sendCustomPacket(new PacketPlayOutBoss(uuid, (float) parseProgress(p.getProperty("bossbar-progress-" + name).get())/100), TabFeature.BOSSBAR);
|
||||
p.setProperty(PropertyUtils.bossbarProgress(name), progress);
|
||||
p.sendCustomPacket(new PacketPlayOutBoss(getUuid(), parseProgress(p.getProperty(PropertyUtils.bossbarProgress(name)).get())/100), TabFeature.BOSSBAR);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -171,10 +172,10 @@ public class BossBarLine implements me.neznamy.tab.api.bossbar.BossBar {
|
||||
TAB.getInstance().getPlaceholderManager().checkForRegistration(color);
|
||||
for (TabPlayer p : TAB.getInstance().getPlayers()) {
|
||||
if (p.getActiveBossBars().contains(this)) {
|
||||
p.setProperty("bossbar-color-" + name, color);
|
||||
p.sendCustomPacket(new PacketPlayOutBoss(uuid,
|
||||
parseColor(p.getProperty("bossbar-color-" + name).get()),
|
||||
parseStyle(p.getProperty("bossbar-style-" + name).get())
|
||||
p.setProperty(PropertyUtils.bossbarColor(name), color);
|
||||
p.sendCustomPacket(new PacketPlayOutBoss(getUuid(),
|
||||
parseColor(p.getProperty(PropertyUtils.bossbarColor(name)).get()),
|
||||
parseStyle(p.getProperty(PropertyUtils.bossbarStyle(name)).get())
|
||||
), TabFeature.BOSSBAR);
|
||||
}
|
||||
}
|
||||
@@ -191,10 +192,10 @@ public class BossBarLine implements me.neznamy.tab.api.bossbar.BossBar {
|
||||
TAB.getInstance().getPlaceholderManager().checkForRegistration(style);
|
||||
for (TabPlayer p : TAB.getInstance().getPlayers()) {
|
||||
if (p.getActiveBossBars().contains(this)) {
|
||||
p.setProperty("bossbar-style-" + name, style);
|
||||
p.sendCustomPacket(new PacketPlayOutBoss(uuid,
|
||||
parseColor(p.getProperty("bossbar-color-" + name).get()),
|
||||
parseStyle(p.getProperty("bossbar-style-" + name).get())
|
||||
p.setProperty(PropertyUtils.bossbarStyle(name), style);
|
||||
p.sendCustomPacket(new PacketPlayOutBoss(getUuid(),
|
||||
parseColor(p.getProperty(PropertyUtils.bossbarColor(name)).get()),
|
||||
parseStyle(p.getProperty(PropertyUtils.bossbarStyle(name)).get())
|
||||
), TabFeature.BOSSBAR);
|
||||
}
|
||||
}
|
||||
@@ -211,18 +212,18 @@ public class BossBarLine implements me.neznamy.tab.api.bossbar.BossBar {
|
||||
* @return loaded bossbar
|
||||
*/
|
||||
public static BossBarLine fromConfig(String bar) {
|
||||
String condition = TAB.getInstance().getConfiguration().bossbar.getString("bars." + bar + ".display-condition", null);
|
||||
String condition = TAB.getInstance().getConfiguration().getBossbarConfig().getString("bars." + bar + ".display-condition", null);
|
||||
if (condition == null) {
|
||||
Object permRequired = TAB.getInstance().getConfiguration().bossbar.getBoolean("bars." + bar + ".permission-required");
|
||||
Object permRequired = TAB.getInstance().getConfiguration().getBossbarConfig().getBoolean("bars." + bar + ".permission-required");
|
||||
if (permRequired != null && (boolean) permRequired) {
|
||||
condition = "permission:tab.bossbar." + bar;
|
||||
}
|
||||
}
|
||||
|
||||
String style = TAB.getInstance().getConfiguration().bossbar.getString("bars." + bar + ".style");
|
||||
String color = TAB.getInstance().getConfiguration().bossbar.getString("bars." + bar + ".color");
|
||||
String progress = TAB.getInstance().getConfiguration().bossbar.getString("bars." + bar + ".progress");
|
||||
String text = TAB.getInstance().getConfiguration().bossbar.getString("bars." + bar + ".text");
|
||||
String style = TAB.getInstance().getConfiguration().getBossbarConfig().getString("bars." + bar + ".style");
|
||||
String color = TAB.getInstance().getConfiguration().getBossbarConfig().getString("bars." + bar + ".color");
|
||||
String progress = TAB.getInstance().getConfiguration().getBossbarConfig().getString("bars." + bar + ".progress");
|
||||
String text = TAB.getInstance().getConfiguration().getBossbarConfig().getString("bars." + bar + ".text");
|
||||
if (style == null) {
|
||||
TAB.getInstance().getErrorManager().missingAttribute("BossBar", bar, "style");
|
||||
style = "PROGRESS";
|
||||
@@ -261,4 +262,8 @@ public class BossBarLine implements me.neznamy.tab.api.bossbar.BossBar {
|
||||
public String getStyle() {
|
||||
return style;
|
||||
}
|
||||
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -32,9 +32,9 @@ public class ColorAndStyleRefresher implements Refreshable {
|
||||
@Override
|
||||
public void refresh(TabPlayer refreshed, boolean force) {
|
||||
if (!refreshed.getActiveBossBars().contains(line)) return;
|
||||
Property color = refreshed.getProperty("bossbar-color-" + line.name);
|
||||
Property style = refreshed.getProperty("bossbar-style-" + line.name);
|
||||
refreshed.sendCustomPacket(new PacketPlayOutBoss(line.uuid, line.parseColor(color.updateAndGet()), line.parseStyle(style.updateAndGet())), TabFeature.BOSSBAR);
|
||||
Property color = refreshed.getProperty("bossbar-color-" + line.getName());
|
||||
Property style = refreshed.getProperty("bossbar-style-" + line.getName());
|
||||
refreshed.sendCustomPacket(new PacketPlayOutBoss(line.getUuid(), line.parseColor(color.updateAndGet()), line.parseStyle(style.updateAndGet())), TabFeature.BOSSBAR);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -44,8 +44,8 @@ public class ColorAndStyleRefresher implements Refreshable {
|
||||
|
||||
@Override
|
||||
public void refreshUsedPlaceholders() {
|
||||
usedPlaceholders = TAB.getInstance().getPlaceholderManager().getUsedPlaceholderIdentifiersRecursive(line.color);
|
||||
usedPlaceholders.addAll(TAB.getInstance().getPlaceholderManager().getUsedPlaceholderIdentifiersRecursive(line.style));
|
||||
usedPlaceholders = TAB.getInstance().getPlaceholderManager().getUsedPlaceholderIdentifiersRecursive(line.getColor());
|
||||
usedPlaceholders.addAll(TAB.getInstance().getPlaceholderManager().getUsedPlaceholderIdentifiersRecursive(line.getStyle()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -31,7 +31,7 @@ public class ProgressRefresher implements Refreshable {
|
||||
@Override
|
||||
public void refresh(TabPlayer refreshed, boolean force) {
|
||||
if (!refreshed.getActiveBossBars().contains(line)) return;
|
||||
refreshed.sendCustomPacket(new PacketPlayOutBoss(line.uuid, (float)line.parseProgress(refreshed.getProperty("bossbar-progress-" + line.name).updateAndGet())/100), TabFeature.BOSSBAR);
|
||||
refreshed.sendCustomPacket(new PacketPlayOutBoss(line.getUuid(), line.parseProgress(refreshed.getProperty("bossbar-progress-" + line.getName()).updateAndGet())/100), TabFeature.BOSSBAR);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -41,7 +41,7 @@ public class ProgressRefresher implements Refreshable {
|
||||
|
||||
@Override
|
||||
public void refreshUsedPlaceholders() {
|
||||
usedPlaceholders = TAB.getInstance().getPlaceholderManager().getUsedPlaceholderIdentifiersRecursive(line.progress);
|
||||
usedPlaceholders = TAB.getInstance().getPlaceholderManager().getUsedPlaceholderIdentifiersRecursive(line.getProgress());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -31,7 +31,7 @@ public class TextRefresher implements Refreshable {
|
||||
@Override
|
||||
public void refresh(TabPlayer refreshed, boolean force) {
|
||||
if (!refreshed.getActiveBossBars().contains(line)) return;
|
||||
refreshed.sendCustomPacket(new PacketPlayOutBoss(line.uuid, refreshed.getProperty("bossbar-title-" + line.name).updateAndGet()), TabFeature.BOSSBAR);
|
||||
refreshed.sendCustomPacket(new PacketPlayOutBoss(line.getUuid(), refreshed.getProperty("bossbar-title-" + line.getName()).updateAndGet()), TabFeature.BOSSBAR);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -41,7 +41,7 @@ public class TextRefresher implements Refreshable {
|
||||
|
||||
@Override
|
||||
public void refreshUsedPlaceholders() {
|
||||
usedPlaceholders = TAB.getInstance().getPlaceholderManager().getUsedPlaceholderIdentifiersRecursive(line.title);
|
||||
usedPlaceholders = TAB.getInstance().getPlaceholderManager().getUsedPlaceholderIdentifiersRecursive(line.getTitle());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -42,9 +42,9 @@ public class ChildGroup {
|
||||
*/
|
||||
public List<TabPlayer> selectPlayers(List<TabPlayer> players){
|
||||
if (condition == null) return players;
|
||||
List<TabPlayer> selected = new ArrayList<TabPlayer>();
|
||||
List<TabPlayer> selected = new ArrayList<>();
|
||||
for (TabPlayer player : players) {
|
||||
if (condition == null || condition.isMet(player)) {
|
||||
if (condition.isMet(player)) {
|
||||
selected.add(player);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,23 +31,17 @@ public class Layout implements Loadable, JoinEventListener {
|
||||
|
||||
private TAB tab;
|
||||
private LayoutDirection direction;
|
||||
private Map<Integer, FixedSlot> fixedSlots = new HashMap<Integer, FixedSlot>();
|
||||
private List<ParentGroup> parentGroups = new ArrayList<ParentGroup>();
|
||||
private Map<String, ChildGroup> childGroups = new HashMap<String, ChildGroup>();
|
||||
private Map<Integer, UUID> uuids = new HashMap<Integer, UUID>();
|
||||
private Map<Integer, FixedSlot> fixedSlots = new HashMap<>();
|
||||
private List<ParentGroup> parentGroups = new ArrayList<>();
|
||||
private Map<String, ChildGroup> childGroups = new HashMap<>();
|
||||
private Map<Integer, UUID> uuids = new HashMap<>();
|
||||
|
||||
public Layout(TAB tab) {
|
||||
this.tab = tab;
|
||||
try {
|
||||
new File(tab.getPlatform().getDataFolder() + File.separator + "layout").mkdirs();
|
||||
ConfigurationFile file = new YamlConfigurationFile(getClass().getClassLoader().getResourceAsStream("layout/default.yml"), new File(tab.getPlatform().getDataFolder(), "layout" + File.separator + "default.yml"));
|
||||
String type = file.getString("direction", "COLUMNS");
|
||||
try {
|
||||
direction = LayoutDirection.valueOf(type);
|
||||
} catch (Throwable e) {
|
||||
tab.getErrorManager().startupWarn("\"&e" + type + "&c\" is not a valid type of layout direction. Valid options are: &e" + Arrays.deepToString(LayoutDirection.values()) + ". &bUsing COLUMNS");
|
||||
direction = LayoutDirection.COLUMNS;
|
||||
}
|
||||
direction = parseDirection(file.getString("direction", "COLUMNS"));
|
||||
for (int i=1; i<=80; i++) {
|
||||
fixedSlots.put(i, new FixedSlot(i, "", null));
|
||||
uuids.put(i, UUID.randomUUID());
|
||||
@@ -64,7 +58,16 @@ public class Layout implements Loadable, JoinEventListener {
|
||||
}
|
||||
loadGroups(file);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
tab.getErrorManager().criticalError("Failed to load layout feature", e);
|
||||
}
|
||||
}
|
||||
|
||||
private LayoutDirection parseDirection(String value) {
|
||||
try {
|
||||
return LayoutDirection.valueOf(value);
|
||||
} catch (Exception e) {
|
||||
tab.getErrorManager().startupWarn("\"&e" + value + "&c\" is not a valid type of layout direction. Valid options are: &e" + Arrays.deepToString(LayoutDirection.values()) + ". &bUsing COLUMNS");
|
||||
return LayoutDirection.COLUMNS;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +79,7 @@ public class Layout implements Loadable, JoinEventListener {
|
||||
}
|
||||
for (Object obj : file.getConfigurationSection("parent-groups").keySet()){
|
||||
Condition condition = Condition.getCondition(file.getString("parent-groups." + obj + ".condition"));
|
||||
List<Integer> positions = new ArrayList<Integer>();
|
||||
List<Integer> positions = new ArrayList<>();
|
||||
for (String line : file.getStringList("parent-groups." + obj + ".slots")) {
|
||||
String[] arr = line.split("-");
|
||||
int from = Integer.parseInt(arr[0]);
|
||||
@@ -85,7 +88,7 @@ public class Layout implements Loadable, JoinEventListener {
|
||||
positions.add(i);
|
||||
}
|
||||
}
|
||||
List<ChildGroup> childs = new ArrayList<ChildGroup>();
|
||||
List<ChildGroup> childs = new ArrayList<>();
|
||||
if (file.hasConfigOption("parent-groups." + obj + ".child-groups")) {
|
||||
for (String child : file.getStringList("parent-groups." + obj + ".child-groups")) {
|
||||
if (childGroups.containsKey(child)) {
|
||||
@@ -98,7 +101,7 @@ public class Layout implements Loadable, JoinEventListener {
|
||||
}
|
||||
|
||||
private Map<Integer, IChatBaseComponent> doTick(TabPlayer viewer, List<TabPlayer> players) {
|
||||
Map<Integer, IChatBaseComponent> result = new HashMap<Integer, IChatBaseComponent>();
|
||||
Map<Integer, IChatBaseComponent> result = new HashMap<>();
|
||||
|
||||
for (int i=1; i<=80; i++) {
|
||||
result.put(i, new IChatBaseComponent(""));
|
||||
@@ -109,7 +112,7 @@ public class Layout implements Loadable, JoinEventListener {
|
||||
}
|
||||
|
||||
for (ParentGroup parent : parentGroups) {
|
||||
List<TabPlayer> meetingCondition = new ArrayList<TabPlayer>();
|
||||
List<TabPlayer> meetingCondition = new ArrayList<>();
|
||||
for (TabPlayer target : players) {
|
||||
if (parent.getCondition() == null || parent.getCondition().isMet(target)) {
|
||||
meetingCondition.add(target);
|
||||
@@ -122,23 +125,21 @@ public class Layout implements Loadable, JoinEventListener {
|
||||
}
|
||||
|
||||
private List<TabPlayer> sortPlayers(Collection<TabPlayer> players){
|
||||
Map<TabPlayer, String> teamMap = new HashMap<TabPlayer, String>();
|
||||
Map<TabPlayer, String> teamMap = new HashMap<>();
|
||||
for (TabPlayer p : players) {
|
||||
teamMap.put(p, p.getTeamName());
|
||||
}
|
||||
teamMap = sortByValue(teamMap);
|
||||
return new ArrayList<TabPlayer>(teamMap.keySet());
|
||||
return new ArrayList<>(teamMap.keySet());
|
||||
}
|
||||
|
||||
private <K, V extends Comparable<V>> Map<K, V> sortByValue(Map<K, V> map) {
|
||||
Comparator<K> valueComparator = new Comparator<K>() {
|
||||
public int compare(K k1, K k2) {
|
||||
int compare = map.get(k2).compareTo(map.get(k1));
|
||||
if (compare == 0) return 1;
|
||||
else return -compare;
|
||||
}
|
||||
Comparator<K> valueComparator = (k1, k2) -> {
|
||||
int compare = map.get(k2).compareTo(map.get(k1));
|
||||
if (compare == 0) return 1;
|
||||
else return -compare;
|
||||
};
|
||||
Map<K, V> sortedByValues = new TreeMap<K, V>(valueComparator);
|
||||
Map<K, V> sortedByValues = new TreeMap<>(valueComparator);
|
||||
sortedByValues.putAll(map);
|
||||
return sortedByValues;
|
||||
}
|
||||
@@ -150,7 +151,7 @@ public class Layout implements Loadable, JoinEventListener {
|
||||
|
||||
@Override
|
||||
public void onJoin(TabPlayer connectedPlayer) {
|
||||
List<PlayerInfoData> list = new ArrayList<PlayerInfoData>();
|
||||
List<PlayerInfoData> list = new ArrayList<>();
|
||||
for (FixedSlot s : fixedSlots.values()) {
|
||||
s.onJoin(connectedPlayer);
|
||||
}
|
||||
@@ -171,29 +172,26 @@ public class Layout implements Loadable, JoinEventListener {
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
tab.getCPUManager().startRepeatingMeasuredTask(500, "ticking layout", getFeatureType(), UsageType.REPEATING_TASK, new Runnable() {
|
||||
tab.getCPUManager().startRepeatingMeasuredTask(500, "ticking layout", getFeatureType(), UsageType.REPEATING_TASK, () -> {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
List<TabPlayer> players = sortPlayers(tab.getPlayers());
|
||||
for (TabPlayer p : tab.getPlayers()) {
|
||||
if (!p.isLoaded()) continue;
|
||||
List<PlayerInfoData> list = new ArrayList<PlayerInfoData>();
|
||||
for (Entry<Integer, IChatBaseComponent> entry : doTick(p, new ArrayList<TabPlayer>(players)).entrySet()) {
|
||||
int slot = translateSlot(entry.getKey());
|
||||
list.add(new PlayerInfoData(uuids.get(slot), entry.getValue()));
|
||||
}
|
||||
p.sendCustomPacket(new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.UPDATE_DISPLAY_NAME, list), getFeatureType());
|
||||
List<TabPlayer> players = sortPlayers(tab.getPlayers());
|
||||
for (TabPlayer p : tab.getPlayers()) {
|
||||
if (!p.isLoaded()) continue;
|
||||
List<PlayerInfoData> list = new ArrayList<>();
|
||||
for (Entry<Integer, IChatBaseComponent> entry : doTick(p, new ArrayList<>(players)).entrySet()) {
|
||||
int slot = translateSlot(entry.getKey());
|
||||
list.add(new PlayerInfoData(uuids.get(slot), entry.getValue()));
|
||||
}
|
||||
p.sendCustomPacket(new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.UPDATE_DISPLAY_NAME, list), getFeatureType());
|
||||
}
|
||||
});
|
||||
List<TabPlayer> players = sortPlayers(tab.getPlayers());
|
||||
for (TabPlayer p : tab.getPlayers()) {
|
||||
List<PlayerInfoData> list = new ArrayList<PlayerInfoData>();
|
||||
List<PlayerInfoData> list = new ArrayList<>();
|
||||
for (FixedSlot s : fixedSlots.values()) {
|
||||
s.onJoin(p);
|
||||
}
|
||||
for (Entry<Integer, IChatBaseComponent> entry : doTick(p, new ArrayList<TabPlayer>(players)).entrySet()) {
|
||||
for (Entry<Integer, IChatBaseComponent> entry : doTick(p, new ArrayList<>(players)).entrySet()) {
|
||||
int slot = translateSlot(entry.getKey());
|
||||
list.add(new PlayerInfoData((char)1 + "SLOT-" + (slot < 10 ? "0" + slot : String.valueOf(slot)), uuids.get(slot), null, 0, EnumGamemode.CREATIVE, entry.getValue()));
|
||||
}
|
||||
@@ -205,8 +203,8 @@ public class Layout implements Loadable, JoinEventListener {
|
||||
public void unload() {
|
||||
List<TabPlayer> players = sortPlayers(tab.getPlayers());
|
||||
for (TabPlayer p : tab.getPlayers()) {
|
||||
List<PlayerInfoData> list = new ArrayList<PlayerInfoData>();
|
||||
for (Entry<Integer, IChatBaseComponent> entry : doTick(p, new ArrayList<TabPlayer>(players)).entrySet()) {
|
||||
List<PlayerInfoData> list = new ArrayList<>();
|
||||
for (Entry<Integer, IChatBaseComponent> entry : doTick(p, new ArrayList<>(players)).entrySet()) {
|
||||
int slot = translateSlot(entry.getKey());
|
||||
list.add(new PlayerInfoData(uuids.get(slot)));
|
||||
}
|
||||
|
||||
Loaded 100 of 162 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user