Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
189797aa73 | ||
|
|
1ae2ef7cad | ||
|
|
de14e14d33 | ||
|
|
19892c14c1 | ||
|
|
2e00c4c002 | ||
|
|
97aa367629 | ||
|
|
87cc9a030b | ||
|
|
8ba83d1cb1 | ||
|
|
9f0e60bd47 | ||
|
|
93b2a25b2e | ||
|
|
4242d7a839 | ||
|
|
0ddb99bd46 | ||
|
|
969672e3ad | ||
|
|
2423fbb150 | ||
|
|
a99928dbf5 | ||
|
|
12f5dd52b4 | ||
|
|
2bd105446e | ||
|
|
6d85875fde | ||
|
|
42810aa490 | ||
|
|
bd31521bd3 | ||
|
|
ec0deb8378 | ||
|
|
ae66b6e9a1 | ||
|
|
3b86becebd | ||
|
|
4a8d86825b | ||
|
|
54a3bd81b4 | ||
|
|
b6768cca99 | ||
|
|
60c414deed | ||
|
|
009283a83f | ||
|
|
4a430b97df | ||
|
|
722333da2e | ||
|
|
1215af5262 | ||
|
|
254088c37b | ||
|
|
cb2ce4acca | ||
|
|
872adca8fd | ||
|
|
f37cc0bdd8 | ||
|
|
4063578ac3 | ||
|
|
2528de7eeb | ||
|
|
37caed3123 | ||
|
|
27fe9dfb12 | ||
|
|
0169cbd4d2 | ||
|
|
ed760aec08 | ||
|
|
858cbcefeb | ||
|
|
8a87d581a9 | ||
|
|
6d642f4e51 | ||
|
|
aca63640bc | ||
|
|
1845a35315 | ||
|
|
cab5f89a95 | ||
|
|
1777d8bf01 | ||
|
|
91b0bfaa9d |
No files matched your search
@@ -11,22 +11,22 @@ jobs:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v3.3.0 #https://github.com/actions/checkout/releases
|
||||
with:
|
||||
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
|
||||
- name: Set up JDK 11
|
||||
uses: actions/setup-java@v3
|
||||
uses: actions/setup-java@v3.9.0 #https://github.com/actions/setup-java/releases
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 11
|
||||
- name: Cache SonarCloud packages
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3.2.3 #https://github.com/actions/cache/releases
|
||||
with:
|
||||
path: ~/.sonar/cache
|
||||
key: ${{ runner.os }}-sonar
|
||||
restore-keys: ${{ runner.os }}-sonar
|
||||
- name: Cache Gradle
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3.2.3 #https://github.com/actions/cache/releases
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
@@ -39,7 +39,7 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
|
||||
run: ./gradlew clean build
|
||||
- name: Upload a Build Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v3.1.2 #https://github.com/actions/upload-artifact/releases
|
||||
with:
|
||||
name: Jar
|
||||
path: jar/build/libs/TAB-**.jar
|
||||
@@ -6,8 +6,8 @@ More information can be found at [Why TAB?](https://github.com/NEZNAMY/TAB/wiki/
|
||||
# Distribution
|
||||
As of TAB 3.0.0, released with MC 1.18 (November 30th, 2021), there is no free / premium
|
||||
version anymore. Only one version of the plugin exists now, which contains all implemented features
|
||||
and is available to everyone for free. However, official support on discord is only provided to
|
||||
those who have purchased the plugin.
|
||||
and is available to everyone for free. However, customer support is only provided to
|
||||
customers who have purchased the plugin.
|
||||
|
||||
# Compiling
|
||||
Compilation requires JDK 8 and up.
|
||||
@@ -15,17 +15,10 @@ To compile the plugin, run `./gradlew build` from the terminal.
|
||||
Once the plugin compiles, grab the jar from `/jar/build/libs/` folder.
|
||||
|
||||
# Links
|
||||
The precompiled JAR can be downloaded for free from:
|
||||
* GitHub releases: https://github.com/NEZNAMY/TAB/releases
|
||||
* BuiltByBit: https://builtbybit.com/resources/20631/
|
||||
|
||||
Support my work & receive official assistance with configuration:
|
||||
* BuiltByBit: https://builtbybit.com/resources/14009/
|
||||
* Polymart: https://polymart.org/resource/484
|
||||
|
||||
Other links:
|
||||
* Discord support for buyers: https://discord.gg/EaSvdk6
|
||||
* Wiki: https://github.com/NEZNAMY/TAB/wiki
|
||||
Download the plugin for free: [GitHub releases](https://github.com/NEZNAMY/TAB/releases),
|
||||
[BuiltByBit](https://builtbybit.com/resources/20631/), [Modrinth](https://modrinth.com/plugin/tab-was-taken)
|
||||
Support my work & receive customer support: [BuiltByBit](https://builtbybit.com/resources/14009/), [Polymart](https://polymart.org/resource/484)
|
||||
Other links: [Discord support for customers](https://discord.gg/EaSvdk6), [Wiki](https://github.com/NEZNAMY/TAB/wiki)
|
||||
|
||||
# Issues
|
||||
The [Issues](https://github.com/NEZNAMY/TAB/issues) section is **only** available for cases included in templates.
|
||||
@@ -33,6 +26,9 @@ In other words, they **are not available for**:
|
||||
* **Support** - support is provided on discord for buyers, where roles are given to verified users
|
||||
allowing us to know who bought it and who didn't. It also serves as a much faster way of communication.
|
||||
* **Feature requests** - closed indefinitely.
|
||||
|
||||
**If you're a customer, please use discord for reporting bugs, especially if you aren't good at making bug reports.
|
||||
You will be provided with a much faster and higher quality service.**
|
||||
|
||||
# Contributing
|
||||
If this plugin has helped you in any way, and you would like to return something back
|
||||
@@ -40,8 +36,8 @@ to make the plugin even better, there is a lot of ways to contribute:
|
||||
* Open a **pull request** containing a new feature or a bug fix, which you believe many users will benefit from.
|
||||
* Make detailed high-quality **bug reports**. The difference between a bug getting fixed in 1 week vs 1 hour
|
||||
is in quality of the report (typically providing correct steps to reproduce that actually work).
|
||||
* Test **experimental builds**, which can be found in [Github Actions](https://github.com/NEZNAMY/TAB/actions) or in a form of pre-releases on discord
|
||||
for problems of any kind including bugs. This way you will help make the actual releases more stable / help get stable releases sooner.
|
||||
* Test **experimental builds**, which can be found in [Github Actions](https://github.com/NEZNAMY/TAB/actions) for problems of any kind including bugs.
|
||||
This way you will help make the actual releases more stable / help get stable releases sooner.
|
||||
* Help improve the wiki by opening a [Wiki change issue](https://github.com/NEZNAMY/TAB/issues/new?assignees=&labels=Wiki&template=wiki_change.yml),
|
||||
where you can improve existing descriptions, add information you found missing, fix typos / grammar mistakes or add more examples of usage of functions.
|
||||
* [Buy a copy](https://builtbybit.com/resources/14009/) of the plugin or [send a donation](https://paypal.me/neznamy1) to keep the plugin active.
|
||||
@@ -39,15 +39,15 @@ public class RGBUtils {
|
||||
*/
|
||||
public RGBUtils() {
|
||||
List<RGBFormatter> list = new ArrayList<>();
|
||||
try {
|
||||
Class.forName("net.kyori.adventure.text.minimessage.MiniMessage");
|
||||
list.add(new MiniMessageFormat());
|
||||
} catch (ClassNotFoundException ignored) {}
|
||||
list.add(new BukkitFormat());
|
||||
list.add(new CMIFormat());
|
||||
list.add(new UnnamedFormat1());
|
||||
list.add(new HtmlFormat());
|
||||
list.add(new KyoriFormat());
|
||||
try {
|
||||
Class.forName("net.kyori.adventure.text.minimessage.MiniMessage");
|
||||
list.add(new MiniMessageFormat());
|
||||
} catch (ClassNotFoundException ignored) {}
|
||||
formats = list.toArray(new RGBFormatter[0]);
|
||||
|
||||
gradients = new GradientPattern[] {
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
package me.neznamy.tab.api.chat.rgb.format;
|
||||
|
||||
import me.neznamy.tab.api.chat.EnumChatFormat;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
|
||||
/**
|
||||
* Formatter for <#RRGGBB>
|
||||
* Call to MiniMessage API to reformat text to &x&R&R&G&G&B&B
|
||||
*/
|
||||
public class MiniMessageFormat implements RGBFormatter {
|
||||
|
||||
@Override
|
||||
public String reformat(String text) {
|
||||
if (!text.contains("<")) return text;
|
||||
String format = text.replace(EnumChatFormat.RESET.getFormat(), ""); //remove &r from header/footer newline inserts
|
||||
try {
|
||||
return LegacyComponentSerializer.legacySection().serialize(MiniMessage.miniMessage().deserialize(format));
|
||||
return LegacyComponentSerializer.legacySection().serialize(MiniMessage.miniMessage().deserialize(text));
|
||||
} catch (Throwable ignored) {
|
||||
return text;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
package me.neznamy.tab.api.config;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import me.neznamy.tab.api.TabAPI;
|
||||
import me.neznamy.tab.api.util.Preconditions;
|
||||
|
||||
import java.io.File;
|
||||
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.LinkedHashMap;
|
||||
@@ -16,9 +13,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import me.neznamy.tab.api.TabAPI;
|
||||
import me.neznamy.tab.api.util.Preconditions;
|
||||
|
||||
/**
|
||||
* Abstract class for configuration file
|
||||
*/
|
||||
@@ -53,18 +47,9 @@ public abstract class ConfigurationFile {
|
||||
Preconditions.checkNotNull(destination, "destination");
|
||||
this.file = destination;
|
||||
if (file.getParentFile() != null && !file.getParentFile().exists()) Files.createDirectories(file.getParentFile().toPath());
|
||||
if (!file.exists() && source == null) throw new IllegalStateException("File does not exist and source is null");
|
||||
if (file.createNewFile()) {
|
||||
// Files.copy(source, file.toPath());
|
||||
//avoiding MalformedInputException thrown on fabric due to file not having UTF8 encoding by default
|
||||
//also automatically using the encoding so users don't have to worry about it anymore
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(source, StandardCharsets.UTF_8));
|
||||
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8))){
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
writer.write(line + "\n");
|
||||
}
|
||||
}
|
||||
if (!file.exists()) {
|
||||
if (source == null) throw new IllegalStateException("File does not exist and source is null");
|
||||
Files.copy(source, file.toPath());
|
||||
}
|
||||
detectHeader();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package me.neznamy.tab.api.util;
|
||||
|
||||
/**
|
||||
* Supplier that can throw an exception
|
||||
*
|
||||
* @param <T>
|
||||
* Return class type
|
||||
*/
|
||||
public interface SupplierWithException<T> {
|
||||
|
||||
T get() throws Exception;
|
||||
}
|
||||
@@ -12,9 +12,12 @@ import me.neznamy.tab.api.protocol.PacketPlayOutBoss.Action;
|
||||
import me.neznamy.tab.api.protocol.PacketPlayOutPlayerInfo.EnumGamemode;
|
||||
import me.neznamy.tab.api.protocol.PacketPlayOutPlayerInfo.EnumPlayerInfoAction;
|
||||
import me.neznamy.tab.api.protocol.PacketPlayOutPlayerInfo.PlayerInfoData;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.*;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.PacketPlayOutEntityDestroy;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.PacketPlayOutEntityMetadata;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.PacketPlayOutEntityTeleport;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.PacketPlayOutSpawnEntityLiving;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcher;
|
||||
import org.bukkit.Bukkit;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.NMSStorage;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.EntityType;
|
||||
|
||||
@@ -99,7 +102,7 @@ public class BukkitPacketBuilder extends PacketBuilder {
|
||||
);
|
||||
}
|
||||
Enum[] array = packet.getActions().stream().map(action -> Enum.valueOf(nms.EnumPlayerInfoAction, action.toString())).toArray(Enum[]::new);
|
||||
Object nmsPacket = nms.newPacketPlayOutPlayerInfo.newInstance(array[0], nms.getHandle.invoke(Bukkit.getOnlinePlayers().iterator().next()));
|
||||
Object nmsPacket = nms.newPacketPlayOutPlayerInfo.newInstance(EnumSet.of(array[0], array), Collections.emptyList());
|
||||
List<Object> items = new ArrayList<>();
|
||||
for (PlayerInfoData data : packet.getEntries()) {
|
||||
GameProfile profile = new GameProfile(data.getUniqueId(), data.getName());
|
||||
@@ -115,7 +118,6 @@ public class BukkitPacketBuilder extends PacketBuilder {
|
||||
data.getProfilePublicKey() == null ? null : nms.newRemoteChatSession$Data.newInstance(data.getChatSessionId(), data.getProfilePublicKey()));
|
||||
items.add(obj);
|
||||
}
|
||||
nms.setField(nmsPacket, nms.PacketPlayOutPlayerInfo_ACTION, EnumSet.of(array[0], array));
|
||||
nms.setField(nmsPacket, nms.PacketPlayOutPlayerInfo_PLAYERS, items);
|
||||
return nmsPacket;
|
||||
} else {
|
||||
|
||||
@@ -9,7 +9,7 @@ import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import me.neznamy.tab.api.TabFeature;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.NMSStorage;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.NMSStorage;
|
||||
import me.neznamy.tab.api.TabConstants;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.features.PipelineInjector;
|
||||
|
||||
@@ -5,6 +5,7 @@ import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import me.neznamy.tab.api.TabConstants;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import me.neznamy.tab.api.chat.EnumChatFormat;
|
||||
import me.neznamy.tab.api.chat.rgb.RGBUtils;
|
||||
import me.neznamy.tab.platforms.bukkit.features.BukkitTabExpansion;
|
||||
import me.neznamy.tab.platforms.bukkit.features.PerWorldPlayerList;
|
||||
import me.neznamy.tab.platforms.bukkit.features.PetFix;
|
||||
@@ -272,6 +273,7 @@ public class BukkitPlatform extends Platform {
|
||||
/**
|
||||
* Sends console message using ConsoleCommandSender, due to
|
||||
* Paper not translating colors correctly in Logger messages
|
||||
* and to allow RGB (at least on Paper, doesn't work on spigot)
|
||||
*
|
||||
* @param message
|
||||
* Message to send
|
||||
@@ -280,6 +282,9 @@ public class BukkitPlatform extends Platform {
|
||||
*/
|
||||
@Override
|
||||
public void sendConsoleMessage(String message, boolean translateColors) {
|
||||
Bukkit.getConsoleSender().sendMessage("[TAB] " + (translateColors ? EnumChatFormat.color(message) : message));
|
||||
Bukkit.getConsoleSender().sendMessage("[TAB] " + (translateColors ?
|
||||
EnumChatFormat.color(RGBUtils.getInstance().convertToBukkitFormat(message,
|
||||
TAB.getInstance().getServerVersion().getMinorVersion() >= 16))
|
||||
: message));
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ import com.viaversion.viaversion.api.legacy.bossbar.BossStyle;
|
||||
import io.netty.channel.Channel;
|
||||
import me.neznamy.tab.api.chat.rgb.RGBUtils;
|
||||
import me.neznamy.tab.api.protocol.PacketPlayOutBoss;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.NMSStorage;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.NMSStorage;
|
||||
import me.neznamy.tab.shared.ITabPlayer;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
package me.neznamy.tab.platforms.bukkit;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import me.neznamy.tab.api.ProtocolVersion;
|
||||
import me.neznamy.tab.api.TabAPI;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.*;
|
||||
import me.neznamy.tab.api.TabConstants;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import me.neznamy.tab.api.chat.EnumChatFormat;
|
||||
import me.neznamy.tab.api.util.SupplierWithException;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.*;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import org.bstats.bukkit.Metrics;
|
||||
import org.bstats.charts.SimplePie;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.*;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import me.neznamy.tab.api.ProtocolVersion;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import me.neznamy.tab.api.chat.EnumChatFormat;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.api.TabConstants;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Main class for Bukkit platform
|
||||
*/
|
||||
@@ -77,25 +77,16 @@ public class Main extends JavaPlugin {
|
||||
try {
|
||||
long time = System.currentTimeMillis();
|
||||
int minorVersion = Integer.parseInt(serverPackage.split("_")[1]);
|
||||
if (minorVersion >= 17) {
|
||||
try {
|
||||
NMSStorage.setInstance(new BukkitModernNMSStorage());
|
||||
} catch (ClassNotFoundException e) {
|
||||
NMSStorage.setInstance(new MojangModernNMSStorage());
|
||||
}
|
||||
} else {
|
||||
NMSStorage.setInstance(new LegacyNMSStorage());
|
||||
}
|
||||
NMSStorage.setInstance(getNMSLoader());
|
||||
if (supportedVersions.contains(serverPackage)) {
|
||||
Bukkit.getConsoleSender().sendMessage(EnumChatFormat.color("[TAB] Loaded NMS hook in " + (System.currentTimeMillis()-time) + "ms"));
|
||||
return true;
|
||||
} else {
|
||||
Bukkit.getConsoleSender().sendMessage(EnumChatFormat.color("&c[TAB] No compatibility issue was found, but this plugin version does not claim to support your server package (" + serverPackage + "). This jar has only been tested on 1.5.2 - 1.19.3. Disabling just to stay safe."));
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
} catch (IllegalStateException ex) {
|
||||
if (supportedVersions.contains(serverPackage)) {
|
||||
Bukkit.getConsoleSender().sendMessage(EnumChatFormat.color("&c[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)"));
|
||||
getLogger().log(Level.SEVERE, "", ex);
|
||||
Bukkit.getConsoleSender().sendMessage(EnumChatFormat.color("&c[TAB] Your server version is marked as compatible, but a compatibility issue was found. Please report this issue (include your server version & fork too)"));
|
||||
} else {
|
||||
Bukkit.getConsoleSender().sendMessage(EnumChatFormat.color("&c[TAB] Your server version is completely unsupported. This plugin version only supports 1.5.2 - 1.19.3. Disabling."));
|
||||
}
|
||||
@@ -103,6 +94,20 @@ public class Main extends JavaPlugin {
|
||||
return false;
|
||||
}
|
||||
|
||||
private NMSStorage getNMSLoader() {
|
||||
List<SupplierWithException<NMSStorage>> loaders = new ArrayList<>();
|
||||
loaders.add(BukkitLegacyNMSStorage::new);
|
||||
loaders.add(BukkitModernNMSStorage::new);
|
||||
loaders.add(MojangModernNMSStorage::new);
|
||||
loaders.add(ThermosNMSStorage::new);
|
||||
for (SupplierWithException<NMSStorage> loader : loaders) {
|
||||
try {
|
||||
return loader.get();
|
||||
} catch (Exception ignored){}
|
||||
}
|
||||
throw new IllegalStateException("Unsupported server version");
|
||||
}
|
||||
|
||||
/**
|
||||
* Command handler for /tab command
|
||||
*/
|
||||
|
||||
+1
-5
@@ -25,9 +25,6 @@ import me.neznamy.tab.shared.TAB;
|
||||
@SuppressWarnings("deprecation")
|
||||
public class PerWorldPlayerList extends TabFeature implements Listener {
|
||||
|
||||
/** Reference to main class */
|
||||
private final JavaPlugin plugin;
|
||||
|
||||
/** Config options */
|
||||
private final boolean allowBypass = TabAPI.getInstance().getConfig().getBoolean("per-world-playerlist.allow-bypass-permission", false);
|
||||
private final List<String> ignoredWorlds = TabAPI.getInstance().getConfig().getStringList("per-world-playerlist.ignore-effect-in-worlds", Arrays.asList("ignoredworld", "build"));
|
||||
@@ -41,14 +38,13 @@ public class PerWorldPlayerList extends TabFeature implements Listener {
|
||||
*/
|
||||
public PerWorldPlayerList(JavaPlugin plugin) {
|
||||
super("Per world PlayerList", null);
|
||||
this.plugin = plugin;
|
||||
Bukkit.getPluginManager().registerEvents(this, plugin);
|
||||
TabAPI.getInstance().debug(String.format("Loaded PerWorldPlayerList feature with parameters allowBypass=%s, ignoredWorlds=%s, sharedWorlds=%s", allowBypass, ignoredWorlds, sharedWorlds));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(){
|
||||
Bukkit.getScheduler().runTask(plugin, () -> Bukkit.getOnlinePlayers().forEach(this::checkPlayer));
|
||||
Bukkit.getOnlinePlayers().forEach(this::checkPlayer);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,7 +3,7 @@ package me.neznamy.tab.platforms.bukkit.features;
|
||||
import me.neznamy.tab.api.TabAPI;
|
||||
import me.neznamy.tab.api.TabFeature;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.NMSStorage;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.NMSStorage;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcher;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcherItem;
|
||||
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ import me.neznamy.tab.api.TabAPI;
|
||||
import me.neznamy.tab.api.TabConstants;
|
||||
import me.neznamy.tab.api.TabFeature;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.NMSStorage;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.NMSStorage;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
package me.neznamy.tab.platforms.bukkit.nms;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* NMS loader for minecraft 1.17+ using Mojang packaging.
|
||||
*/
|
||||
public abstract class ModernNMSStorage extends NMSStorage {
|
||||
|
||||
/**
|
||||
* Creates new instance, initializes required NMS classes and fields
|
||||
*
|
||||
* @throws ReflectiveOperationException
|
||||
* If any class, field or method fails to load
|
||||
*/
|
||||
public ModernNMSStorage() throws ReflectiveOperationException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns class with given potential names in same order
|
||||
*
|
||||
* @param names
|
||||
* possible class names
|
||||
* @return class for specified names
|
||||
* @throws ClassNotFoundException
|
||||
* if class does not exist
|
||||
*/
|
||||
protected Class<?> getModernClass(String... names) throws ClassNotFoundException {
|
||||
for (String name : names) {
|
||||
try {
|
||||
return Class.forName(name);
|
||||
} catch (ClassNotFoundException e) {
|
||||
//not the first class name in array
|
||||
}
|
||||
}
|
||||
throw new ClassNotFoundException("No class found with possible names " + Arrays.toString(names));
|
||||
}
|
||||
}
|
||||
+6
-1
@@ -5,7 +5,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import me.neznamy.tab.api.util.Preconditions;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.NMSStorage;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.NMSStorage;
|
||||
|
||||
/**
|
||||
* A class representing the n.m.s.DataWatcher class to make work with it much easier
|
||||
@@ -112,4 +112,9 @@ public class DataWatcher {
|
||||
}
|
||||
return watcher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("DataWatcher{values=%s}", dataValues);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -4,7 +4,7 @@ import me.neznamy.tab.api.ProtocolVersion;
|
||||
import me.neznamy.tab.api.TabAPI;
|
||||
import me.neznamy.tab.api.chat.IChatBaseComponent;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitPacketBuilder;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.NMSStorage;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.NMSStorage;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
+6
-1
@@ -2,7 +2,7 @@ package me.neznamy.tab.platforms.bukkit.nms.datawatcher;
|
||||
|
||||
import me.neznamy.tab.api.TabAPI;
|
||||
import me.neznamy.tab.api.util.Preconditions;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.NMSStorage;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.NMSStorage;
|
||||
|
||||
/**
|
||||
* Class representing NMS Data Watcher Item
|
||||
@@ -67,4 +67,9 @@ public class DataWatcherItem {
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("DataWatcherItem{type=%s,value=%s}", type, value);
|
||||
}
|
||||
}
|
||||
+5
@@ -39,4 +39,9 @@ public class DataWatcherObject {
|
||||
public Object getSerializer() {
|
||||
return serializer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("DataWatcherObject{position=%d,serializer=%s}", position, serializer);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
package me.neznamy.tab.platforms.bukkit.nms.datawatcher;
|
||||
|
||||
import me.neznamy.tab.platforms.bukkit.nms.NMSStorage;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.NMSStorage;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
+18
-31
@@ -1,14 +1,12 @@
|
||||
package me.neznamy.tab.platforms.bukkit.nms;
|
||||
|
||||
import me.neznamy.tab.platforms.bukkit.Main;
|
||||
package me.neznamy.tab.platforms.bukkit.nms.storage;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* NMS loader for Minecraft 1.16.5 and lower using old NMS class structure.
|
||||
* NMS loader for Minecraft 1.5.2 - 1.16.5 using Bukkit mapping.
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public class LegacyNMSStorage extends NMSStorage {
|
||||
public class BukkitLegacyNMSStorage extends NMSStorage {
|
||||
|
||||
/**
|
||||
* Creates new instance, initializes required NMS classes and fields
|
||||
@@ -16,7 +14,7 @@ public class LegacyNMSStorage extends NMSStorage {
|
||||
* @throws ReflectiveOperationException
|
||||
* If any class, field or method fails to load
|
||||
*/
|
||||
public LegacyNMSStorage() throws ReflectiveOperationException {
|
||||
public BukkitLegacyNMSStorage() throws ReflectiveOperationException {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,44 +46,33 @@ public class LegacyNMSStorage extends NMSStorage {
|
||||
* @throws ClassNotFoundException
|
||||
* if class was not found
|
||||
*/
|
||||
private Class<?> getLegacyClass(String name) throws ClassNotFoundException {
|
||||
try {
|
||||
return Class.forName("net.minecraft.server." + serverPackage + "." + name);
|
||||
} catch (ClassNotFoundException | NullPointerException e) {
|
||||
try {
|
||||
//modded server?
|
||||
Class<?> clazz = Main.class.getClassLoader().loadClass("net.minecraft.server." + serverPackage + "." + name);
|
||||
if (clazz != null) return clazz;
|
||||
} catch (NullPointerException ignored) {}
|
||||
throw new ClassNotFoundException(name);
|
||||
}
|
||||
public Class<?> getLegacyClass(String name) throws ClassNotFoundException {
|
||||
return Class.forName("net.minecraft.server." + serverPackage + "." + name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadNamedFieldsAndMethods() throws ReflectiveOperationException {
|
||||
PING = getField(EntityPlayer, "ping", "field_71138_i"); // {Bukkit, Thermos}
|
||||
ScoreboardScore_setScore = getMethod(ScoreboardScore, new String[]{"setScore", "func_96647_c"}, int.class); // {Bukkit, Thermos}
|
||||
ScoreboardTeam_setAllowFriendlyFire = getMethod(ScoreboardTeam,
|
||||
new String[]{"setAllowFriendlyFire", "func_96660_a"}, boolean.class); // {Bukkit, Thermos}
|
||||
ScoreboardTeam_setCanSeeFriendlyInvisibles = getMethod(ScoreboardTeam,
|
||||
new String[]{"setCanSeeFriendlyInvisibles", "func_98300_b"}, boolean.class); // {Bukkit, Thermos}
|
||||
PING = getField(EntityPlayer, "ping");
|
||||
ScoreboardScore_setScore = getMethod(ScoreboardScore, new String[] {"setScore", "c"}, int.class); // 1.5.1+, 1.5
|
||||
ScoreboardTeam_setAllowFriendlyFire = getMethod(ScoreboardTeam, new String[] {"setAllowFriendlyFire", "a"}, boolean.class); // 1.5.1+, 1.5
|
||||
ScoreboardTeam_setCanSeeFriendlyInvisibles = getMethod(ScoreboardTeam, new String[] {"setCanSeeFriendlyInvisibles", "b"}, boolean.class); // 1.5.1+, 1.5
|
||||
if (minorVersion >= 7) {
|
||||
ChatSerializer_DESERIALIZE = getMethod(ChatSerializer, new String[]{"a", "func_150699_a"}, String.class); // {Bukkit, Thermos}
|
||||
ChatSerializer_DESERIALIZE = ChatSerializer.getMethod("a", String.class);
|
||||
}
|
||||
if (minorVersion >= 8) {
|
||||
ScoreboardTeam_setNameTagVisibility = getMethod(ScoreboardTeam, new String[] {"setNameTagVisibility", "a"}, EnumNameTagVisibility); // {1.8.1+, 1.8}
|
||||
}
|
||||
if (minorVersion >= 9) {
|
||||
DataWatcher_REGISTER = getMethod(DataWatcher, "register", DataWatcherObject, Object.class);
|
||||
DataWatcher_REGISTER = DataWatcher.getMethod("register", DataWatcherObject, Object.class);
|
||||
} else {
|
||||
DataWatcher_REGISTER = getMethod(DataWatcher, new String[]{"a", "func_75682_a"}, int.class, Object.class); // {Bukkit, Thermos}
|
||||
DataWatcher_REGISTER = DataWatcher.getMethod("a", int.class, Object.class);
|
||||
}
|
||||
if (minorVersion >= 13) {
|
||||
ScoreboardTeam_setPrefix = getMethod(ScoreboardTeam, "setPrefix", IChatBaseComponent);
|
||||
ScoreboardTeam_setSuffix = getMethod(ScoreboardTeam, "setSuffix", IChatBaseComponent);
|
||||
ScoreboardTeam_setPrefix = ScoreboardTeam.getMethod("setPrefix", IChatBaseComponent);
|
||||
ScoreboardTeam_setSuffix = ScoreboardTeam.getMethod("setSuffix", IChatBaseComponent);
|
||||
} else {
|
||||
ScoreboardTeam_setPrefix = getMethod(ScoreboardTeam, new String[]{"setPrefix", "func_96666_b"}, String.class); // {Bukkit, Thermos}
|
||||
ScoreboardTeam_setSuffix = getMethod(ScoreboardTeam, new String[]{"setSuffix", "func_96662_c"}, String.class); // {Bukkit, Thermos}
|
||||
ScoreboardTeam_setPrefix = getMethod(ScoreboardTeam, new String[] {"setPrefix", "b"}, String.class); // 1.5.1+, 1.5
|
||||
ScoreboardTeam_setSuffix = getMethod(ScoreboardTeam, new String[] {"setSuffix", "c"}, String.class); // 1.5.1+, 1.5
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,7 +138,7 @@ public class LegacyNMSStorage extends NMSStorage {
|
||||
Scoreboard = getLegacyClass("Scoreboard");
|
||||
ScoreboardObjective = getLegacyClass("ScoreboardObjective");
|
||||
ScoreboardScore = getLegacyClass("ScoreboardScore");
|
||||
IScoreboardCriteria = getLegacyClass("IScoreboardCriteria");
|
||||
IScoreboardCriteria = getLegacyClass("IScoreboardCriteria", "IObjective"); // 1.5.1+, 1.5
|
||||
ScoreboardTeam = getLegacyClass("ScoreboardTeam");
|
||||
if (minorVersion >= 8) {
|
||||
EnumScoreboardHealthDisplay = (Class<Enum>) getLegacyClass("IScoreboardCriteria$EnumScoreboardHealthDisplay", "EnumScoreboardHealthDisplay");
|
||||
+13
-8
@@ -1,10 +1,10 @@
|
||||
package me.neznamy.tab.platforms.bukkit.nms;
|
||||
package me.neznamy.tab.platforms.bukkit.nms.storage;
|
||||
|
||||
/**
|
||||
* NMS loader for minecraft 1.17+ using Mojang packaging and bukkit names.
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public class BukkitModernNMSStorage extends ModernNMSStorage {
|
||||
public class BukkitModernNMSStorage extends NMSStorage {
|
||||
|
||||
/**
|
||||
* Creates new instance, initializes required NMS classes and fields
|
||||
@@ -18,7 +18,7 @@ public class BukkitModernNMSStorage extends ModernNMSStorage {
|
||||
@Override
|
||||
public void loadNamedFieldsAndMethods() throws ReflectiveOperationException {
|
||||
PING = getField(EntityPlayer, "e");
|
||||
ChatSerializer_DESERIALIZE = getMethod(ChatSerializer, "a", String.class);
|
||||
ChatSerializer_DESERIALIZE = ChatSerializer.getMethod("a", String.class);
|
||||
DataWatcher_REGISTER = getMethod(DataWatcher, new String[]{"register", "a"}, DataWatcherObject, Object.class); // {Bukkit, Bukkit 1.18+}
|
||||
ScoreboardScore_setScore = getMethod(ScoreboardScore, new String[]{"setScore", "b"}, int.class); // {Bukkit, Bukkit 1.18+}
|
||||
ScoreboardTeam_setAllowFriendlyFire = getMethod(ScoreboardTeam, new String[]{"setAllowFriendlyFire", "a"}, boolean.class); // {Bukkit, Bukkit 1.18+}
|
||||
@@ -29,6 +29,7 @@ public class BukkitModernNMSStorage extends ModernNMSStorage {
|
||||
if (minorVersion >= 19) {
|
||||
EntityTypes_ARMOR_STAND = EntityTypes.getDeclaredField("d").get(null);
|
||||
PacketPlayOutSpawnEntityLiving_ENTITYTYPE = getField(PacketPlayOutSpawnEntityLiving, "e");
|
||||
DataWatcher_b = DataWatcher.getMethod("b");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,9 +49,10 @@ public class BukkitModernNMSStorage extends ModernNMSStorage {
|
||||
PlayerConnection = Class.forName("net.minecraft.server.network.PlayerConnection");
|
||||
|
||||
PacketPlayOutPlayerListHeaderFooter = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutPlayerListHeaderFooter");
|
||||
PacketPlayOutChat = getModernClass("net.minecraft.network.protocol.game.ClientboundSystemChatPacket",
|
||||
"net.minecraft.network.protocol.game.PacketPlayOutChat");
|
||||
if (minorVersion < 19) {
|
||||
if (minorVersion >= 19) {
|
||||
PacketPlayOutChat = Class.forName("net.minecraft.network.protocol.game.ClientboundSystemChatPacket");
|
||||
} else {
|
||||
PacketPlayOutChat = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutChat");
|
||||
ChatMessageType = (Class<Enum>) Class.forName("net.minecraft.network.chat.ChatMessageType");
|
||||
}
|
||||
|
||||
@@ -65,8 +67,11 @@ public class BukkitModernNMSStorage extends ModernNMSStorage {
|
||||
}
|
||||
|
||||
// Entities
|
||||
PacketPlayOutSpawnEntityLiving = getModernClass("net.minecraft.network.protocol.game.PacketPlayOutSpawnEntityLiving",
|
||||
"net.minecraft.network.protocol.game.PacketPlayOutSpawnEntity");
|
||||
if (minorVersion >= 19) {
|
||||
PacketPlayOutSpawnEntityLiving = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutSpawnEntity");
|
||||
} else {
|
||||
PacketPlayOutSpawnEntityLiving = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutSpawnEntityLiving");
|
||||
}
|
||||
PacketPlayOutEntityTeleport = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutEntityTeleport");
|
||||
PacketPlayInUseEntity = Class.forName("net.minecraft.network.protocol.game.PacketPlayInUseEntity");
|
||||
PacketPlayInUseEntity$d = Class.forName("net.minecraft.network.protocol.game.PacketPlayInUseEntity$d");
|
||||
+20
-15
@@ -1,10 +1,10 @@
|
||||
package me.neznamy.tab.platforms.bukkit.nms;
|
||||
package me.neznamy.tab.platforms.bukkit.nms.storage;
|
||||
|
||||
/**
|
||||
* NMS loader for minecraft 1.17+ using Mojang packaging and names.
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public class MojangModernNMSStorage extends ModernNMSStorage {
|
||||
public class MojangModernNMSStorage extends NMSStorage {
|
||||
|
||||
/**
|
||||
* Creates new instance, initializes required NMS classes and fields
|
||||
@@ -18,17 +18,18 @@ public class MojangModernNMSStorage extends ModernNMSStorage {
|
||||
@Override
|
||||
public void loadNamedFieldsAndMethods() throws ReflectiveOperationException {
|
||||
PING = getField(EntityPlayer, "latency");
|
||||
ChatSerializer_DESERIALIZE = getMethod(ChatSerializer, "fromJson", String.class);
|
||||
DataWatcher_REGISTER = getMethod(DataWatcher, "define", DataWatcherObject, Object.class);
|
||||
ScoreboardScore_setScore = getMethod(ScoreboardScore, "setScore", int.class);
|
||||
ScoreboardTeam_setAllowFriendlyFire = getMethod(ScoreboardTeam, "setAllowFriendlyFire", boolean.class);
|
||||
ScoreboardTeam_setCanSeeFriendlyInvisibles = getMethod(ScoreboardTeam, "setSeeFriendlyInvisibles", boolean.class);
|
||||
ScoreboardTeam_setPrefix = getMethod(ScoreboardTeam, "setPlayerPrefix", IChatBaseComponent);
|
||||
ScoreboardTeam_setSuffix = getMethod(ScoreboardTeam, "setPlayerSuffix", IChatBaseComponent);
|
||||
ScoreboardTeam_setNameTagVisibility = getMethod(ScoreboardTeam, "setNameTagVisibility", EnumNameTagVisibility);
|
||||
ChatSerializer_DESERIALIZE = ChatSerializer.getMethod("fromJson", String.class);
|
||||
DataWatcher_REGISTER = DataWatcher.getMethod("define", DataWatcherObject, Object.class);
|
||||
ScoreboardScore_setScore = ScoreboardScore.getMethod("setScore", int.class);
|
||||
ScoreboardTeam_setAllowFriendlyFire = ScoreboardTeam.getMethod("setAllowFriendlyFire", boolean.class);
|
||||
ScoreboardTeam_setCanSeeFriendlyInvisibles = ScoreboardTeam.getMethod("setSeeFriendlyInvisibles", boolean.class);
|
||||
ScoreboardTeam_setPrefix = ScoreboardTeam.getMethod("setPlayerPrefix", IChatBaseComponent);
|
||||
ScoreboardTeam_setSuffix = ScoreboardTeam.getMethod("setPlayerSuffix", IChatBaseComponent);
|
||||
ScoreboardTeam_setNameTagVisibility = ScoreboardTeam.getMethod("setNameTagVisibility", EnumNameTagVisibility);
|
||||
if (minorVersion >= 19) {
|
||||
EntityTypes_ARMOR_STAND = EntityTypes.getDeclaredField("ARMOR_STAND").get(null);
|
||||
PacketPlayOutSpawnEntityLiving_ENTITYTYPE = getField(PacketPlayOutSpawnEntityLiving, "type");
|
||||
DataWatcher_b = DataWatcher.getMethod("packDirty");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,9 +48,10 @@ public class MojangModernNMSStorage extends ModernNMSStorage {
|
||||
EntityLiving = Class.forName("net.minecraft.world.entity.LivingEntity");
|
||||
PlayerConnection = Class.forName("net.minecraft.server.network.ServerGamePacketListenerImpl");
|
||||
PacketPlayOutPlayerListHeaderFooter = Class.forName("net.minecraft.network.protocol.game.ClientboundTabListPacket");
|
||||
PacketPlayOutChat = getModernClass("net.minecraft.network.protocol.game.ClientboundSystemChatPacket",
|
||||
"net.minecraft.network.protocol.game.ClientboundChatPacket");
|
||||
if (minorVersion < 19) {
|
||||
if (minorVersion >= 19) {
|
||||
PacketPlayOutChat = Class.forName("net.minecraft.network.protocol.game.ClientboundSystemChatPacket");
|
||||
} else {
|
||||
PacketPlayOutChat = Class.forName("net.minecraft.network.protocol.game.ClientboundChatPacket");
|
||||
ChatMessageType = (Class<Enum>) Class.forName("net.minecraft.network.chat.ChatType");
|
||||
}
|
||||
|
||||
@@ -64,8 +66,11 @@ public class MojangModernNMSStorage extends ModernNMSStorage {
|
||||
}
|
||||
|
||||
// Entities
|
||||
PacketPlayOutSpawnEntityLiving = getModernClass("net.minecraft.network.protocol.game.ClientboundAddMobPacket",
|
||||
"net.minecraft.network.protocol.game.ClientboundAddEntityPacket");
|
||||
if (minorVersion >= 19) {
|
||||
PacketPlayOutSpawnEntityLiving = Class.forName("net.minecraft.network.protocol.game.ClientboundAddEntityPacket");
|
||||
} else {
|
||||
PacketPlayOutSpawnEntityLiving = Class.forName("net.minecraft.network.protocol.game.ClientboundAddMobPacket");
|
||||
}
|
||||
PacketPlayOutEntityTeleport = Class.forName("net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket");
|
||||
PacketPlayInUseEntity = Class.forName("net.minecraft.network.protocol.game.ServerboundInteractPacket");
|
||||
PacketPlayInUseEntity$d = Class.forName("net.minecraft.network.protocol.game.ServerboundInteractPacket$InteractionAction");
|
||||
+5
-63
@@ -1,4 +1,4 @@
|
||||
package me.neznamy.tab.platforms.bukkit.nms;
|
||||
package me.neznamy.tab.platforms.bukkit.nms.storage;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import io.netty.channel.Channel;
|
||||
@@ -71,13 +71,13 @@ public abstract class NMSStorage {
|
||||
public Field DataWatcherObject_SLOT;
|
||||
public Field DataWatcherObject_SERIALIZER;
|
||||
public Method DataWatcher_REGISTER;
|
||||
public Method DataWatcher_b;
|
||||
private final DataWatcherRegistry registry;
|
||||
//1.19.3+
|
||||
protected Class<?> DataWatcher$DataValue;
|
||||
public Field DataWatcher$DataValue_POSITION;
|
||||
public Field DataWatcher$DataValue_VALUE;
|
||||
public Method DataWatcher_markDirty;
|
||||
public Method DataWatcher_b;
|
||||
|
||||
/** PacketPlayOutSpawnEntityLiving */
|
||||
public Class<?> PacketPlayOutSpawnEntityLiving;
|
||||
@@ -229,7 +229,7 @@ public abstract class NMSStorage {
|
||||
try {
|
||||
Class.forName("net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket");
|
||||
is1_19_3Plus = true;
|
||||
} catch (ClassNotFoundException ignored) {}
|
||||
} catch (ClassNotFoundException | NullPointerException ignored) {}
|
||||
ProtocolVersion.UNKNOWN_SERVER_VERSION.setMinorVersion(minorVersion); //fixing compatibility with forks that set version field value to "Unknown"
|
||||
loadClasses();
|
||||
if (minorVersion >= 7) {
|
||||
@@ -312,7 +312,7 @@ public abstract class NMSStorage {
|
||||
if (minorVersion < 8) return;
|
||||
if (is1_19_3Plus()) {
|
||||
newClientboundPlayerInfoRemovePacket = ClientboundPlayerInfoRemovePacket.getConstructor(List.class);
|
||||
newPacketPlayOutPlayerInfo = PacketPlayOutPlayerInfo.getConstructor(EnumPlayerInfoAction, EntityPlayer);
|
||||
newPacketPlayOutPlayerInfo = PacketPlayOutPlayerInfo.getConstructor(EnumSet.class, Collection.class);
|
||||
ClientboundPlayerInfoRemovePacket_getEntries = getMethods(ClientboundPlayerInfoRemovePacket, List.class).get(0);
|
||||
PacketPlayOutPlayerInfo_ACTION = getFields(PacketPlayOutPlayerInfo, EnumSet.class).get(0);
|
||||
newRemoteChatSession$Data = RemoteChatSession$Data.getConstructor(UUID.class, ProfilePublicKey$a);
|
||||
@@ -466,7 +466,6 @@ public abstract class NMSStorage {
|
||||
protected void dataWatcher() throws ReflectiveOperationException {
|
||||
newDataWatcher = DataWatcher.getConstructors()[0];
|
||||
DataWatcherItem_VALUE = getFields(DataWatcherItem, Object.class).get(0);
|
||||
DataWatcher_b = getMethods(DataWatcher, List.class).get(0);
|
||||
if (minorVersion >= 9) {
|
||||
newDataWatcherObject = DataWatcherObject.getConstructor(int.class, DataWatcherSerializer);
|
||||
DataWatcherItem_TYPE = getFields(DataWatcherItem, DataWatcherObject).get(0);
|
||||
@@ -579,7 +578,7 @@ public abstract class NMSStorage {
|
||||
protected Method getMethod(Class<?> clazz, String[] names, Class<?>... parameterTypes) throws NoSuchMethodException {
|
||||
for (String name : names) {
|
||||
try {
|
||||
return getMethod(clazz, name, parameterTypes);
|
||||
return clazz.getMethod(name, parameterTypes);
|
||||
} catch (NoSuchMethodException e) {
|
||||
//not the first method in array
|
||||
}
|
||||
@@ -601,39 +600,6 @@ public abstract class NMSStorage {
|
||||
Arrays.toString(parameterTypes) + " in class " + clazz.getName() + ". Methods with matching parameters: " + list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Method from class with given name and parameter types. This should be equal to
|
||||
* simply calling Class#getMethod, which however does not work with a few specific methods on
|
||||
* CatServer fork. This workaround works for them.
|
||||
*
|
||||
* @param clazz
|
||||
* Class to get method from
|
||||
* @param name
|
||||
* Name of the method
|
||||
* @param parameterTypes
|
||||
* Parameter types of the method
|
||||
* @return Method with specified name and parameter types
|
||||
* @throws NoSuchMethodException
|
||||
* If no such method was found
|
||||
*/
|
||||
protected Method getMethod(Class<?> clazz, String name, Class<?>... parameterTypes) throws NoSuchMethodException {
|
||||
List<Method> list = new ArrayList<>();
|
||||
for (Method m : clazz.getMethods()) {
|
||||
if (!m.getName().equals(name) || m.getParameterCount() != parameterTypes.length) continue;
|
||||
Class<?>[] types = m.getParameterTypes();
|
||||
boolean valid = true;
|
||||
for (int i=0; i<types.length; i++) {
|
||||
if (types[i] != parameterTypes[i]) {
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (valid) list.add(m);
|
||||
}
|
||||
if (!list.isEmpty()) return list.get(0);
|
||||
throw new NoSuchMethodException("No method found with name " + name + " in class " + clazz.getName() + " with parameters " + Arrays.toString(parameterTypes));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all methods from class which return specified class type and have specified parameter types.
|
||||
*
|
||||
@@ -720,30 +686,6 @@ public abstract class NMSStorage {
|
||||
throw new NoSuchFieldException("Field \"" + name + "\" was not found in class " + clazz.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns field from class with specified possible names of the field.
|
||||
* Names are checked in specified order and first match is returned.
|
||||
* If no match is found, {@link NoSuchFieldException} is thrown.
|
||||
*
|
||||
* @param clazz
|
||||
* Class to get field from
|
||||
* @param potentialNames
|
||||
* Potential names of the field
|
||||
* @return Field with specified name
|
||||
* @throws NoSuchFieldException
|
||||
* If no match is found
|
||||
*/
|
||||
protected 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));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns server's minor version
|
||||
* @return server's minor version
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
package me.neznamy.tab.platforms.bukkit.nms.storage;
|
||||
|
||||
import me.neznamy.tab.platforms.bukkit.Main;
|
||||
|
||||
/**
|
||||
* NMS loader for Thermos 1.7.10.
|
||||
*/
|
||||
public class ThermosNMSStorage extends BukkitLegacyNMSStorage {
|
||||
|
||||
/**
|
||||
* Creates new instance, initializes required NMS classes and fields
|
||||
*
|
||||
* @throws ReflectiveOperationException
|
||||
* If any class, field or method fails to load
|
||||
*/
|
||||
public ThermosNMSStorage() throws ReflectiveOperationException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns class from given name
|
||||
*
|
||||
* @param name
|
||||
* class name
|
||||
* @return class from given name
|
||||
* @throws ClassNotFoundException
|
||||
* if class was not found
|
||||
*/
|
||||
@Override
|
||||
public Class<?> getLegacyClass(String name) throws ClassNotFoundException {
|
||||
try {
|
||||
return Main.class.getClassLoader().loadClass("net.minecraft.server." + serverPackage + "." + name);
|
||||
} catch (NullPointerException e) {
|
||||
// nested class not found
|
||||
throw new ClassNotFoundException(name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadNamedFieldsAndMethods() throws ReflectiveOperationException {
|
||||
PING = getField(EntityPlayer, "field_71138_i");
|
||||
ScoreboardScore_setScore = ScoreboardScore.getMethod("func_96647_c", int.class);
|
||||
ScoreboardTeam_setAllowFriendlyFire = ScoreboardTeam.getMethod("func_96660_a", boolean.class);
|
||||
ScoreboardTeam_setCanSeeFriendlyInvisibles = ScoreboardTeam.getMethod("func_98300_b", boolean.class);
|
||||
ChatSerializer_DESERIALIZE = ChatSerializer.getMethod("func_150699_a", String.class);
|
||||
DataWatcher_REGISTER = DataWatcher.getMethod("func_75682_a", int.class, Object.class);
|
||||
ScoreboardTeam_setPrefix = ScoreboardTeam.getMethod("func_96666_b", String.class);
|
||||
ScoreboardTeam_setSuffix = ScoreboardTeam.getMethod("func_96662_c", String.class);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
# Project properties - we put these here so they can be modified without causing a recompile of the build scripts
|
||||
projectVersion=3.2.1
|
||||
projectVersion=3.2.3-SNAPSHOT
|
||||
|
||||
# Gradle properties
|
||||
org.gradle.daemon=true
|
||||
|
||||
@@ -3,19 +3,19 @@ metadata.format.version = "1.1"
|
||||
[versions]
|
||||
|
||||
# API
|
||||
netty = "4.1.80.Final"
|
||||
netty = "4.1.86.Final"
|
||||
jsonSimple = "1.1.1"
|
||||
snakeyaml = "1.33"
|
||||
yamlAssist = "1.0.5"
|
||||
gson = "2.9.1"
|
||||
slf4j = "1.7.36"
|
||||
minimessage = "4.11.0"
|
||||
gson = "2.10"
|
||||
slf4j = "2.0.6"
|
||||
minimessage = "4.12.0"
|
||||
|
||||
# General
|
||||
luckperms = "5.4"
|
||||
guava = "31.1-jre"
|
||||
floodgate = "2.2.0-SNAPSHOT"
|
||||
kotlin = "1.7.10"
|
||||
kotlin = "1.8.0"
|
||||
event = "3.0.0"
|
||||
|
||||
# Platforms
|
||||
@@ -27,12 +27,12 @@ velocity = "3.1.2-SNAPSHOT"
|
||||
# Platform extras
|
||||
placeholderapi = "2.11.2"
|
||||
vault = "1.7"
|
||||
via = "4.4.2"
|
||||
via = "4.5.1"
|
||||
authlib = "1.5.25"
|
||||
bstats = "3.0.0"
|
||||
essentials = "2.19.7"
|
||||
premiumVanish = "2.7.11-2"
|
||||
redisBungee = "0.7.3"
|
||||
redisBungee = "0.10.1"
|
||||
|
||||
# Plugins
|
||||
indra = "2.1.1"
|
||||
|
||||
Vendored
BIN
Binary file not shown.
+1
-1
@@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
@@ -205,6 +205,12 @@ set -- \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
|
||||
Vendored
+8
-6
@@ -14,7 +14,7 @@
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@@ -25,7 +25,7 @@
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
@@ -75,13 +75,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
@@ -9,6 +9,7 @@ dependencyResolutionManagement {
|
||||
maven("https://repo.viaversion.com/") // ViaVersion
|
||||
maven("https://repo.essentialsx.net/releases/") // Essentials
|
||||
maven("https://repo.codemc.org/repository/maven-public/") // RedisBungee
|
||||
maven("https://repo.codemc.io/repository/maven-snapshots/") // Fixing compilation
|
||||
maven("https://repo.kryptonmc.org/releases") // YamlAssist, LuckPerms
|
||||
maven("https://repo.kryptonmc.org/snapshots") // BungeeCord
|
||||
maven("https://repo.opencollab.dev/maven-snapshots/") // Floodgate
|
||||
|
||||
@@ -44,10 +44,10 @@ public class CpuManager implements ThreadManager {
|
||||
private Map<String, AtomicInteger> packetsPrevious = new ConcurrentHashMap<>();
|
||||
|
||||
/** TAB's main thread where all tasks are executed */
|
||||
private ExecutorService thread = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat("TAB Processing Thread").build());
|
||||
private final ExecutorService thread = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat("TAB Processing Thread").build());
|
||||
|
||||
/** Thread pool for delayed and repeating tasks to perform sleep before submitting task to main thread */
|
||||
private final ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(20,
|
||||
private final ScheduledThreadPoolExecutor threadPool = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(20,
|
||||
new ThreadFactoryBuilder().setNameFormat("TAB Repeating / Delayed Thread %d").build());
|
||||
|
||||
/** Tasks submitted to main thread before plugin was fully enabled */
|
||||
@@ -74,13 +74,10 @@ public class CpuManager implements ThreadManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels all tasks, new instance is set to avoid errors when starting tasks on shutdown (such as packet readers)
|
||||
* Cancels all tasks and shuts down thread pools
|
||||
*/
|
||||
public void cancelAllTasks() {
|
||||
//preventing errors when tasks are inserted while shutting down
|
||||
ExecutorService old = thread;
|
||||
thread = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat("TAB Processing Thread").build());
|
||||
old.shutdownNow();
|
||||
thread.shutdownNow();
|
||||
threadPool.shutdownNow();
|
||||
}
|
||||
|
||||
@@ -107,13 +104,20 @@ public class CpuManager implements ThreadManager {
|
||||
taskQueue.add(task);
|
||||
return null;
|
||||
}
|
||||
return (Future<Void>) thread.submit(() -> {
|
||||
try {
|
||||
task.run();
|
||||
} catch (Exception | LinkageError | StackOverflowError e) {
|
||||
TAB.getInstance().getErrorManager().printError("An error was thrown when executing task", e);
|
||||
}
|
||||
});
|
||||
if (thread.isShutdown()) return null;
|
||||
try {
|
||||
return (Future<Void>) thread.submit(() -> {
|
||||
try {
|
||||
task.run();
|
||||
} catch (Exception | LinkageError | StackOverflowError e) {
|
||||
TAB.getInstance().getErrorManager().printError("An error was thrown when executing task", e);
|
||||
}
|
||||
});
|
||||
} catch (OutOfMemoryError e) {
|
||||
TAB.getInstance().getErrorManager().criticalError("Failed to schedule task due to " + e.getClass().getName() +
|
||||
": " + e.getMessage() + ". Threads created by TAB: " + (threadPool.getActiveCount()+1), null);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -359,21 +363,25 @@ public class CpuManager implements ThreadManager {
|
||||
|
||||
@Override
|
||||
public Future<?> startRepeatingMeasuredTask(int intervalMilliseconds, TabFeature feature, String type, Runnable task) {
|
||||
if (threadPool.isShutdown()) return null;
|
||||
return threadPool.scheduleAtFixedRate(() -> runMeasuredTask(feature, type, task), 0, intervalMilliseconds, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<?> startRepeatingTask(int intervalMilliseconds, Runnable task) {
|
||||
if (threadPool.isShutdown()) return null;
|
||||
return threadPool.scheduleAtFixedRate(() -> runTask(task), 0, intervalMilliseconds, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<?> runTaskLater(int delayMilliseconds, TabFeature feature, String type, Runnable task) {
|
||||
if (threadPool.isShutdown()) return null;
|
||||
return threadPool.schedule(() -> runMeasuredTask(feature, type, task), delayMilliseconds, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<?> runTaskLater(int delayMilliseconds, Runnable task) {
|
||||
if (threadPool.isShutdown()) return null;
|
||||
return threadPool.schedule(() -> submit(task), delayMilliseconds, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
@@ -225,6 +225,6 @@ public class DynamicText implements Property {
|
||||
RelationalPlaceholderImpl pl = (RelationalPlaceholderImpl) TAB.getInstance().getPlaceholderManager().getPlaceholder(identifier);
|
||||
format = format.replace(pl.getIdentifier(), viewer == null ? "" : pl.getLastValue(viewer, owner));
|
||||
}
|
||||
return format;
|
||||
return EnumChatFormat.color(format);
|
||||
}
|
||||
}
|
||||
@@ -119,15 +119,11 @@ public class FeatureManagerImpl implements FeatureManager {
|
||||
long millis = System.currentTimeMillis();
|
||||
TAB.getInstance().addPlayer(connectedPlayer);
|
||||
for (TabFeature f : values) {
|
||||
try {
|
||||
if (!f.overridesMethod("onJoin")) continue;
|
||||
long time = System.nanoTime();
|
||||
f.onJoin(connectedPlayer);
|
||||
TAB.getInstance().getCPUManager().addTime(f, TabConstants.CpuUsageCategory.PLAYER_JOIN, System.nanoTime()-time);
|
||||
TAB.getInstance().debug("Feature " + f.getClass().getSimpleName() + " processed player join in " + (System.nanoTime()-time)/1000000 + "ms");
|
||||
} catch (Throwable e) {
|
||||
TAB.getInstance().getErrorManager().criticalError("Feature " + f.getClass().getSimpleName() + " failed to process player " + connectedPlayer.getName(), e);
|
||||
}
|
||||
if (!f.overridesMethod("onJoin")) continue;
|
||||
long time = System.nanoTime();
|
||||
f.onJoin(connectedPlayer);
|
||||
TAB.getInstance().getCPUManager().addTime(f, TabConstants.CpuUsageCategory.PLAYER_JOIN, System.nanoTime()-time);
|
||||
TAB.getInstance().debug("Feature " + f.getClass().getSimpleName() + " processed player join in " + (System.nanoTime()-time)/1000000 + "ms");
|
||||
}
|
||||
((ITabPlayer)connectedPlayer).markAsLoaded(true);
|
||||
TAB.getInstance().debug("Player join of " + connectedPlayer.getName() + " processed in " + (System.currentTimeMillis()-millis) + "ms");
|
||||
|
||||
@@ -150,8 +150,8 @@ public class TAB extends TabAPI {
|
||||
long time = System.currentTimeMillis();
|
||||
errorManager = new ErrorManager();
|
||||
cpu = new CpuManager();
|
||||
featureManager = new FeatureManagerImpl();
|
||||
configuration = new Configs();
|
||||
featureManager = new FeatureManagerImpl();
|
||||
featureManager.registerFeature(TabConstants.Feature.PLACEHOLDER_MANAGER, new PlaceholderManagerImpl());
|
||||
featureManager.registerFeature(TabConstants.Feature.GROUP_MANAGER, new GroupManager(platform.detectPermissionPlugin()));
|
||||
platform.loadFeatures();
|
||||
|
||||
@@ -2,6 +2,7 @@ package me.neznamy.tab.shared.command;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
@@ -93,6 +94,9 @@ public class PlayerCommand extends PropertyCommand {
|
||||
if (property.length > 0 && String.valueOf(value.length() == 0 ? null : value).equals(String.valueOf(property[0]))) return;
|
||||
TAB.getInstance().getConfiguration().getUsers().setProperty(player, type, server, world, value.length() == 0 ? null : value);
|
||||
TabPlayer pl = TAB.getInstance().getPlayer(player);
|
||||
try {
|
||||
if (pl == null) pl = TAB.getInstance().getPlayer(UUID.fromString(player));
|
||||
} catch (IllegalArgumentException ignored){} // not an uuid string
|
||||
if (pl != null) {
|
||||
pl.forceRefresh();
|
||||
}
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
package me.neznamy.tab.shared.features;
|
||||
|
||||
import me.neznamy.tab.api.HeaderFooterManager;
|
||||
import me.neznamy.tab.api.TabConstants;
|
||||
import me.neznamy.tab.api.TabFeature;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import me.neznamy.tab.api.protocol.PacketPlayOutPlayerListHeaderFooter;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import me.neznamy.tab.api.HeaderFooterManager;
|
||||
import me.neznamy.tab.api.TabFeature;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import me.neznamy.tab.api.chat.EnumChatFormat;
|
||||
import me.neznamy.tab.api.protocol.PacketPlayOutPlayerListHeaderFooter;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.api.TabConstants;
|
||||
|
||||
/**
|
||||
* Feature handler for header and footer
|
||||
*/
|
||||
@@ -90,7 +89,7 @@ public class HeaderFooter extends TabFeature implements HeaderFooterManager {
|
||||
|
||||
private String getProperty(TabPlayer p, String property) {
|
||||
String append = getFromConfig(p, property + "append");
|
||||
if (append.length() > 0) append = "\n" + EnumChatFormat.COLOR_CHAR + "r" + append;
|
||||
if (append.length() > 0) append = "\n" + append;
|
||||
return getFromConfig(p, property) + append;
|
||||
}
|
||||
|
||||
@@ -115,7 +114,7 @@ public class HeaderFooter extends TabFeature implements HeaderFooterManager {
|
||||
lines = TAB.getInstance().getConfiguration().getConfig().getStringList("header-footer." + property);
|
||||
}
|
||||
if (lines == null) lines = new ArrayList<>();
|
||||
return String.join("\n" + EnumChatFormat.COLOR_CHAR + "r", lines);
|
||||
return String.join("\n", lines);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -251,7 +251,7 @@ public class PlaceholderManagerImpl extends TabFeature implements PlaceholderMan
|
||||
int refresh = gcd(p.getRefresh(), refreshInterval);
|
||||
if (refreshInterval != refresh) {
|
||||
TAB.getInstance().debug("Decreasing refresh interval of placeholder refreshing task to " + refresh + "ms due to placeholder " + identifier);
|
||||
refreshTask.cancel(true);
|
||||
if (refreshTask != null) refreshTask.cancel(true);
|
||||
refreshInterval = refresh;
|
||||
refreshTask = TAB.getInstance().getCPUManager().startRepeatingMeasuredTask(refreshInterval, this, "Refreshing placeholders", this::refresh);
|
||||
atomic.set(0);
|
||||
|
||||
@@ -62,11 +62,12 @@ public class YellowNumber extends TabFeature {
|
||||
addDisabledPlayer(loaded);
|
||||
continue;
|
||||
}
|
||||
if (loaded.isBedrockPlayer()) continue;
|
||||
loaded.sendCustomPacket(new PacketPlayOutScoreboardObjective(0, OBJECTIVE_NAME, TITLE, displayType), this);
|
||||
loaded.sendCustomPacket(new PacketPlayOutScoreboardDisplayObjective(DISPLAY_SLOT, OBJECTIVE_NAME), this);
|
||||
}
|
||||
for (TabPlayer viewer : TAB.getInstance().getOnlinePlayers()){
|
||||
if (isDisabledPlayer(viewer)) continue;
|
||||
if (isDisabledPlayer(viewer) || viewer.isBedrockPlayer()) continue;
|
||||
for (TabPlayer target : TAB.getInstance().getOnlinePlayers()){
|
||||
viewer.sendCustomPacket(new PacketPlayOutScoreboardScore(Action.CHANGE, OBJECTIVE_NAME, target.getNickname(), getValue(target)), this);
|
||||
}
|
||||
@@ -76,7 +77,7 @@ public class YellowNumber extends TabFeature {
|
||||
@Override
|
||||
public void unload() {
|
||||
for (TabPlayer p : TAB.getInstance().getOnlinePlayers()){
|
||||
if (isDisabledPlayer(p)) continue;
|
||||
if (isDisabledPlayer(p) || p.isBedrockPlayer()) continue;
|
||||
p.sendCustomPacket(new PacketPlayOutScoreboardObjective(OBJECTIVE_NAME), this);
|
||||
}
|
||||
}
|
||||
@@ -88,17 +89,15 @@ public class YellowNumber extends TabFeature {
|
||||
addDisabledPlayer(connectedPlayer);
|
||||
return;
|
||||
}
|
||||
connectedPlayer.sendCustomPacket(new PacketPlayOutScoreboardObjective(0, OBJECTIVE_NAME, TITLE, displayType), this);
|
||||
connectedPlayer.sendCustomPacket(new PacketPlayOutScoreboardDisplayObjective(DISPLAY_SLOT, OBJECTIVE_NAME), this);
|
||||
if (!connectedPlayer.isBedrockPlayer()) {
|
||||
connectedPlayer.sendCustomPacket(new PacketPlayOutScoreboardObjective(0, OBJECTIVE_NAME, TITLE, displayType), this);
|
||||
connectedPlayer.sendCustomPacket(new PacketPlayOutScoreboardDisplayObjective(DISPLAY_SLOT, OBJECTIVE_NAME), this);
|
||||
}
|
||||
int value = getValue(connectedPlayer);
|
||||
for (TabPlayer all : TAB.getInstance().getOnlinePlayers()){
|
||||
if (all == connectedPlayer) {
|
||||
connectedPlayer.sendCustomPacket(new PacketPlayOutScoreboardScore(Action.CHANGE, OBJECTIVE_NAME, connectedPlayer.getNickname(), value), this);
|
||||
continue;
|
||||
}
|
||||
if (!isDisabledPlayer(all)) {
|
||||
all.sendCustomPacket(new PacketPlayOutScoreboardScore(Action.CHANGE, OBJECTIVE_NAME, connectedPlayer.getNickname(), value), this);
|
||||
connectedPlayer.sendCustomPacket(new PacketPlayOutScoreboardScore(Action.CHANGE, OBJECTIVE_NAME, all.getNickname(), getValue(all)), this);
|
||||
if (!all.isBedrockPlayer()) all.sendCustomPacket(new PacketPlayOutScoreboardScore(Action.CHANGE, OBJECTIVE_NAME, connectedPlayer.getNickname(), value), this);
|
||||
if (!connectedPlayer.isBedrockPlayer()) connectedPlayer.sendCustomPacket(new PacketPlayOutScoreboardScore(Action.CHANGE, OBJECTIVE_NAME, all.getNickname(), getValue(all)), this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -119,7 +118,7 @@ public class YellowNumber extends TabFeature {
|
||||
removeDisabledPlayer(p);
|
||||
}
|
||||
if (disabledNow && !disabledBefore) {
|
||||
p.sendCustomPacket(new PacketPlayOutScoreboardObjective(OBJECTIVE_NAME), this);
|
||||
if (!p.isBedrockPlayer()) p.sendCustomPacket(new PacketPlayOutScoreboardObjective(OBJECTIVE_NAME), this);
|
||||
}
|
||||
if (!disabledNow && disabledBefore) {
|
||||
onJoin(p);
|
||||
@@ -132,7 +131,7 @@ public class YellowNumber extends TabFeature {
|
||||
public void refresh(TabPlayer refreshed, boolean force) {
|
||||
int value = getValue(refreshed);
|
||||
for (TabPlayer all : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (isDisabledPlayer(all)) continue;
|
||||
if (isDisabledPlayer(all) || all.isBedrockPlayer()) continue;
|
||||
all.sendCustomPacket(new PacketPlayOutScoreboardScore(Action.CHANGE, OBJECTIVE_NAME, refreshed.getNickname(), value), this);
|
||||
}
|
||||
RedisSupport redis = (RedisSupport) TAB.getInstance().getFeatureManager().getFeature(TabConstants.Feature.REDIS_BUNGEE);
|
||||
@@ -141,7 +140,7 @@ public class YellowNumber extends TabFeature {
|
||||
|
||||
@Override
|
||||
public void onLoginPacket(TabPlayer packetReceiver) {
|
||||
if (isDisabledPlayer(packetReceiver)) return;
|
||||
if (isDisabledPlayer(packetReceiver) || packetReceiver.isBedrockPlayer()) return;
|
||||
packetReceiver.sendCustomPacket(new PacketPlayOutScoreboardObjective(0, OBJECTIVE_NAME, TITLE, displayType), this);
|
||||
packetReceiver.sendCustomPacket(new PacketPlayOutScoreboardDisplayObjective(DISPLAY_SLOT, OBJECTIVE_NAME), this);
|
||||
for (TabPlayer all : TAB.getInstance().getOnlinePlayers()){
|
||||
|
||||
+7
-3
@@ -1,5 +1,6 @@
|
||||
package me.neznamy.tab.shared.features.alignedplayerlist;
|
||||
|
||||
import me.neznamy.tab.api.Property;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import me.neznamy.tab.api.chat.EnumChatFormat;
|
||||
import me.neznamy.tab.api.chat.IChatBaseComponent;
|
||||
@@ -72,9 +73,12 @@ public class PlayerView {
|
||||
public synchronized IChatBaseComponent formatName(TabPlayer target) {
|
||||
Integer width = playerWidths.get(target);
|
||||
if (width == null) return null; //in packet reader, not loaded yet, will send packet after loading player
|
||||
String prefixAndName = target.getProperty(TabConstants.Property.TABPREFIX).getFormat(viewer) +
|
||||
target.getProperty(TabConstants.Property.CUSTOMTABNAME).getFormat(viewer);
|
||||
String suffix = target.getProperty(TabConstants.Property.TABSUFFIX).getFormat(viewer);
|
||||
Property prefixPr = target.getProperty(TabConstants.Property.TABPREFIX);
|
||||
Property namePr = target.getProperty(TabConstants.Property.CUSTOMTABNAME);
|
||||
Property suffixPr = target.getProperty(TabConstants.Property.TABSUFFIX);
|
||||
if (prefixPr == null || namePr == null || suffixPr == null) return null; // no idea why is another check needed
|
||||
String prefixAndName = prefixPr.getFormat(viewer) + namePr.getFormat(viewer);
|
||||
String suffix = suffixPr.getFormat(viewer);
|
||||
if (suffix.length() == 0) return IChatBaseComponent.optimizedComponent(prefixAndName);
|
||||
if ((target.isVanished() && !canSeeVanished) || width > maxWidth) {
|
||||
//tab sending packets for vanished players or player just unvanished
|
||||
|
||||
@@ -170,7 +170,10 @@ public class BossBarLine implements BossBar {
|
||||
* @return parsed progress
|
||||
*/
|
||||
public float parseProgress(String progress) {
|
||||
return TAB.getInstance().getErrorManager().parseFloat(progress, 100);
|
||||
float value = TAB.getInstance().getErrorManager().parseFloat(progress, 100);
|
||||
if (value < 0) value = 0;
|
||||
if (value > 100) value = 100;
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
-2
@@ -168,8 +168,9 @@ public class GlobalPlayerList extends TabFeature {
|
||||
for (PlayerInfoData playerInfoData : info.getEntries()) {
|
||||
TabPlayer packetPlayer = TAB.getInstance().getPlayerByTabListUUID(playerInfoData.getUniqueId());
|
||||
//not preventing NPC removals
|
||||
if (packetPlayer != null && !packetFromTAB && !packetPlayer.isVanished() &&
|
||||
(System.currentTimeMillis()-lastServerSwitch.getOrDefault(packetPlayer, 0L) < 500)) {
|
||||
if (packetPlayer != null && !packetFromTAB && !packetPlayer.isVanished()
|
||||
&& (System.currentTimeMillis()-lastServerSwitch.getOrDefault(packetPlayer, 0L) < 2000)
|
||||
) {
|
||||
//remove packet not coming from tab
|
||||
//changing to random non-existing player, the easiest way to cancel the removal
|
||||
playerInfoData.setUniqueId(UUID.randomUUID());
|
||||
|
||||
@@ -62,7 +62,7 @@ public class NameTag extends TabFeature implements TeamManager {
|
||||
@Override
|
||||
public void unload() {
|
||||
for (TabPlayer p : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (!isDisabledPlayer(p)) unregisterTeam(p);
|
||||
if (!isDisabledPlayer(p)) unregisterTeam(p, sorting.getShortTeamName(p));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ public class NameTag extends TabFeature implements TeamManager {
|
||||
}
|
||||
boolean changed = updateProperties(p);
|
||||
if (disabledNow && !disabledBefore) {
|
||||
unregisterTeam(p);
|
||||
unregisterTeam(p, sorting.getShortTeamName(p));
|
||||
} else if (!disabledNow && disabledBefore) {
|
||||
registerTeam(p);
|
||||
} else if (changed) {
|
||||
@@ -193,7 +193,7 @@ public class NameTag extends TabFeature implements TeamManager {
|
||||
@Override
|
||||
public void pauseTeamHandling(TabPlayer player) {
|
||||
if (teamHandlingPaused.contains(player)) return;
|
||||
if (!isDisabledPlayer(player)) unregisterTeam(player);
|
||||
if (!isDisabledPlayer(player)) unregisterTeam(player, sorting.getShortTeamName(player));
|
||||
teamHandlingPaused.add(player); //adding after, so unregisterTeam method runs
|
||||
}
|
||||
|
||||
@@ -213,7 +213,7 @@ public class NameTag extends TabFeature implements TeamManager {
|
||||
public void forceTeamName(TabPlayer player, String name) {
|
||||
if (Objects.equals(forcedTeamName.get(player), name)) return;
|
||||
if (name != null && name.length() > 16) throw new IllegalArgumentException("Team name cannot be more than 16 characters long.");
|
||||
unregisterTeam(player);
|
||||
unregisterTeam(player, sorting.getShortTeamName(player));
|
||||
forcedTeamName.put(player, name);
|
||||
registerTeam(player);
|
||||
if (name != null) sorting.setTeamNameNote(player, "Set using API");
|
||||
@@ -257,10 +257,10 @@ public class NameTag extends TabFeature implements TeamManager {
|
||||
viewer.sendCustomPacket(new PacketPlayOutScoreboardTeam(sorting.getShortTeamName(p), currentPrefix, currentSuffix, translate(visible), translate(collisionManager.getCollision(p)), getTeamOptions()), TabConstants.PacketCategory.NAMETAGS_TEAM_UPDATE);
|
||||
}
|
||||
|
||||
public void unregisterTeam(TabPlayer p) {
|
||||
public void unregisterTeam(TabPlayer p, String teamName) {
|
||||
if (hasTeamHandlingPaused(p) || sorting.getShortTeamName(p) == null) return;
|
||||
for (TabPlayer viewer : TAB.getInstance().getOnlinePlayers()) {
|
||||
viewer.sendCustomPacket(new PacketPlayOutScoreboardTeam(sorting.getShortTeamName(p)), TabConstants.PacketCategory.NAMETAGS_TEAM_UNREGISTER);
|
||||
viewer.sendCustomPacket(new PacketPlayOutScoreboardTeam(teamName), TabConstants.PacketCategory.NAMETAGS_TEAM_UNREGISTER);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,13 +279,12 @@ public class NameTag extends TabFeature implements TeamManager {
|
||||
}
|
||||
|
||||
private void updateTeam(TabPlayer p) {
|
||||
if (sorting.getShortTeamName(p) == null) return; //player not loaded yet
|
||||
String oldName = getSorting().getShortTeamName(p);
|
||||
getSorting().constructTeamNames(p);
|
||||
if (oldName.equals(sorting.getShortTeamName(p))) {
|
||||
updateTeamData(p);
|
||||
} else {
|
||||
unregisterTeam(p);
|
||||
unregisterTeam(p, oldName);
|
||||
LayoutManager layout = (LayoutManager) TAB.getInstance().getFeatureManager().getFeature(TabConstants.Feature.LAYOUT);
|
||||
if (layout != null) layout.updateTeamName(p, sorting.getFullTeamName(p));
|
||||
registerTeam(p);
|
||||
|
||||
+1
-1
@@ -355,7 +355,7 @@ public abstract class NameTagX extends NameTag implements UnlimitedNametagManage
|
||||
public void pauseTeamHandling(TabPlayer player) {
|
||||
Preconditions.checkLoaded(player);
|
||||
if (teamHandlingPaused.contains(player)) return;
|
||||
if (!isDisabledPlayer(player)) unregisterTeam(player);
|
||||
if (!isDisabledPlayer(player)) unregisterTeam(player, getSorting().getShortTeamName(player));
|
||||
teamHandlingPaused.add(player); //adding after, so unregisterTeam method runs
|
||||
pauseArmorStands(player);
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ public class ScoreboardImpl extends TabFeature implements Scoreboard {
|
||||
|
||||
@Override
|
||||
public void refresh(TabPlayer refreshed, boolean force) {
|
||||
if (refreshed.getProperty(TabConstants.Property.SCOREBOARD_TITLE) == null) return;
|
||||
if (!players.contains(refreshed)) return;
|
||||
refreshed.sendCustomPacket(new PacketPlayOutScoreboardObjective(2, ScoreboardManagerImpl.OBJECTIVE_NAME,
|
||||
refreshed.getProperty(TabConstants.Property.SCOREBOARD_TITLE).updateAndGet(), EnumScoreboardHealthDisplay.INTEGER), TabConstants.PacketCategory.SCOREBOARD_TITLE);
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ public class Groups extends SortingType {
|
||||
public String getChars(ITabPlayer p) {
|
||||
String group = p.getGroup().toLowerCase();
|
||||
int position;
|
||||
if (!sortedGroups.containsKey(group.toLowerCase())) {
|
||||
if (!sortedGroups.containsKey(group)) {
|
||||
position = sortedGroups.size() + 1;
|
||||
sorting.setTeamNameNote(p, sorting.getTeamNameNote(p) + "\n-> &cPrimary group (&e" + p.getGroup() + "&c) is not in sorting list. &r");
|
||||
} else {
|
||||
|
||||
@@ -60,9 +60,7 @@ public abstract class SortingType {
|
||||
int index = 1;
|
||||
for (String element : elements){
|
||||
for (String element0 : element.split("\\|")) {
|
||||
while (element0.startsWith(" ")) element0 = element0.substring(1);
|
||||
while (element0.endsWith(" ")) element0 = element0.substring(0, element0.length()-1);
|
||||
sortedGroups.put(EnumChatFormat.color(element0.toLowerCase()), index++);
|
||||
sortedGroups.put(EnumChatFormat.color(element0.trim().toLowerCase()), index++);
|
||||
}
|
||||
}
|
||||
return sortedGroups;
|
||||
|
||||
@@ -1,35 +1,3 @@
|
||||
MyAnimation1:
|
||||
change-interval: 100
|
||||
texts:
|
||||
- '&d-&3--------------'
|
||||
- '&3-&d-&3-------------'
|
||||
- '&3--&d-&3------------'
|
||||
- '&3---&d-&3-----------'
|
||||
- '&3----&d-&3----------'
|
||||
- '&3-----&d-&3---------'
|
||||
- '&3------&d-&3--------'
|
||||
- '&3-------&d-&3-------'
|
||||
- '&3--------&d-&3------'
|
||||
- '&3---------&d-&3-----'
|
||||
- '&3----------&d-&3----'
|
||||
- '&3-----------&d-&3---'
|
||||
- '&3------------&d-&3--'
|
||||
- '&3-------------&d-&3-'
|
||||
- '&3--------------&d-'
|
||||
- '&3-------------&d-&3-'
|
||||
- '&3------------&d-&3--'
|
||||
- '&3-----------&d-&3---'
|
||||
- '&3----------&d-&3----'
|
||||
- '&3---------&d-&3-----'
|
||||
- '&3--------&d-&3------'
|
||||
- '&3-------&d-&3-------'
|
||||
- '&3------&d-&3--------'
|
||||
- '&3-----&d-&3---------'
|
||||
- '&3----&d-&3----------'
|
||||
- '&3---&d-&3-----------'
|
||||
- '&3--&d-&3------------'
|
||||
- '&3-&d-&3-------------'
|
||||
- '&d-&3--------------'
|
||||
ServerName:
|
||||
change-interval: 300
|
||||
texts:
|
||||
@@ -97,16 +65,10 @@ Welcome:
|
||||
- '&7&lW_'
|
||||
- '&7&lW_'
|
||||
time:
|
||||
change-interval: 900
|
||||
change-interval: 3000
|
||||
texts:
|
||||
- '&7Time &b%time%'
|
||||
- '&7> Time &b%time% &7<'
|
||||
- '&7>> Time &b%time% &7<<'
|
||||
- '&7>>> Time &b%time% &7<<<'
|
||||
- '&7Date &b%date%'
|
||||
- '&7> Date &b%date% &7<'
|
||||
- '&7>> Date &b%date% &7<<'
|
||||
- '&7>>> Date &b%date% &7<<<'
|
||||
- '&7Time &b%time%'
|
||||
- '&7Date &b%date%'
|
||||
barcolors:
|
||||
change-interval: 1000
|
||||
texts:
|
||||
|
||||
@@ -6,19 +6,19 @@ header-footer:
|
||||
disable-in-servers:
|
||||
- disabledserver
|
||||
header:
|
||||
- "<#FFFFFF>&m </#FFFF00>"
|
||||
- "&3&lServer name"
|
||||
- "&7&l>> %animation:Welcome%&3 &l%player%&7&l! &7&l<<"
|
||||
- "&7Online players: &f%online%"
|
||||
- "&6Online staff: &e%staffonline%"
|
||||
- ""
|
||||
- "%animation:MyAnimation1%"
|
||||
footer:
|
||||
- "%animation:MyAnimation1%"
|
||||
- "%animation:time%"
|
||||
- "&2Ping: %ping%"
|
||||
- "&7&l Used memory: %memory-used% MB / %memory-max% MB"
|
||||
- ""
|
||||
- "&7Visit our webpage %animation:web%"
|
||||
- "<#FFFFFF>&m </#FFFF00>"
|
||||
per-world:
|
||||
world1:
|
||||
header:
|
||||
|
||||
Reference in new issue
Block a user