Compare commits

..
61 Commits
Author SHA1 Message Date
NEZNAMY 48c565d85d 3.1.3 2022-07-28 17:59:15 +02:00
NEZNAMY 86b3cc4044 Sorting - Fix startup error caused by misconfiguration (#664) 2022-07-28 11:40:42 +02:00
NEZNAMY 6a2d5091b8 Bukkit - Add 1.19.1 support 2022-07-28 11:30:34 +02:00
NEZNAMY 4fc139c0c6 Remove synchronized lock from sendCustomPacket method 2022-07-26 21:57:36 +02:00
NEZNAMY e5d800f469 API - Expose a few more methods 2022-07-26 21:56:16 +02:00
NEZNAMY 4879ac28b5 PingSpoof - Add Layout compatibility 2022-07-25 15:34:33 +02:00
NEZNAMY bd0badab48 Feature management - Don't deserialize objective packets if no feature is listening to them 2022-07-24 21:20:55 +02:00
NEZNAMY 5575a26d3b Placeholders - Use event instead of refresh task for %essentialsnick% placeholder 2022-07-24 20:27:43 +02:00
NEZNAMY d8cbe96949 BossBar - Fix issues with hidden-by-default enabled 2022-07-24 17:55:04 +02:00
NEZNAMY cfb506a7ff BossBar - Make Wither's size (nearly) zero on 1.8 (#654) 2022-07-24 13:28:18 +02:00
NEZNAMY 31d259210c Bukkit - Add support for mojang mapped jars 2022-07-21 12:56:23 +02:00
NEZNAMY 39112b8d41 Tab expansion - Add %tab_nametag_visibility% and rename %tab_ntpreview% to %tab_nametag_preview% 2022-07-20 00:14:38 +02:00
NEZNAMY 4c92286ebb Thread management - Increase max thread pool size to 20 2022-07-19 14:02:44 +02:00
NEZNAMY a317aeba85 Plugin message handling - Fix ClassCastException when a placeholder is externally registered as a server placeholder 2022-07-19 13:30:32 +02:00
NEZNAMY dcaf17294e Aligned PlayerList - Fix commit ebd67dd - Do not save config if no changes were made 2022-07-19 12:00:16 +02:00
NEZNAMY 0bc734689a Unlimited Nametags - Fix per-world formatting not applying on world switch 2022-07-19 00:22:11 +02:00
NEZNAMY d0c2c00cc9 BungeeCord - Respect Waterfall's tablist rewrite config option (#652) 2022-07-18 19:25:07 +02:00
NEZNAMY fd02328af9 Aligned PlayerList - Update widths.txt for 1.19 2022-07-18 14:55:05 +02:00
NEZNAMY 3b7de31324 Aligned PlayerList - Add a subcommand (disabled by default) for mass-verifying character widths 2022-07-18 14:52:44 +02:00
NEZNAMY ebd67dd025 Aligned PlayerList - Remove custom widths from config that match default value 2022-07-17 21:30:56 +02:00
NEZNAMY 4557a39ae2 RGB - Fix &r getting removed 2022-07-17 21:29:59 +02:00
NEZNAMY ce1eb299d3 Conditions - Fix conditions being 1 loop behind nested placeholders 2022-07-16 22:58:37 +02:00
Callum Seabrook 20ab3f0a72 Disabled JavaDoc generation for all but API and added property to enable for API 2022-07-16 20:11:58 +01:00
NEZNAMY d61f90c25c Code style - use api module instead of shared where possible 2022-07-16 20:56:59 +02:00
NEZNAMY 90474e7592 Layout - Fix startup error when a layout is missing groups section 2022-07-16 19:15:18 +02:00
NEZNAMY a2e28003bc Code style - Move TabConstants class to api module 2022-07-16 19:13:31 +02:00
NEZNAMY 6e409c3dcd Thread management - Use scheduled executor for repeating and delayed tasks 2022-07-16 18:39:13 +02:00
NEZNAMY 85a699c8de Commands - Only show announcement bars in auto-complete for bossbar announcement command 2022-07-16 18:33:57 +02:00
NEZNAMY a788d1fb23 Commands - Add missing permission check when toggling scoreboard using player argument 2022-07-16 14:14:35 +02:00
NEZNAMY ab5b72375c Code style - Remove redundant suppression and cast 2022-07-13 16:42:36 +02:00
NEZNAMY 3a023c51b5 Catch NoClassDefFoundError which is rarely thrown on reloads and leads to memory leaks 2022-07-13 16:24:17 +02:00
NEZNAMY 0ad91bcafe Sorting - Fix space in sorting types causing it to not work 2022-07-13 15:25:30 +02:00
NEZNAMY f41ea3bcab Unlimited Nametags - Improve heights to match vanilla & remove config option for space between lines, since original value was found 2022-07-13 14:57:07 +02:00
NEZNAMY 327dc4b416 Unlimited Nametags - Fix sneaking not being detected immediately on reload 2022-07-13 14:55:39 +02:00
NEZNAMY 27e7779456 Unlimited Nametags - Do not spawn for <1.8 players 2022-07-13 14:02:33 +02:00
NEZNAMY a7b2f5bb22 BungeeCord - Fix NPE on <1.8 clients 2022-07-13 13:32:53 +02:00
NEZNAMY 19fcb7c946 Layout - Do not send latency update packets to <1.8 clients 2022-07-13 13:32:23 +02:00
NEZNAMY 2706cd5881 Placeholder output replacements - Apply again after applying nested placeholders 2022-07-13 12:17:39 +02:00
NEZNAMY 4e2abd9c5b Bukkit - Fix startup on 1.7.x and 1.8.0 2022-07-13 12:04:21 +02:00
NEZNAMY 51ba2fa80a Placeholder output replacements - Fix exact match detection when input is not colored (new placeholderapi version) 2022-07-11 00:28:14 +02:00
NEZNAMY fd60cd0a21 Change the way the module is disabled 2022-07-06 22:00:52 +02:00
NEZNAMY 5025372c05 Revert "Code style - Remove unused method" 2022-07-06 21:15:54 +02:00
NEZNAMY 4806bd075f Configuration - Fix NPE when disabled world/server is null 2022-07-05 19:09:56 +02:00
NEZNAMY 370d17757a Add poor and unreliable MiniMessage support 2022-07-04 18:06:19 +02:00
NEZNAMY a648d7e75f Scoreboard - Fix NPE when using show command from console without player argument (#639) 2022-07-04 14:05:44 +02:00
NEZNAMY 518e1c5310 AlignedPlayerList - Fix rare NPE caused by multi-thread access 2022-07-04 13:46:29 +02:00
NEZNAMY 11539d8290 Commands - Allow removing per-world/server values 2022-07-04 13:44:08 +02:00
NEZNAMY 073caa9515 Compilation - Bump Authlib version 2022-07-04 13:33:00 +02:00
NEZNAMY 2b06b11916 Scoreboard - Fix same lines of text not appearing with use-numbers true 2022-06-24 21:16:45 +02:00
NEZNAMY 032b0f8a41 Configuration - Fix NPE when copying bukkit config to bungeecord 2022-06-19 14:05:59 +02:00
NEZNAMY 9391363f9b Unlimited Nametags - Disable on boat with chest as well (#625) 2022-06-19 12:36:35 +02:00
NEZNAMY 467fb2e9c7 Bukkit - Use reflection for LibsDisguises hook 2022-06-18 16:12:53 +02:00
NEZNAMY 257893b8de Downgrade dependency to fix compilation 2022-06-18 16:12:09 +02:00
NEZNAMY e919839de5 Merge pull request #623 from JT122406/Updates
Repo Bumps
2022-06-18 14:12:41 +02:00
J.T. McQuigg 77d372cbee Use new RedisBungee 2022-06-18 07:42:38 -04:00
J.T. McQuigg 03e9facaf7 Repo Bumps 2022-06-18 07:35:45 -04:00
NEZNAMY f3e459d911 Revert "BungeeCord - Retry plugin message processing if player isn't loaded for any reason (#564)"
This reverts commit dffac5deb8.
2022-06-17 14:15:39 +02:00
NEZNAMY 36feff0e04 Sorting - Fix off-by-1 possibly causing sorting to not work correctly for players without sorting group/permission 2022-06-16 18:53:42 +02:00
NEZNAMY 0320140a1b BungeeCord - Fix vanish/invisible status not resetting on server switch 2022-06-12 14:16:20 +02:00
NEZNAMY 4fb1b1c9f9 3.1.2 2022-06-11 18:01:17 +02:00
NEZNAMY 37f3896a41 Update to 1.19 2022-06-11 18:01:08 +02:00
144 changed files with 1781 additions and 1257 deletions

No files matched your search

+16
View File
@@ -1,3 +1,7 @@
plugins {
id("net.kyori.blossom") version "1.2.0"
}
dependencies {
compileOnlyApi(libs.netty)
api(libs.jsonSimple) {
@@ -6,4 +10,16 @@ dependencies {
compileOnlyApi(libs.snakeyaml)
api(libs.yamlAssist)
compileOnlyApi(libs.gson)
compileOnlyApi(libs.adventureMiniMessage)
compileOnlyApi(libs.adventureApi)
compileOnlyApi(libs.adventureLegacy)
}
blossom {
replaceToken("@plugin_version@", project.version)
replaceTokenIn("src/main/java/me/neznamy/tab/api/TabConstants.java")
}
tasks.javadoc {
enabled = project.hasProperty("enable-javadoc")
}
@@ -1,5 +1,7 @@
package me.neznamy.tab.api;
import java.util.UUID;
/**
* Feature manager allows registration and work with features.
*/
@@ -41,4 +43,55 @@ public interface FeatureManager {
* @return the feature or null if feature does not exist
*/
TabFeature getFeature(String name);
/**
* Calls onQuit(TabPlayer) to all enabled features
*
* @param disconnectedPlayer
* player who disconnected
*/
void onQuit(TabPlayer disconnectedPlayer);
/**
* Calls onJoin(TabPlayer) to all enabled features
*
* @param connectedPlayer
* player who connected
*/
void onJoin(TabPlayer connectedPlayer);
/**
* Calls onServerChange(TabPlayer, String, String) to all enabled features
*
* @param playerUUID
* player who switched server
* @param to
* name of the new server
*/
void onServerChange(UUID playerUUID, String to);
/**
* Calls onWorldChange(TabPlayer, String, String) to all enabled features
*
* @param playerUUID
* player who switched world
* @param to
* name of the new world
*/
void onWorldChange(UUID playerUUID, String to);
/**
* Calls onCommand(TabPlayer, String) to all enabled features
*
* @param sender
* command sender
* @param command
* command line including /
* @return {@code true} if some feature marked the command for cancel, {@code false} if not
*/
boolean onCommand(TabPlayer sender, String command);
void markObjective();
void markDisplayObjective();
}
@@ -8,6 +8,8 @@ public enum ProtocolVersion {
UNKNOWN_SERVER_VERSION ("Unknown"),
UNKNOWN_CLIENT_VERSION ("Unknown"),
PROXY ("Proxy"),
V1_19_1 (760),
V1_19 (759),
V1_18_2 (758),
V1_18_1 (757),
V1_18 (757),
@@ -204,4 +204,13 @@ public abstract class TabAPI {
* Name of file with syntax error
*/
public abstract void setBrokenFile(String file);
/**
* Returns {@code true} if the plugin is currently disabled due to an error,
* either a yaml syntax error or an internal startup error. Returns {@code false}
* if the plugin is properly running.
*
* @return {@code true} if disabled, {@code false} if running correctly
*/
public abstract boolean isPluginDisabled();
}
@@ -1,4 +1,4 @@
package me.neznamy.tab.shared;
package me.neznamy.tab.api;
/**
* A class containing various constants used everywhere in the plugin
@@ -64,12 +64,16 @@ public abstract class TabFeature {
methodOverrides.add("onWorldChange");
if (getClass().getMethod("onServerChange", TabPlayer.class, String.class, String.class).getDeclaringClass() != TabFeature.class)
methodOverrides.add("onServerChange");
if (getClass().getMethod("onDisplayObjective", TabPlayer.class, PacketPlayOutScoreboardDisplayObjective.class).getDeclaringClass() != TabFeature.class)
if (getClass().getMethod("onDisplayObjective", TabPlayer.class, PacketPlayOutScoreboardDisplayObjective.class).getDeclaringClass() != TabFeature.class) {
methodOverrides.add("onDisplayObjective");
TabAPI.getInstance().getFeatureManager().markDisplayObjective();
}
if (getClass().getMethod("onLoginPacket", TabPlayer.class).getDeclaringClass() != TabFeature.class)
methodOverrides.add("onLoginPacket");
if (getClass().getMethod("onObjective", TabPlayer.class, PacketPlayOutScoreboardObjective.class).getDeclaringClass() != TabFeature.class)
if (getClass().getMethod("onObjective", TabPlayer.class, PacketPlayOutScoreboardObjective.class).getDeclaringClass() != TabFeature.class) {
methodOverrides.add("onObjective");
TabAPI.getInstance().getFeatureManager().markObjective();
}
if (getClass().getMethod("onPlayerInfo", TabPlayer.class, PacketPlayOutPlayerInfo.class).getDeclaringClass() != TabFeature.class)
methodOverrides.add("onPlayerInfo");
if (getClass().getMethod("onPacketReceive", TabPlayer.class, Object.class).getDeclaringClass() != TabFeature.class)
@@ -199,4 +199,12 @@ public interface BossBar {
* @return {@code true} if contains, {@code false} if not
*/
boolean containsPlayer(TabPlayer player);
/**
* Returns {@code true} if this bossbar in configured as announcement-only bar,
* {@code false} if not.
*
* @return {@code true} if bar is announcement only, {@code false} if not
*/
boolean isAnnouncementBar();
}
@@ -424,7 +424,7 @@ public class IChatBaseComponent {
if (text == null) return null;
if (componentCache.containsKey(text)) return componentCache.get(text);
IChatBaseComponent component;
if (text.contains("#") || text.contains("&x") || text.contains(EnumChatFormat.COLOR_CHAR + "x")){
if (text.contains("#") || text.contains("&x") || text.contains(EnumChatFormat.COLOR_CHAR + "x") || text.contains("<")){
//contains RGB colors
component = IChatBaseComponent.fromColoredText(text);
} else {
@@ -1,16 +1,13 @@
package me.neznamy.tab.api.chat.rgb;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import me.neznamy.tab.api.chat.EnumChatFormat;
import me.neznamy.tab.api.chat.TextColor;
import me.neznamy.tab.api.chat.rgb.format.BukkitFormat;
import me.neznamy.tab.api.chat.rgb.format.CMIFormat;
import me.neznamy.tab.api.chat.rgb.format.HtmlFormat;
import me.neznamy.tab.api.chat.rgb.format.KyoriFormat;
import me.neznamy.tab.api.chat.rgb.format.RGBFormatter;
import me.neznamy.tab.api.chat.rgb.format.UnnamedFormat1;
import me.neznamy.tab.api.chat.rgb.format.*;
import me.neznamy.tab.api.chat.rgb.gradient.CMIGradient;
import me.neznamy.tab.api.chat.rgb.gradient.CommonGradient;
import me.neznamy.tab.api.chat.rgb.gradient.GradientPattern;
@@ -41,13 +38,18 @@ public class RGBUtils {
* Constructs new instance and loads all RGB patterns and gradients
*/
public RGBUtils() {
formats = new RGBFormatter[] {
new BukkitFormat(),
new CMIFormat(),
new UnnamedFormat1(),
new HtmlFormat(),
new KyoriFormat()
};
List<RGBFormatter> list = new ArrayList<>();
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[] {
//{#RRGGBB>}text{#RRGGBB<}
new CMIGradient(),
@@ -0,0 +1,22 @@
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 &lt;#RRGGBB>
*/
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));
} catch (Exception ignored) {
return text;
}
}
}
@@ -224,7 +224,7 @@ public abstract class ConfigurationFile {
}
List<String> fixedList = new ArrayList<>();
for (Object key : (List<Object>)value) {
fixedList.add(key.toString());
fixedList.add(String.valueOf(key));
}
return fixedList;
}
@@ -9,4 +9,6 @@ public interface Placeholder {
void enableTriggerMode(Runnable onActivation, Runnable onDisable);
void unload();
boolean isUsed();
}
@@ -48,4 +48,6 @@ public interface PlaceholderManager {
String findReplacement(String placeholder, String output);
List<String> getUsedPlaceholders();
Placeholder getPlaceholder(String identifier);
}
@@ -49,10 +49,20 @@ public interface ThreadManager {
* usage type to add cpu usage to
* @param task
* the task
* @return Future representing the submitted task
*/
RepeatingTask startRepeatingMeasuredTask(int intervalMilliseconds, TabFeature feature, String type, Runnable task);
Future<?> startRepeatingMeasuredTask(int intervalMilliseconds, TabFeature feature, String type, Runnable task);
RepeatingTask startRepeatingTask(int intervalMilliseconds, Runnable task);
/**
* Starts a new task with defined repeat interval
*
* @param intervalMilliseconds
* task interval
* @param task
* the task
* @return Future representing the submitted task
*/
Future<?> startRepeatingTask(int intervalMilliseconds, Runnable task);
/**
* Runs task with a delay and measures how long it took to process
@@ -65,7 +75,18 @@ public interface ThreadManager {
* usage type to add cpu usage to
* @param task
* the task
* @return future allowing to cancel the task
* @return Future representing the submitted task
*/
Future<?> runTaskLater(int delayMilliseconds, TabFeature feature, String type, Runnable task);
/**
* Runs task with a delay
*
* @param delayMilliseconds
* how long to run the task after
* @param task
* the task
* @return Future representing the submitted task
*/
Future<?> runTaskLater(int delayMilliseconds, Runnable task);
}
@@ -13,6 +13,8 @@ tasks {
))
}
javadoc {
// This saves a decent bit of processing power on slow machines
enabled = false
options.encoding = Charsets.UTF_8.name()
(options as StandardJavadocDocletOptions).addStringOption("Xdoclint:none", "-quiet")
}
+1 -1
View File
@@ -12,7 +12,7 @@ val platforms = setOf(
projects.bukkit,
projects.bungeecord,
// projects.krypton,
// projects.velocity
projects.velocity
).map { it.dependencyProject }
val special = setOf(
-1
View File
@@ -6,7 +6,6 @@ dependencies {
compileOnly(libs.vault)
compileOnly(libs.via)
compileOnly(libs.authlib)
compileOnly(libs.libsDisguises)
compileOnly(libs.essentials) {
exclude("org.spigotmc", "spigot-api")
}
@@ -1,5 +1,6 @@
package me.neznamy.tab.platforms.bukkit;
import me.neznamy.tab.api.TabAPI;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
@@ -8,8 +9,6 @@ import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import me.neznamy.tab.shared.TAB;
/**
* The core for bukkit forwarding events into all enabled features
*/
@@ -36,8 +35,8 @@ public class BukkitEventListener implements Listener {
*/
@EventHandler(priority = EventPriority.HIGHEST)
public void onQuit(PlayerQuitEvent e){
if (TAB.getInstance().isDisabled()) return;
TAB.getInstance().getCPUManager().runTask(() -> TAB.getInstance().getFeatureManager().onQuit(TAB.getInstance().getPlayer(e.getPlayer().getUniqueId())));
if (TabAPI.getInstance().isPluginDisabled()) return;
TabAPI.getInstance().getThreadManager().runTask(() -> TabAPI.getInstance().getFeatureManager().onQuit(TabAPI.getInstance().getPlayer(e.getPlayer().getUniqueId())));
}
/**
@@ -48,8 +47,8 @@ public class BukkitEventListener implements Listener {
*/
@EventHandler(priority = EventPriority.LOWEST)
public void onJoin(PlayerJoinEvent e) {
if (TAB.getInstance().isDisabled()) return;
TAB.getInstance().getCPUManager().runTask(() -> TAB.getInstance().getFeatureManager().onJoin(new BukkitTabPlayer(e.getPlayer(), platform.getProtocolVersion(e.getPlayer()))));
if (TabAPI.getInstance().isPluginDisabled()) return;
TabAPI.getInstance().getThreadManager().runTask(() -> TabAPI.getInstance().getFeatureManager().onJoin(new BukkitTabPlayer(e.getPlayer(), platform.getProtocolVersion(e.getPlayer()))));
}
/**
@@ -60,8 +59,8 @@ public class BukkitEventListener implements Listener {
*/
@EventHandler(priority = EventPriority.LOWEST)
public void onWorldChange(PlayerChangedWorldEvent e){
if (TAB.getInstance().isDisabled()) return;
TAB.getInstance().getCPUManager().runTask(() -> TAB.getInstance().getFeatureManager().onWorldChange(e.getPlayer().getUniqueId(), e.getPlayer().getWorld().getName()));
if (TabAPI.getInstance().isPluginDisabled()) return;
TabAPI.getInstance().getThreadManager().runTask(() -> TabAPI.getInstance().getFeatureManager().onWorldChange(e.getPlayer().getUniqueId(), e.getPlayer().getWorld().getName()));
}
/**
@@ -72,7 +71,7 @@ public class BukkitEventListener implements Listener {
*/
@EventHandler
public void onCommand(PlayerCommandPreprocessEvent e) {
if (TAB.getInstance().isDisabled()) return;
if (TAB.getInstance().getFeatureManager().onCommand(TAB.getInstance().getPlayer(e.getPlayer().getUniqueId()), e.getMessage())) e.setCancelled(true);
if (TabAPI.getInstance().isPluginDisabled()) return;
if (TabAPI.getInstance().getFeatureManager().onCommand(TabAPI.getInstance().getPlayer(e.getPlayer().getUniqueId()), e.getMessage())) e.setCancelled(true);
}
}
@@ -1,36 +1,24 @@
package me.neznamy.tab.platforms.bukkit;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import com.mojang.authlib.properties.Property;
import me.neznamy.tab.api.chat.WrappedChatComponent;
import me.neznamy.tab.api.protocol.*;
import org.bukkit.Location;
import org.bukkit.entity.EntityType;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import me.neznamy.tab.api.ProtocolVersion;
import me.neznamy.tab.api.chat.ChatComponentEntity;
import me.neznamy.tab.api.TabAPI;
import me.neznamy.tab.api.chat.EnumChatFormat;
import me.neznamy.tab.api.chat.IChatBaseComponent;
import me.neznamy.tab.api.chat.WrappedChatComponent;
import me.neznamy.tab.api.protocol.*;
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.NMSStorage;
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.*;
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcher;
import org.bukkit.Location;
import org.bukkit.entity.EntityType;
import java.lang.reflect.Array;
import java.util.*;
@SuppressWarnings({"unchecked", "rawtypes"})
public class BukkitPacketBuilder extends PacketBuilder {
@@ -51,9 +39,10 @@ public class BukkitPacketBuilder extends PacketBuilder {
* Constructs new instance
*/
public BukkitPacketBuilder() {
if (nms.getMinorVersion() >= 13) {
if (nms.getMinorVersion() >= 19) {
entityIds.put(EntityType.ARMOR_STAND, 2);
} else if (nms.getMinorVersion() >= 13) {
entityIds.put(EntityType.ARMOR_STAND, 1);
entityIds.put(EntityType.WITHER, 83);
} else {
entityIds.put(EntityType.WITHER, 64);
if (nms.getMinorVersion() >= 8){
@@ -79,18 +68,21 @@ public class BukkitPacketBuilder extends PacketBuilder {
@Override
public Object build(PacketPlayOutChat packet, ProtocolVersion clientVersion) throws ReflectiveOperationException {
Object component = toNMSComponent(packet.getMessage(), clientVersion);
if (nms.getMinorVersion() >= 16) {
if (nms.getMinorVersion() >= 19)
try {
return nms.newPacketPlayOutChat.newInstance(component, packet.getType() == PacketPlayOutChat.ChatMessageType.GAME_INFO);
} catch (Exception e) {
//1.19.0
return nms.newPacketPlayOutChat.newInstance(component, packet.getType().ordinal());
}
if (nms.getMinorVersion() >= 16)
return nms.newPacketPlayOutChat.newInstance(component, nms.ChatMessageType_values[packet.getType().ordinal()], UUID.randomUUID());
}
if (nms.getMinorVersion() >= 12) {
if (nms.getMinorVersion() >= 12)
return nms.newPacketPlayOutChat.newInstance(component, Enum.valueOf((Class<Enum>) nms.ChatMessageType, packet.getType().toString()));
}
if (nms.getMinorVersion() >= 8) {
if (nms.getMinorVersion() >= 8)
return nms.newPacketPlayOutChat.newInstance(component, (byte) packet.getType().ordinal());
}
if (nms.getMinorVersion() == 7) {
if (nms.getMinorVersion() == 7)
return nms.newPacketPlayOutChat.newInstance(component);
}
return packet;
}
@@ -103,13 +95,14 @@ public class BukkitPacketBuilder extends PacketBuilder {
GameProfile profile = new GameProfile(data.getUniqueId(), data.getName());
if (data.getSkin() != null) profile.getProperties().put("textures", new Property("textures", data.getSkin().getValue(), data.getSkin().getSignature()));
List<Object> parameters = new ArrayList<>();
if (nms.newPlayerInfoData.getParameterCount() == 5) {
if (nms.newPlayerInfoData.getParameterTypes()[0] == nms.PacketPlayOutPlayerInfo) {
parameters.add(nmsPacket);
}
parameters.add(profile);
parameters.add(data.getLatency());
parameters.add(data.getGameMode() == null ? null : nms.EnumGamemode_values[nms.EnumGamemode_values.length-EnumGamemode.VALUES.length+data.getGameMode().ordinal()]); //not_set was removed in 1.17
parameters.add(data.getDisplayName() == null ? null : toNMSComponent(data.getDisplayName(), clientVersion));
if (nms.getMinorVersion() >= 19) parameters.add(null);
items.add(nms.newPlayerInfoData.newInstance(parameters.toArray()));
}
nms.setField(nmsPacket, nms.PacketPlayOutPlayerInfo_PLAYERS, items);
@@ -254,7 +247,6 @@ public class BukkitPacketBuilder extends PacketBuilder {
nmsPacket = nms.newPacketPlayOutSpawnEntityLiving.newInstance();
}
nms.setField(nmsPacket, nms.PacketPlayOutSpawnEntityLiving_ENTITYID, packet.getEntityId());
nms.setField(nmsPacket, nms.PacketPlayOutSpawnEntityLiving_ENTITYTYPE, entityIds.get(packet.getEntityType()));
nms.setField(nmsPacket, nms.PacketPlayOutSpawnEntityLiving_YAW, (byte)(packet.getLocation().getYaw() * 256.0f / 360.0f));
nms.setField(nmsPacket, nms.PacketPlayOutSpawnEntityLiving_PITCH, (byte)(packet.getLocation().getPitch() * 256.0f / 360.0f));
if (nms.getMinorVersion() <= 14) {
@@ -270,6 +262,12 @@ public class BukkitPacketBuilder extends PacketBuilder {
nms.setField(nmsPacket, nms.PacketPlayOutSpawnEntityLiving_Y, floor(packet.getLocation().getY()*32));
nms.setField(nmsPacket, nms.PacketPlayOutSpawnEntityLiving_Z, floor(packet.getLocation().getZ()*32));
}
int id = entityIds.get(packet.getEntityType());
if (nms.getMinorVersion() >= 19) {
nms.setField(nmsPacket, nms.PacketPlayOutSpawnEntityLiving_ENTITYTYPE, nms.Registry_a.invoke(nms.IRegistry_X, id));
} else {
nms.setField(nmsPacket, nms.PacketPlayOutSpawnEntityLiving_ENTITYTYPE, id);
}
return nmsPacket;
}
@@ -363,7 +361,7 @@ public class BukkitPacketBuilder extends PacketBuilder {
IChatBaseComponent listName = nmsComponent == null ? null : new WrappedChatComponent(nmsComponent);
Skin skin = null;
if (!profile.getProperties().get("textures").isEmpty()) {
Property pr = (Property) profile.getProperties().get("textures").iterator().next();
Property pr = profile.getProperties().get("textures").iterator().next();
skin = new Skin(pr.getValue(), pr.getSignature());
}
listData.add(new PlayerInfoData(profile.getName(), profile.getId(), skin,
@@ -417,6 +415,7 @@ public class BukkitPacketBuilder extends PacketBuilder {
}
if (packet.getAction() == Action.ADD) {
w.helper().setEntityFlags((byte) 32);
w.helper().setWitherInvulnerableTime(880); // Magic number
return build(new PacketPlayOutSpawnEntityLiving(entityId, new UUID(0, 0), EntityType.WITHER, new Location(null, 0,0,0), w));
} else {
return build(new PacketPlayOutEntityMetadata(entityId, w));
@@ -452,62 +451,7 @@ public class BukkitPacketBuilder extends PacketBuilder {
Map<IChatBaseComponent, Object> cache = clientVersion.getMinorVersion() >= 16 ? componentCacheModern : componentCacheLegacy;
if (cache.containsKey(component)) return cache.get(component);
if (cache.size() > 10000) cache.clear();
Object chat = nms.newChatComponentText.newInstance(component.getText());
Object modifier;
Object clickEvent = component.getModifier().getClickEvent() == null ? null : nms.newChatClickable.newInstance(Enum.valueOf((Class<Enum>) nms.EnumClickAction,
component.getModifier().getClickEvent().getAction().toString().toUpperCase()), component.getModifier().getClickEvent().getValue());
if (nms.getMinorVersion() >= 16) {
Object color = null;
if (component.getModifier().getColor() != null) {
if (clientVersion.getMinorVersion() >= 16) {
color = nms.ChatHexColor_ofInt.invoke(null, (component.getModifier().getColor().getRed() << 16) + (component.getModifier().getColor().getGreen() << 8) + component.getModifier().getColor().getBlue());
} else {
color = nms.ChatHexColor_ofString.invoke(null, component.getModifier().getColor().getLegacyColor().toString().toLowerCase());
}
}
Object hoverEvent = null;
if (component.getModifier().getHoverEvent() != null) {
Object nmsAction = nms.EnumHoverAction_a.invoke(null, component.getModifier().getHoverEvent().getAction().toString().toLowerCase());
switch (component.getModifier().getHoverEvent().getAction()) {
case SHOW_TEXT:
hoverEvent = nms.newChatHoverable.newInstance(nmsAction, toNMSComponent(component.getModifier().getHoverEvent().getValue(), clientVersion));
break;
case SHOW_ENTITY:
hoverEvent = nms.EnumHoverAction_fromJson.invoke(nmsAction, ((ChatComponentEntity) component.getModifier().getHoverEvent().getValue()).toJson());
break;
case SHOW_ITEM:
hoverEvent = nms.EnumHoverAction_fromLegacyComponent.invoke(nmsAction, toNMSComponent(component.getModifier().getHoverEvent().getValue(), clientVersion));
break;
default:
break;
}
}
modifier = nms.newChatModifier.newInstance(
color,
component.getModifier().getBold(),
component.getModifier().getItalic(),
component.getModifier().getUnderlined(),
component.getModifier().getStrikethrough(),
component.getModifier().getObfuscated(),
clickEvent, hoverEvent, null, null);
} else {
modifier = nms.newChatModifier.newInstance();
if (component.getModifier().getColor() != null) nms.setField(modifier, nms.ChatModifier_color, Enum.valueOf((Class<Enum>) nms.EnumChatFormat, component.getModifier().getColor().getLegacyColor().toString()));
nms.setField(modifier, nms.ChatModifier_bold, component.getModifier().getBold());
nms.setField(modifier, nms.ChatModifier_italic, component.getModifier().getItalic());
nms.setField(modifier, nms.ChatModifier_underlined, component.getModifier().getUnderlined());
nms.setField(modifier, nms.ChatModifier_strikethrough, component.getModifier().getStrikethrough());
nms.setField(modifier, nms.ChatModifier_obfuscated, component.getModifier().getObfuscated());
if (clickEvent != null) nms.setField(modifier, nms.ChatModifier_clickEvent, clickEvent);
if (component.getModifier().getHoverEvent() != null) {
nms.setField(modifier, nms.ChatModifier_hoverEvent, nms.newChatHoverable.newInstance(nms.EnumHoverAction_a.invoke(null,
component.getModifier().getHoverEvent().getAction().toString().toLowerCase()), toNMSComponent(component.getModifier().getHoverEvent().getValue(), clientVersion)));
}
}
nms.setField(chat, nms.ChatBaseComponent_modifier, modifier);
for (IChatBaseComponent extra : component.getExtra()) {
nms.ChatComponentText_addSibling.invoke(chat, toNMSComponent(extra, clientVersion));
}
Object chat = nms.ChatSerializer_DESERIALIZE.invoke(null, component.toString(clientVersion));
cache.put(component, chat);
return chat;
}
@@ -523,7 +467,7 @@ public class BukkitPacketBuilder extends PacketBuilder {
*/
private Object newScoreboardObjective(String objectiveName) throws ReflectiveOperationException {
if (nms.getMinorVersion() >= 13) {
return nms.newScoreboardObjective.newInstance(null, objectiveName, null, nms.newChatComponentText.newInstance(""), null);
return nms.newScoreboardObjective.newInstance(null, objectiveName, null, toNMSComponent(new IChatBaseComponent(""), TabAPI.getInstance().getServerVersion()), null);
}
return nms.newScoreboardObjective.newInstance(null, objectiveName, nms.IScoreboardCriteria_self.get(null));
}
@@ -10,7 +10,7 @@ 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.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.features.PipelineInjector;
import org.jetbrains.annotations.NotNull;
@@ -5,9 +5,16 @@ import java.lang.reflect.Method;
import java.text.NumberFormat;
import java.util.Locale;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.api.placeholder.PlayerPlaceholder;
import me.neznamy.tab.shared.TAB;
import net.ess3.api.events.NickChangeEvent;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.RegisteredServiceProvider;
@@ -16,6 +23,7 @@ import com.earth2me.essentials.Essentials;
import me.neznamy.tab.api.placeholder.PlaceholderManager;
import me.neznamy.tab.shared.placeholders.UniversalPlaceholderRegistry;
import net.milkbowl.vault.chat.Chat;
import org.bukkit.plugin.java.JavaPlugin;
/**
* Bukkit registry to register bukkit-only and universal placeholders
@@ -25,7 +33,8 @@ public class BukkitPlaceholderRegistry extends UniversalPlaceholderRegistry {
/** Number formatter for 2 decimal places */
private final NumberFormat numberFormat = NumberFormat.getNumberInstance(Locale.US);
private Object chat; // Object because Fabric
private final JavaPlugin plugin;
private Chat chat;
private final Plugin essentials = Bukkit.getPluginManager().getPlugin(TabConstants.Plugin.ESSENTIALS);
private Object server;
private Field recentTps;
@@ -33,13 +42,11 @@ public class BukkitPlaceholderRegistry extends UniversalPlaceholderRegistry {
private Method paperMspt;
private Method purpurIsAfk;
/**
* Constructs new instance with given parameter
*/
public BukkitPlaceholderRegistry() {
public BukkitPlaceholderRegistry(JavaPlugin plugin) {
this.plugin = plugin;
numberFormat.setMaximumFractionDigits(2);
if (Bukkit.getPluginManager().isPluginEnabled(TabConstants.Plugin.VAULT)) {
RegisteredServiceProvider<?> rspChat = Bukkit.getServicesManager().getRegistration(Chat.class);
RegisteredServiceProvider<Chat> rspChat = Bukkit.getServicesManager().getRegistration(Chat.class);
if (rspChat != null) chat = rspChat.getProvider();
}
try {
@@ -78,15 +85,29 @@ public class BukkitPlaceholderRegistry extends UniversalPlaceholderRegistry {
if (essentials != null && ((Essentials)essentials).getUser(p.getUniqueId()).isAfk()) return true;
return purpurIsAfk != null && ((Player)p.getPlayer()).isAfk();
});
manager.registerPlayerPlaceholder(TabConstants.Placeholder.ESSENTIALS_NICK, 1000, p -> {
String nickname = null;
if (essentials != null)
nickname = ((Essentials)essentials).getUser(p.getUniqueId()).getNickname();
return nickname == null || nickname.length() == 0 ? p.getName() : nickname;
});
if (essentials != null) {
PlayerPlaceholder nick = manager.registerPlayerPlaceholder(TabConstants.Placeholder.ESSENTIALS_NICK, -1, p -> {
String nickname = ((Essentials)essentials).getUser(p.getUniqueId()).getNickname();
return nickname == null ? p.getName() : nickname;
});
Listener nickListener = new Listener() {
@EventHandler
public void onNickChange(NickChangeEvent e) {
String name = e.getValue() == null ? e.getAffected().getName() : e.getValue();
TabPlayer player = TAB.getInstance().getPlayer(e.getAffected().getUUID());
if (player == null) return;
nick.updateValue(player, name);
}
};
nick.enableTriggerMode(() -> Bukkit.getPluginManager().registerEvents(nickListener, plugin),
() -> HandlerList.unregisterAll(nickListener));
} else {
manager.registerPlayerPlaceholder(TabConstants.Placeholder.ESSENTIALS_NICK, -1, TabPlayer::getName);
}
if (chat != null) {
manager.registerPlayerPlaceholder(TabConstants.Placeholder.VAULT_PREFIX, 1000, p -> ((Chat) chat).getPlayerPrefix((Player) p.getPlayer()));
manager.registerPlayerPlaceholder(TabConstants.Placeholder.VAULT_SUFFIX, 1000, p -> ((Chat) chat).getPlayerSuffix((Player) p.getPlayer()));
manager.registerPlayerPlaceholder(TabConstants.Placeholder.VAULT_PREFIX, 1000, p -> chat.getPlayerPrefix((Player) p.getPlayer()));
manager.registerPlayerPlaceholder(TabConstants.Placeholder.VAULT_SUFFIX, 1000, p -> chat.getPlayerSuffix((Player) p.getPlayer()));
} else {
manager.registerServerPlaceholder(TabConstants.Placeholder.VAULT_PREFIX, -1, () -> "");
manager.registerServerPlaceholder(TabConstants.Placeholder.VAULT_SUFFIX, -1, () -> "");
@@ -15,7 +15,7 @@ import me.neznamy.tab.platforms.bukkit.features.unlimitedtags.BukkitNameTagX;
import me.neznamy.tab.platforms.bukkit.permission.Vault;
import me.neznamy.tab.shared.Platform;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
import me.neznamy.tab.shared.features.PlaceholderManagerImpl;
import me.neznamy.tab.shared.features.bossbar.BossBarManagerImpl;
import me.neznamy.tab.shared.features.nametags.NameTag;
@@ -86,7 +86,7 @@ public class BukkitPlatform extends Platform {
TAB tab = TAB.getInstance();
if (tab.getConfiguration().isPipelineInjection())
tab.getFeatureManager().registerFeature(TabConstants.Feature.PIPELINE_INJECTION, new BukkitPipelineInjector());
new BukkitPlaceholderRegistry().registerPlaceholders(tab.getPlaceholderManager());
new BukkitPlaceholderRegistry(plugin).registerPlaceholders(tab.getPlaceholderManager());
if (tab.getConfiguration().getConfig().getBoolean("scoreboard-teams.enabled", true)) {
if (tab.getConfiguration().getConfig().getBoolean("scoreboard-teams.unlimited-nametag-mode.enabled", false) && tab.getServerVersion().getMinorVersion() >= 8) {
tab.getFeatureManager().registerFeature(TabConstants.Feature.UNLIMITED_NAME_TAGS, new BukkitNameTagX(plugin));
@@ -11,6 +11,7 @@ import org.bukkit.boss.BarColor;
import org.bukkit.boss.BarFlag;
import org.bukkit.boss.BarStyle;
import org.bukkit.boss.BossBar;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.metadata.MetadataValue;
import org.bukkit.potion.PotionEffectType;
@@ -23,7 +24,6 @@ import com.viaversion.viaversion.api.legacy.bossbar.BossFlag;
import com.viaversion.viaversion.api.legacy.bossbar.BossStyle;
import io.netty.channel.Channel;
import me.libraryaddict.disguise.DisguiseAPI;
import me.neznamy.tab.api.chat.rgb.RGBUtils;
import me.neznamy.tab.api.protocol.PacketPlayOutBoss;
import me.neznamy.tab.platforms.bukkit.nms.NMSStorage;
@@ -56,7 +56,7 @@ public class BukkitTabPlayer extends ITabPlayer {
* Player's protocol network id
*/
public BukkitTabPlayer(Player p, int protocolVersion){
super(p, p.getUniqueId(), p.getName(), "N/A", p.getWorld().getName(), protocolVersion);
super(p, p.getUniqueId(), p.getName(), "N/A", p.getWorld().getName(), protocolVersion, true);
try {
handle = NMSStorage.getInstance().getHandle.invoke(player);
playerConnection = NMSStorage.getInstance().PLAYER_CONNECTION.get(handle);
@@ -243,8 +243,8 @@ public class BukkitTabPlayer extends ITabPlayer {
public boolean isDisguised() {
try {
if (!((BukkitPlatform)TAB.getInstance().getPlatform()).isLibsDisguisesEnabled()) return false;
return DisguiseAPI.isDisguised(getPlayer());
} catch (LinkageError e) {
return (boolean) Class.forName("me.libraryaddict.disguise.DisguiseAPI").getMethod("isDisguised", Entity.class).invoke(null, getPlayer());
} catch (LinkageError | ReflectiveOperationException e) {
//java.lang.NoClassDefFoundError: Could not initialize class me.libraryaddict.disguise.DisguiseAPI
TAB.getInstance().getErrorManager().printError("Failed to check disguise status using LibsDisguises", e);
((BukkitPlatform)TAB.getInstance().getPlatform()).setLibsDisguisesEnabled(false);
@@ -252,7 +252,6 @@ public class BukkitTabPlayer extends ITabPlayer {
}
}
@SuppressWarnings("unchecked")
@Override
public Skin getSkin() {
try {
@@ -5,6 +5,8 @@ import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import me.neznamy.tab.api.TabAPI;
import me.neznamy.tab.platforms.bukkit.nms.*;
import org.bstats.bukkit.Metrics;
import org.bstats.charts.SimplePie;
import org.bukkit.Bukkit;
@@ -14,9 +16,8 @@ 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.platforms.bukkit.nms.NMSStorage;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
import org.jetbrains.annotations.NotNull;
/**
@@ -70,23 +71,33 @@ public class Main extends JavaPlugin {
"v1_5_R1", "v1_5_R2", "v1_5_R3", "v1_6_R1", "v1_6_R2", "v1_6_R3",
"v1_7_R1", "v1_7_R2", "v1_7_R3", "v1_7_R4", "v1_8_R1", "v1_8_R2", "v1_8_R3",
"v1_9_R1", "v1_9_R2", "v1_10_R1", "v1_11_R1", "v1_12_R1", "v1_13_R1", "v1_13_R2",
"v1_14_R1", "v1_15_R1", "v1_16_R1", "v1_16_R2", "v1_16_R3", "v1_17_R1", "v1_18_R1", "v1_18_R2");
"v1_14_R1", "v1_15_R1", "v1_16_R1", "v1_16_R2", "v1_16_R3", "v1_17_R1", "v1_18_R1",
"v1_18_R2", "v1_19_R1");
String serverPackage = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
try {
long time = System.currentTimeMillis();
NMSStorage.setInstance(new NMSStorage());
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());
}
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.x - 1.18.2. Disabling just to stay safe."));
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.x - 1.19. Disabling just to stay safe."));
}
} catch (Exception 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);
} else {
Bukkit.getConsoleSender().sendMessage(EnumChatFormat.color("&c[TAB] Your server version is completely unsupported. This plugin version only supports 1.5.x - 1.18.2. Disabling."));
Bukkit.getConsoleSender().sendMessage(EnumChatFormat.color("&c[TAB] Your server version is completely unsupported. This plugin version only supports 1.5.x - 1.19. Disabling."));
}
}
return false;
@@ -99,7 +110,7 @@ public class Main extends JavaPlugin {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) {
if (TAB.getInstance().isDisabled()) {
if (TabAPI.getInstance().isPluginDisabled()) {
for (String message : TAB.getInstance().getDisabledCommand().execute(args, sender.hasPermission(TabConstants.Permission.COMMAND_RELOAD), sender.hasPermission(TabConstants.Permission.COMMAND_ALL))) {
sender.sendMessage(EnumChatFormat.color(message));
}
@@ -2,9 +2,10 @@ package me.neznamy.tab.platforms.bukkit.features;
import me.clip.placeholderapi.PlaceholderAPI;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
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.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.shared.features.TabExpansion;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
@@ -46,13 +47,13 @@ public class BukkitTabExpansion extends PlaceholderExpansion implements TabExpan
if (identifier.startsWith("replace_")) {
String placeholder = "%" + identifier.substring(8) + "%";
String output = PlaceholderAPI.setPlaceholders(player, placeholder);
return TAB.getInstance().getPlaceholderManager().findReplacement(placeholder, output);
return TabAPI.getInstance().getPlaceholderManager().findReplacement(placeholder, output);
}
if (identifier.startsWith("placeholder_")) {
TAB.getInstance().getPlaceholderManager().addUsedPlaceholder("%" + identifier.substring(12) + "%", TAB.getInstance().getPlaceholderManager());
TabAPI.getInstance().getPlaceholderManager().addUsedPlaceholder("%" + identifier.substring(12) + "%", (TabFeature) TabAPI.getInstance().getPlaceholderManager());
}
if (player == null) return "<Player cannot be null>";
TabPlayer p = TAB.getInstance().getPlayer(player.getUniqueId());
TabPlayer p = TabAPI.getInstance().getPlayer(player.getUniqueId());
if (p == null || !p.isLoaded()) return "<Player is not loaded>";
return values.get(p).get(identifier);
}
@@ -5,6 +5,7 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import me.neznamy.tab.api.TabAPI;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@@ -15,7 +16,7 @@ import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.plugin.java.JavaPlugin;
import me.neznamy.tab.api.TabFeature;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
import me.neznamy.tab.shared.TAB;
/**
@@ -28,9 +29,9 @@ public class PerWorldPlayerList extends TabFeature implements Listener {
private final JavaPlugin plugin;
//config options
private final boolean allowBypass = TAB.getInstance().getConfiguration().getConfig().getBoolean("per-world-playerlist.allow-bypass-permission", false);
private final List<String> ignoredWorlds = TAB.getInstance().getConfiguration().getConfig().getStringList("per-world-playerlist.ignore-effect-in-worlds", Arrays.asList("ignoredworld", "build"));
private final Map<String, List<String>> sharedWorlds = TAB.getInstance().getConfiguration().getConfig().getConfigurationSection("per-world-playerlist.shared-playerlist-world-groups");
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"));
private final Map<String, List<String>> sharedWorlds = TabAPI.getInstance().getConfig().getConfigurationSection("per-world-playerlist.shared-playerlist-world-groups");
/**
* Constructs new instance with given parameters and loads config options
@@ -41,7 +42,7 @@ public class PerWorldPlayerList extends TabFeature implements Listener {
public PerWorldPlayerList(JavaPlugin plugin) {
super("Per world PlayerList", null);
this.plugin = plugin;
TAB.getInstance().debug(String.format("Loaded PerWorldPlayerList feature with parameters allowBypass=%s, ignoredWorlds=%s, sharedWorlds=%s", allowBypass, ignoredWorlds, sharedWorlds));
TabAPI.getInstance().debug(String.format("Loaded PerWorldPlayerList feature with parameters allowBypass=%s, ignoredWorlds=%s, sharedWorlds=%s", allowBypass, ignoredWorlds, sharedWorlds));
Bukkit.getPluginManager().registerEvents(this, plugin);
}
@@ -1,13 +1,16 @@
package me.neznamy.tab.platforms.bukkit.features;
import java.util.*;
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.datawatcher.DataWatcher;
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcherItem;
import me.neznamy.tab.shared.TAB;
import java.util.ConcurrentModificationException;
import java.util.List;
import java.util.Optional;
import java.util.WeakHashMap;
/**
* A feature to disable minecraft 1.9+ feature making tamed animals
@@ -45,7 +48,7 @@ public class PetFix extends TabFeature {
*/
public PetFix() {
super("Pet name fix", null);
TAB.getInstance().debug("Loaded PetFix feature");
TabAPI.getInstance().debug("Loaded PetFix feature");
}
/**
@@ -55,7 +58,7 @@ public class PetFix extends TabFeature {
*/
private int getPetOwnerPosition() {
if (nms.getMinorVersion() >= 17) {
//1.17.x, 1.18.x
//1.17.x, 1.18.x, 1.19.x
return 18;
} else if (nms.getMinorVersion() >= 15) {
//1.15.x, 1.16.x
@@ -12,7 +12,7 @@ import org.bukkit.plugin.java.JavaPlugin;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.api.bossbar.BossBar;
import me.neznamy.tab.platforms.bukkit.nms.PacketPlayOutEntityTeleport;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.features.bossbar.BossBarManagerImpl;
@@ -1,16 +1,6 @@
package me.neznamy.tab.platforms.bukkit.features.unlimitedtags;
import java.util.UUID;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.entity.Pose;
import me.neznamy.tab.api.ArmorStand;
import me.neznamy.tab.api.Property;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.api.*;
import me.neznamy.tab.api.chat.EnumChatFormat;
import me.neznamy.tab.api.chat.IChatBaseComponent;
import me.neznamy.tab.api.protocol.TabPacket;
@@ -19,8 +9,13 @@ 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 me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.shared.TAB;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.entity.Pose;
import java.util.UUID;
/**
* A class representing an armor stand attached to a player (if the feature is enabled)
@@ -31,7 +26,7 @@ public class BukkitArmorStand implements ArmorStand {
private static int idCounter = 2000000000;
//NameTag feature
private final BukkitNameTagX manager = (BukkitNameTagX) TAB.getInstance().getFeatureManager().getFeature(TabConstants.Feature.UNLIMITED_NAME_TAGS);
private final BukkitNameTagX manager = (BukkitNameTagX) TabAPI.getInstance().getFeatureManager().getFeature(TabConstants.Feature.UNLIMITED_NAME_TAGS);
private final BukkitArmorStandManager asm;
@@ -73,6 +68,7 @@ public class BukkitArmorStand implements ArmorStand {
this.yOffset = yOffset;
this.property = owner.getProperty(propertyName);
visible = getVisibility();
sneaking = player.isSneaking();
}
@Override
@@ -204,20 +200,28 @@ public class BukkitArmorStand implements ArmorStand {
/**
* Returns general location where armor stand should be at time of calling
*
* @param viewer
* Player looking at the armor stand
* @return Location where armor stand should be for everyone
*/
public Location getLocation() {
public Location getLocation(TabPlayer viewer) {
double x = player.getLocation().getX();
double y = getY() + yOffset + 2;
double y = getY() + yOffset;
double z = player.getLocation().getZ();
if (player.isSleeping()) {
y -= 1.76;
} else {
if (TAB.getInstance().getServerVersion().getMinorVersion() >= 9) {
y -= (sneaking ? 0.45 : 0.18);
if (!player.isSleeping()) {
if (sneaking) {
if (viewer.getVersion().getMinorVersion() >= 15) {
y += 1.37;
} else if (viewer.getVersion().getMinorVersion() >= 9) {
y += 1.52;
} else {
y += 1.7;
}
} else {
y -= (sneaking ? 0.30 : 0.18);
y += viewer.getVersion().getMinorVersion() >= 9 ? 1.8 : 1.84; // Normal
}
} else {
y += viewer.getVersion().getMinorVersion() >= 9 ? 0.2 : 0.26; // Sleeping
}
return new Location(null,x,y,z);
}
@@ -245,15 +249,15 @@ public class BukkitArmorStand implements ArmorStand {
}
}
//1.13+ swimming or 1.9+ flying with elytra
if (isSwimming() || (TAB.getInstance().getServerVersion().getMinorVersion() >= 9 && player.isGliding())) {
if (isSwimming() || (TabAPI.getInstance().getServerVersion().getMinorVersion() >= 9 && player.isGliding())) {
return player.getLocation().getY()-1.22;
}
return player.getLocation().getY();
}
private boolean isSwimming() {
if (TAB.getInstance().getServerVersion().getMinorVersion() >= 14 && player.getPose() == Pose.SWIMMING) return true;
return TAB.getInstance().getServerVersion().getMinorVersion() == 13 && player.isSwimming();
if (TabAPI.getInstance().getServerVersion().getMinorVersion() >= 14 && player.getPose() == Pose.SWIMMING) return true;
return TabAPI.getInstance().getServerVersion().getMinorVersion() == 13 && player.isSwimming();
}
/**
@@ -311,7 +315,7 @@ public class BukkitArmorStand implements ArmorStand {
public TabPacket[] getSpawnPackets(TabPlayer viewer) {
visible = getVisibility();
DataWatcher dataWatcher = createDataWatcher(property.getFormat(viewer), viewer);
if (TAB.getInstance().getServerVersion().getMinorVersion() >= 15) {
if (TabAPI.getInstance().getServerVersion().getMinorVersion() >= 15) {
return new TabPacket[] {
new PacketPlayOutSpawnEntityLiving(entityId, uuid, EntityType.ARMOR_STAND, getArmorStandLocationFor(viewer), null),
new PacketPlayOutEntityMetadata(entityId, dataWatcher)
@@ -331,7 +335,7 @@ public class BukkitArmorStand implements ArmorStand {
* @return location of armor stand
*/
public Location getArmorStandLocationFor(TabPlayer viewer) {
return viewer.getVersion().getMinorVersion() == 8 && !manager.isMarkerFor18x() ? getLocation().clone().add(0,-2,0) : getLocation();
return viewer.getVersion().getMinorVersion() == 8 && !manager.isMarkerFor18x() ? getLocation(viewer).add(0,-2,0) : getLocation(viewer);
}
@Override
@@ -3,7 +3,7 @@ package me.neznamy.tab.platforms.bukkit.features.unlimitedtags;
import me.neznamy.tab.api.ArmorStand;
import me.neznamy.tab.api.ArmorStandManager;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
import me.neznamy.tab.shared.features.nametags.unlimited.NameTagX;
import java.util.ArrayList;
@@ -16,7 +16,6 @@ import java.util.Map;
*/
public class BukkitArmorStandManager implements ArmorStandManager {
private final NameTagX nameTagX;
//map of registered armor stands
private final Map<String, ArmorStand> armorStands = new LinkedHashMap<>();
@@ -29,14 +28,13 @@ public class BukkitArmorStandManager implements ArmorStandManager {
private TabPlayer[] nearbyPlayerArray = new TabPlayer[0];
public BukkitArmorStandManager(NameTagX nameTagX, TabPlayer owner) {
this.nameTagX = nameTagX;
owner.setProperty(nameTagX, TabConstants.Property.NAMETAG, owner.getProperty(TabConstants.Property.TAGPREFIX).getCurrentRawValue()
+ owner.getProperty(TabConstants.Property.CUSTOMTAGNAME).getCurrentRawValue()
+ owner.getProperty(TabConstants.Property.TAGSUFFIX).getCurrentRawValue());
double height = 0;
for (String line : nameTagX.getDynamicLines()) {
addArmorStand(line, new BukkitArmorStand(this, owner, line, height, false));
height += nameTagX.getSpaceBetweenLines();
height += 0.26;
}
for (Map.Entry<String, Object> line : nameTagX.getStaticLines().entrySet()) {
addArmorStand(line.getKey(), new BukkitArmorStand(this, owner, line.getKey(), Double.parseDouble(line.getValue().toString()), true));
@@ -134,11 +132,11 @@ public class BukkitArmorStandManager implements ArmorStandManager {
* Fixes heights of all armor stands due to dynamic lines
*/
public void fixArmorStandHeights() {
double currentY = -nameTagX.getSpaceBetweenLines();
double currentY = -0.26;
for (ArmorStand as : armorStandArray) {
if (as.hasStaticOffset()) continue;
if (as.getProperty().get().length() != 0) {
currentY += nameTagX.getSpaceBetweenLines();
currentY += 0.26;
as.setOffset(currentY);
}
}
@@ -1,8 +1,8 @@
package me.neznamy.tab.platforms.bukkit.features.unlimitedtags;
import me.neznamy.tab.api.TabAPI;
import me.neznamy.tab.api.TabConstants;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.shared.features.nametags.unlimited.NameTagX;
import org.bukkit.Bukkit;
import org.bukkit.Location;
@@ -29,16 +29,16 @@ public class BukkitNameTagX extends NameTagX {
public BukkitNameTagX(JavaPlugin plugin) {
super(BukkitArmorStandManager::new);
Bukkit.getPluginManager().registerEvents(eventListener, plugin);
TAB.getInstance().getFeatureManager().registerFeature(TabConstants.Feature.UNLIMITED_NAME_TAGS_PACKET_LISTENER, new PacketListener(this));
TAB.getInstance().getFeatureManager().registerFeature(TabConstants.Feature.UNLIMITED_NAME_TAGS_VEHICLE_REFRESHER, vehicleManager);
TabAPI.getInstance().getFeatureManager().registerFeature(TabConstants.Feature.UNLIMITED_NAME_TAGS_PACKET_LISTENER, new PacketListener(this));
TabAPI.getInstance().getFeatureManager().registerFeature(TabConstants.Feature.UNLIMITED_NAME_TAGS_VEHICLE_REFRESHER, vehicleManager);
}
@Override
public void load() {
super.load();
for (TabPlayer all : TAB.getInstance().getOnlinePlayers()) {
for (TabPlayer all : TabAPI.getInstance().getOnlinePlayers()) {
if (isPlayerDisabled(all)) continue;
for (TabPlayer viewer : TAB.getInstance().getOnlinePlayers()) {
for (TabPlayer viewer : TabAPI.getInstance().getOnlinePlayers()) {
spawnArmorStands(viewer, all);
}
}
@@ -46,9 +46,9 @@ public class BukkitNameTagX extends NameTagX {
}
private void startVisibilityRefreshTask() {
TAB.getInstance().getCPUManager().startRepeatingMeasuredTask(500, this, TabConstants.CpuUsageCategory.REFRESHING_NAME_TAG_VISIBILITY, () -> {
TabAPI.getInstance().getThreadManager().startRepeatingMeasuredTask(500, this, TabConstants.CpuUsageCategory.REFRESHING_NAME_TAG_VISIBILITY, () -> {
for (TabPlayer p : TAB.getInstance().getOnlinePlayers()) {
for (TabPlayer p : TabAPI.getInstance().getOnlinePlayers()) {
if (isPlayerDisabled(p)) continue;
getArmorStandManager(p).updateVisibility(false);
}
@@ -65,7 +65,7 @@ public class BukkitNameTagX extends NameTagX {
public void onJoin(TabPlayer connectedPlayer) {
super.onJoin(connectedPlayer);
if (isPlayerDisabled(connectedPlayer)) return;
for (TabPlayer viewer : TAB.getInstance().getOnlinePlayers()) {
for (TabPlayer viewer : TabAPI.getInstance().getOnlinePlayers()) {
spawnArmorStands(viewer, connectedPlayer);
spawnArmorStands(connectedPlayer, viewer);
}
@@ -77,6 +77,7 @@ public class BukkitNameTagX extends NameTagX {
}
private void spawnArmorStands(TabPlayer viewer, TabPlayer target) {
if (viewer.getVersion().getMinorVersion() < 8) return;
if (target == viewer || isPlayerDisabled(target)) return;
if (((Player) viewer.getPlayer()).getWorld() != ((Player) target.getPlayer()).getWorld()) return;
if (getDistance(viewer, target) <= 48 && ((Player)viewer.getPlayer()).canSee((Player)target.getPlayer()) && !target.isVanished())
@@ -95,7 +96,7 @@ public class BukkitNameTagX extends NameTagX {
@Override
public void resumeArmorStands(TabPlayer player) {
if (isPlayerDisabled(player)) return;
for (TabPlayer viewer : TAB.getInstance().getOnlinePlayers()) {
for (TabPlayer viewer : TabAPI.getInstance().getOnlinePlayers()) {
spawnArmorStands(viewer, player);
}
}
@@ -107,7 +108,7 @@ public class BukkitNameTagX extends NameTagX {
@Override
public void updateNameTagVisibilityView(TabPlayer player) {
for (TabPlayer all : TAB.getInstance().getOnlinePlayers()) {
for (TabPlayer all : TabAPI.getInstance().getOnlinePlayers()) {
getArmorStandManager(all).updateVisibility(true);
}
}
@@ -115,7 +116,7 @@ public class BukkitNameTagX extends NameTagX {
@Override
public void onQuit(TabPlayer disconnectedPlayer) {
super.onQuit(disconnectedPlayer);
for (TabPlayer all : TAB.getInstance().getOnlinePlayers()) {
for (TabPlayer all : TabAPI.getInstance().getOnlinePlayers()) {
getArmorStandManager(all).unregisterPlayer(disconnectedPlayer);
}
armorStandManagerMap.get(disconnectedPlayer).destroy();
@@ -135,7 +136,7 @@ public class BukkitNameTagX extends NameTagX {
getArmorStandManager(p).spawn(p);
}
//for some reason this is needed for some users
for (TabPlayer viewer : TAB.getInstance().getOnlinePlayers()) {
for (TabPlayer viewer : TabAPI.getInstance().getOnlinePlayers()) {
if (viewer.getWorld().equals(from)) {
getArmorStandManager(p).destroy(viewer);
}
@@ -1,15 +1,14 @@
package me.neznamy.tab.platforms.bukkit.features.unlimitedtags;
import me.neznamy.tab.api.TabAPI;
import me.neznamy.tab.api.TabConstants;
import me.neznamy.tab.api.TabPlayer;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.event.player.PlayerToggleSneakEvent;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.shared.TAB;
/**
* The event listener part for securing proper functionality of armor stands
*/
@@ -36,9 +35,9 @@ public class EventListener implements Listener {
*/
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onSneak(PlayerToggleSneakEvent e) {
TabPlayer p = TAB.getInstance().getPlayer(e.getPlayer().getUniqueId());
TabPlayer p = TabAPI.getInstance().getPlayer(e.getPlayer().getUniqueId());
if (p == null || feature.isPlayerDisabled(p)) return;
TAB.getInstance().getCPUManager().runMeasuredTask(feature, TabConstants.CpuUsageCategory.PLAYER_SNEAK, () -> feature.getArmorStandManager(p).sneak(e.isSneaking()));
TabAPI.getInstance().getThreadManager().runMeasuredTask(feature, TabConstants.CpuUsageCategory.PLAYER_SNEAK, () -> feature.getArmorStandManager(p).sneak(e.isSneaking()));
}
/**
@@ -49,8 +48,8 @@ public class EventListener implements Listener {
*/
@EventHandler
public void onRespawn(PlayerRespawnEvent e) {
TAB.getInstance().getCPUManager().runMeasuredTask(feature, TabConstants.CpuUsageCategory.PLAYER_RESPAWN, () -> {
TabPlayer respawned = TAB.getInstance().getPlayer(e.getPlayer().getUniqueId());
TabAPI.getInstance().getThreadManager().runMeasuredTask(feature, TabConstants.CpuUsageCategory.PLAYER_RESPAWN, () -> {
TabPlayer respawned = TabAPI.getInstance().getPlayer(e.getPlayer().getUniqueId());
if (feature.isPlayerDisabled(respawned)) return;
feature.getArmorStandManager(respawned).teleport();
});
@@ -1,18 +1,17 @@
package me.neznamy.tab.platforms.bukkit.features.unlimitedtags;
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 org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import me.neznamy.tab.api.TabFeature;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.platforms.bukkit.nms.NMSStorage;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.shared.TAB;
/**
* The packet listening part for securing proper functionality of armor stands
* Bukkit events are too unreliable and delayed/ahead which causes de-sync
@@ -41,7 +40,7 @@ public class PacketListener extends TabFeature {
@Override
public void load() {
for (TabPlayer all : TAB.getInstance().getOnlinePlayers()) {
for (TabPlayer all : TabAPI.getInstance().getOnlinePlayers()) {
entityIdMap.put(((Player) all.getPlayer()).getEntityId(), all);
}
}
@@ -61,7 +60,7 @@ public class PacketListener extends TabFeature {
if (sender.getVersion().getMinorVersion() == 8 && nms.PacketPlayInUseEntity.isInstance(packet)) {
int entityId = nms.PacketPlayInUseEntity_ENTITY.getInt(packet);
TabPlayer attacked = null;
for (TabPlayer all : TAB.getInstance().getOnlinePlayers()) {
for (TabPlayer all : TabAPI.getInstance().getOnlinePlayers()) {
if (all.isLoaded() && nameTagX.getArmorStandManager(all).hasArmorStandWithID(entityId)) {
attacked = all;
break;
@@ -114,14 +113,14 @@ public class PacketListener extends TabFeature {
if (pl != null) {
//player moved
if (nameTagX.isPlayerDisabled(pl) || !pl.isLoaded()) return;
TAB.getInstance().getCPUManager().runMeasuredTask(nameTagX, TabConstants.CpuUsageCategory.PACKET_ENTITY_MOVE,
TabAPI.getInstance().getThreadManager().runMeasuredTask(nameTagX, TabConstants.CpuUsageCategory.PACKET_ENTITY_MOVE,
() -> nameTagX.getArmorStandManager(pl).teleport(receiver));
} else if ((vehicleList = nameTagX.getVehicleManager().getVehicles().get(entityId)) != null){
//a vehicle carrying something moved
for (Entity entity : vehicleList) {
TabPlayer passenger = entityIdMap.get(entity.getEntityId());
if (passenger != null && nameTagX.getArmorStandManager(passenger) != null) {
TAB.getInstance().getCPUManager().runMeasuredTask(nameTagX, TabConstants.CpuUsageCategory.PACKET_ENTITY_MOVE_PASSENGER,
TabAPI.getInstance().getThreadManager().runMeasuredTask(nameTagX, TabConstants.CpuUsageCategory.PACKET_ENTITY_MOVE_PASSENGER,
() -> nameTagX.getArmorStandManager(passenger).teleport(receiver));
}
}
@@ -131,7 +130,7 @@ public class PacketListener extends TabFeature {
private void onEntitySpawn(TabPlayer receiver, int entityId) {
TabPlayer spawnedPlayer = entityIdMap.get(entityId);
if (spawnedPlayer != null && spawnedPlayer.isLoaded() && !nameTagX.isPlayerDisabled(spawnedPlayer)) {
TAB.getInstance().getCPUManager().runMeasuredTask(nameTagX, TabConstants.CpuUsageCategory.PACKET_ENTITY_SPAWN,
TabAPI.getInstance().getThreadManager().runMeasuredTask(nameTagX, TabConstants.CpuUsageCategory.PACKET_ENTITY_SPAWN,
() -> nameTagX.getArmorStandManager(spawnedPlayer).spawn(receiver));
}
}
@@ -152,7 +151,7 @@ public class PacketListener extends TabFeature {
TabPlayer deSpawnedPlayer = entityIdMap.get(entity);
if (deSpawnedPlayer != null && deSpawnedPlayer.isLoaded() && !nameTagX.isPlayerDisabled(deSpawnedPlayer)) {
BukkitArmorStandManager asm = nameTagX.getArmorStandManager(deSpawnedPlayer);
TAB.getInstance().getCPUManager().runMeasuredTask(nameTagX, TabConstants.CpuUsageCategory.PACKET_ENTITY_DESTROY,
TabAPI.getInstance().getThreadManager().runMeasuredTask(nameTagX, TabConstants.CpuUsageCategory.PACKET_ENTITY_DESTROY,
() -> asm.destroy(receiver));
}
}
@@ -1,17 +1,15 @@
package me.neznamy.tab.platforms.bukkit.features.unlimitedtags;
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 org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import me.neznamy.tab.shared.TabConstants;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import me.neznamy.tab.api.TabFeature;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.TAB;
public class VehicleRefresher extends TabFeature {
//map of players currently in a vehicle
@@ -28,30 +26,30 @@ public class VehicleRefresher extends TabFeature {
public VehicleRefresher(BukkitNameTagX feature) {
super(feature.getFeatureName(), "Refreshing vehicles");
this.feature = feature;
TAB.getInstance().getCPUManager().startRepeatingMeasuredTask(50,
TabAPI.getInstance().getThreadManager().startRepeatingMeasuredTask(50,
this, TabConstants.CpuUsageCategory.PROCESSING_PLAYER_MOVEMENT, () -> {
for (TabPlayer inVehicle : playersInVehicle.keySet()) {
if (!inVehicle.isOnline() || feature.getArmorStandManager(inVehicle) == null) continue; // not removed from WeakHashMap yet
feature.getArmorStandManager(inVehicle).teleport();
}
for (TabPlayer p : TAB.getInstance().getOnlinePlayers()) {
for (TabPlayer p : TabAPI.getInstance().getOnlinePlayers()) {
if (feature.isPreviewingNametag(p)) {
feature.getArmorStandManager(p).teleport(p);
}
}
});
addUsedPlaceholders(Collections.singletonList(TabConstants.Placeholder.VEHICLE));
TAB.getInstance().getPlaceholderManager().registerPlayerPlaceholder(TabConstants.Placeholder.VEHICLE, 100, p -> ((Player)p.getPlayer()).getVehicle() == null ? "" : ((Player)p.getPlayer()).getVehicle());
TabAPI.getInstance().getPlaceholderManager().registerPlayerPlaceholder(TabConstants.Placeholder.VEHICLE, 100, p -> ((Player)p.getPlayer()).getVehicle() == null ? "" : ((Player)p.getPlayer()).getVehicle());
}
@Override
public void load() {
for (TabPlayer p : TAB.getInstance().getOnlinePlayers()) {
for (TabPlayer p : TabAPI.getInstance().getOnlinePlayers()) {
Entity vehicle = ((Player)p.getPlayer()).getVehicle();
if (vehicle != null) {
vehicles.put(vehicle.getEntityId(), getPassengers(vehicle));
playersInVehicle.put(p, vehicle);
if (feature.isDisableOnBoats() && vehicle.getType() == EntityType.BOAT) {
if (feature.isDisableOnBoats() && vehicle.getType().toString().contains("BOAT")) {
playersOnBoats.add(p);
}
}
@@ -91,7 +89,7 @@ public class VehicleRefresher extends TabFeature {
vehicles.put(vehicle.getEntityId(), getPassengers(vehicle));
feature.getArmorStandManager(p).respawn(); //making teleport instant instead of showing teleport animation
playersInVehicle.put(p, vehicle);
if (feature.isDisableOnBoats() && vehicle.getType() == EntityType.BOAT) {
if (feature.isDisableOnBoats() && vehicle.getType().toString().contains("BOAT")) {
playersOnBoats.add(p);
feature.updateTeamData(p);
}
@@ -115,7 +113,7 @@ public class VehicleRefresher extends TabFeature {
*/
@SuppressWarnings("deprecation")
public List<Entity> getPassengers(Entity vehicle){
if (TAB.getInstance().getServerVersion().getMinorVersion() >= 11) {
if (TabAPI.getInstance().getServerVersion().getMinorVersion() >= 11) {
return vehicle.getPassengers();
} else {
if (vehicle.getPassenger() != null) {
@@ -0,0 +1,102 @@
package me.neznamy.tab.platforms.bukkit.nms;
/**
* NMS loader for minecraft 1.17+ using Mojang packaging and bukkit names.
*/
public class BukkitModernNMSStorage extends ModernNMSStorage {
/**
* Creates new instance, initializes required NMS classes and fields
*
* @throws ReflectiveOperationException
* If any class, field or method fails to load
*/
public BukkitModernNMSStorage() throws ReflectiveOperationException {
}
@Override
public void loadNamedFieldsAndMethods() throws ReflectiveOperationException {
PING = getField(EntityPlayer, "e");
ChatSerializer_DESERIALIZE = getMethod(ChatSerializer, "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+}
ScoreboardTeam_setCanSeeFriendlyInvisibles = getMethod(ScoreboardTeam, new String[]{"setCanSeeFriendlyInvisibles", "b"}, boolean.class); // {Bukkit, Bukkit 1.18+}
ScoreboardTeam_setPrefix = getMethod(ScoreboardTeam, new String[]{"setPrefix", "b"}, IChatBaseComponent); // {Bukkit, Bukkit 1.18+}
ScoreboardTeam_setSuffix = getMethod(ScoreboardTeam, new String[]{"setSuffix", "c"}, IChatBaseComponent); // {Bukkit, Bukkit 1.18+}
ScoreboardTeam_setNameTagVisibility = getMethod(ScoreboardTeam, new String[]{"setNameTagVisibility", "a"}, EnumNameTagVisibility); // {Bukkit, Bukkit 1.18+}
if (minorVersion >= 19) {
Registry_a = Registry.getMethod("a", int.class);
IRegistry_X = IRegistry.getDeclaredField("X").get(null);
PacketPlayOutSpawnEntityLiving_ENTITYTYPE = getField(PacketPlayOutSpawnEntityLiving, "e");
}
}
@Override
public void loadClasses() throws ClassNotFoundException {
ChatSerializer = Class.forName("net.minecraft.network.chat.IChatBaseComponent$ChatSerializer");
World = Class.forName("net.minecraft.world.level.World");
EntityArmorStand = Class.forName("net.minecraft.world.entity.decoration.EntityArmorStand");
EntityHuman = Class.forName("net.minecraft.world.entity.player.EntityHuman");
NetworkManager = Class.forName("net.minecraft.network.NetworkManager");
IChatBaseComponent = Class.forName("net.minecraft.network.chat.IChatBaseComponent");
Packet = Class.forName("net.minecraft.network.protocol.Packet");
EnumChatFormat = Class.forName("net.minecraft.EnumChatFormat");
EntityPlayer = Class.forName("net.minecraft.server.level.EntityPlayer");
Entity = Class.forName("net.minecraft.world.entity.Entity");
EntityLiving = Class.forName("net.minecraft.world.entity.EntityLiving");
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) {
ChatMessageType = Class.forName("net.minecraft.network.chat.ChatMessageType");
}
// DataWatcher
DataWatcher = Class.forName("net.minecraft.network.syncher.DataWatcher");
DataWatcherItem = Class.forName("net.minecraft.network.syncher.DataWatcher$Item");
DataWatcherObject = Class.forName("net.minecraft.network.syncher.DataWatcherObject");
DataWatcherRegistry = Class.forName("net.minecraft.network.syncher.DataWatcherRegistry");
DataWatcherSerializer = Class.forName("net.minecraft.network.syncher.DataWatcherSerializer");
// Entities
PacketPlayOutSpawnEntityLiving = getModernClass("net.minecraft.network.protocol.game.PacketPlayOutSpawnEntityLiving",
"net.minecraft.network.protocol.game.PacketPlayOutSpawnEntity");
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");
PacketPlayOutEntity = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutEntity");
PacketPlayOutEntityDestroy = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutEntityDestroy");
PacketPlayOutEntityLook = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutEntity$PacketPlayOutEntityLook");
PacketPlayOutEntityMetadata = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutEntityMetadata");
PacketPlayOutNamedEntitySpawn = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutNamedEntitySpawn");
EnumEntityUseAction = Class.forName("net.minecraft.network.protocol.game.PacketPlayInUseEntity$EnumEntityUseAction");
if (minorVersion >= 19) {
Registry = Class.forName("net.minecraft.core.Registry");
IRegistry = Class.forName("net.minecraft.core.IRegistry");
}
// Player Info
PacketPlayOutPlayerInfo = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo");
EnumPlayerInfoAction = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo$EnumPlayerInfoAction");
PlayerInfoData = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo$PlayerInfoData");
EnumGamemode = Class.forName("net.minecraft.world.level.EnumGamemode");
// Scoreboard
PacketPlayOutScoreboardDisplayObjective = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutScoreboardDisplayObjective");
PacketPlayOutScoreboardObjective = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutScoreboardObjective");
Scoreboard = Class.forName("net.minecraft.world.scores.Scoreboard");
PacketPlayOutScoreboardScore = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutScoreboardScore");
ScoreboardObjective = Class.forName("net.minecraft.world.scores.ScoreboardObjective");
ScoreboardScore = Class.forName("net.minecraft.world.scores.ScoreboardScore");
IScoreboardCriteria = Class.forName("net.minecraft.world.scores.criteria.IScoreboardCriteria");
EnumScoreboardHealthDisplay = Class.forName("net.minecraft.world.scores.criteria.IScoreboardCriteria$EnumScoreboardHealthDisplay");
EnumScoreboardAction = Class.forName("net.minecraft.server.ScoreboardServer$Action");
PacketPlayOutScoreboardTeam = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutScoreboardTeam");
ScoreboardTeam = Class.forName("net.minecraft.world.scores.ScoreboardTeam");
EnumNameTagVisibility = Class.forName("net.minecraft.world.scores.ScoreboardTeamBase$EnumNameTagVisibility");
EnumTeamPush = Class.forName("net.minecraft.world.scores.ScoreboardTeamBase$EnumTeamPush");
PacketPlayOutScoreboardTeam_PlayerAction = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutScoreboardTeam$a");
}
}
@@ -0,0 +1,164 @@
package me.neznamy.tab.platforms.bukkit.nms;
import me.neznamy.tab.platforms.bukkit.Main;
import java.util.Arrays;
/**
* NMS loader for Minecraft 1.16.5 and lower using old NMS class structure.
*/
public class LegacyNMSStorage extends NMSStorage {
/**
* Creates new instance, initializes required NMS classes and fields
*
* @throws ReflectiveOperationException
* If any class, field or method fails to load
*/
public LegacyNMSStorage() 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
*/
private Class<?> getLegacyClass(String... names) throws ClassNotFoundException {
for (String name : names) {
try {
return getLegacyClass(name);
} catch (ClassNotFoundException e) {
//not the first class name in array
}
}
throw new ClassNotFoundException("No class found with possible names " + Arrays.toString(names));
}
/**
* Returns class from given name
*
* @param name
* class name
* @return class from given name
* @throws ClassNotFoundException
* if class was not found
*/
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);
}
}
@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}
if (minorVersion >= 7) {
ChatSerializer_DESERIALIZE = getMethod(ChatSerializer, new String[]{"a", "func_150699_a"}, String.class); // {Bukkit, Thermos}
}
if (minorVersion >= 8) {
ScoreboardTeam_setNameTagVisibility = getMethod(ScoreboardTeam, "setNameTagVisibility", EnumNameTagVisibility);
}
if (minorVersion >= 9) {
DataWatcher_REGISTER = getMethod(DataWatcher, "register", DataWatcherObject, Object.class);
} else {
DataWatcher_REGISTER = getMethod(DataWatcher, new String[]{"a", "func_75682_a"}, int.class, Object.class); // {Bukkit, Thermos}
}
if (minorVersion >= 13) {
ScoreboardTeam_setPrefix = getMethod(ScoreboardTeam, "setPrefix", IChatBaseComponent);
ScoreboardTeam_setSuffix = getMethod(ScoreboardTeam, "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}
}
}
@Override
public void loadClasses() throws ClassNotFoundException {
EntityHuman = getLegacyClass("EntityHuman");
World = getLegacyClass("World");
Packet = getLegacyClass("Packet");
EnumChatFormat = getLegacyClass("EnumChatFormat");
EntityPlayer = getLegacyClass("EntityPlayer");
Entity = getLegacyClass("Entity");
EntityLiving = getLegacyClass("EntityLiving");
PlayerConnection = getLegacyClass("PlayerConnection");
PacketPlayOutChat = getLegacyClass("PacketPlayOutChat", "Packet3Chat");
NetworkManager = getLegacyClass("NetworkManager");
if (minorVersion >= 7) {
IChatBaseComponent = getLegacyClass("IChatBaseComponent");
ChatSerializer = getLegacyClass("IChatBaseComponent$ChatSerializer", "ChatSerializer");
}
if (minorVersion >= 8) {
PacketPlayOutPlayerListHeaderFooter = getLegacyClass("PacketPlayOutPlayerListHeaderFooter");
EntityArmorStand = getLegacyClass("EntityArmorStand");
}
if (minorVersion >= 12) {
ChatMessageType = getLegacyClass("ChatMessageType");
}
// DataWatcher
DataWatcher = getLegacyClass("DataWatcher");
DataWatcherItem = getLegacyClass("DataWatcher$Item", "DataWatcher$WatchableObject", "WatchableObject");
if (minorVersion >= 9) {
DataWatcherObject = getLegacyClass("DataWatcherObject");
DataWatcherRegistry = getLegacyClass("DataWatcherRegistry");
DataWatcherSerializer = getLegacyClass("DataWatcherSerializer");
}
// Entities
PacketPlayOutSpawnEntityLiving = getLegacyClass("PacketPlayOutSpawnEntityLiving", "Packet24MobSpawn");
PacketPlayOutEntityTeleport = getLegacyClass("PacketPlayOutEntityTeleport", "Packet34EntityTeleport");
PacketPlayInUseEntity = getLegacyClass("PacketPlayInUseEntity", "Packet7UseEntity");
PacketPlayOutEntity = getLegacyClass("PacketPlayOutEntity", "Packet30Entity");
PacketPlayOutEntityDestroy = getLegacyClass("PacketPlayOutEntityDestroy", "Packet29DestroyEntity");
PacketPlayOutEntityLook = getLegacyClass("PacketPlayOutEntity$PacketPlayOutEntityLook", "PacketPlayOutEntityLook", "Packet32EntityLook");
PacketPlayOutEntityMetadata = getLegacyClass("PacketPlayOutEntityMetadata", "Packet40EntityMetadata");
PacketPlayOutNamedEntitySpawn = getLegacyClass("PacketPlayOutNamedEntitySpawn", "Packet20NamedEntitySpawn");
if (minorVersion >= 7) {
EnumEntityUseAction = getLegacyClass("PacketPlayInUseEntity$EnumEntityUseAction", "EnumEntityUseAction");
}
// Player Info
if (minorVersion >= 8) {
PacketPlayOutPlayerInfo = getLegacyClass("PacketPlayOutPlayerInfo");
EnumPlayerInfoAction = getLegacyClass("PacketPlayOutPlayerInfo$EnumPlayerInfoAction", "EnumPlayerInfoAction");
PlayerInfoData = getLegacyClass("PacketPlayOutPlayerInfo$PlayerInfoData", "PlayerInfoData");
EnumGamemode = getLegacyClass("EnumGamemode", "WorldSettings$EnumGamemode");
}
// Scoreboard
PacketPlayOutScoreboardDisplayObjective = getLegacyClass("PacketPlayOutScoreboardDisplayObjective", "Packet208SetScoreboardDisplayObjective");
PacketPlayOutScoreboardObjective = getLegacyClass("PacketPlayOutScoreboardObjective", "Packet206SetScoreboardObjective");
PacketPlayOutScoreboardTeam = getLegacyClass("PacketPlayOutScoreboardTeam", "Packet209SetScoreboardTeam");
PacketPlayOutScoreboardScore = getLegacyClass("PacketPlayOutScoreboardScore", "Packet207SetScoreboardScore");
Scoreboard = getLegacyClass("Scoreboard");
ScoreboardObjective = getLegacyClass("ScoreboardObjective");
ScoreboardScore = getLegacyClass("ScoreboardScore");
IScoreboardCriteria = getLegacyClass("IScoreboardCriteria");
ScoreboardTeam = getLegacyClass("ScoreboardTeam");
if (minorVersion >= 8) {
EnumScoreboardHealthDisplay = getLegacyClass("IScoreboardCriteria$EnumScoreboardHealthDisplay", "EnumScoreboardHealthDisplay");
EnumScoreboardAction = getLegacyClass("ScoreboardServer$Action", "PacketPlayOutScoreboardScore$EnumScoreboardAction", "EnumScoreboardAction");
EnumNameTagVisibility = getLegacyClass("ScoreboardTeamBase$EnumNameTagVisibility", "EnumNameTagVisibility");
}
if (minorVersion >= 9) {
EnumTeamPush = getLegacyClass("ScoreboardTeamBase$EnumTeamPush");
}
}
}
@@ -0,0 +1,41 @@
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 {
protected Class<?> IRegistry;
protected Class<?> Registry;
/**
* 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));
}
}
@@ -0,0 +1,102 @@
package me.neznamy.tab.platforms.bukkit.nms;
/**
* NMS loader for minecraft 1.17+ using Mojang packaging and names.
*/
public class MojangModernNMSStorage extends ModernNMSStorage {
/**
* Creates new instance, initializes required NMS classes and fields
*
* @throws ReflectiveOperationException
* If any class, field or method fails to load
*/
public MojangModernNMSStorage() throws ReflectiveOperationException {
}
@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);
if (minorVersion >= 19) {
Registry_a = Registry.getMethod("byId", int.class);
IRegistry_X = IRegistry.getDeclaredField("ENTITY_TYPE").get(null);
PacketPlayOutSpawnEntityLiving_ENTITYTYPE = getField(PacketPlayOutSpawnEntityLiving, "type");
}
}
@Override
public void loadClasses() throws ClassNotFoundException {
IChatBaseComponent = Class.forName("net.minecraft.network.chat.Component");
ChatSerializer = Class.forName("net.minecraft.network.chat.Component$Serializer");
World = Class.forName("net.minecraft.world.level.Level");
EntityArmorStand = Class.forName("net.minecraft.world.entity.decoration.ArmorStand");
EntityHuman = Class.forName("net.minecraft.world.entity.player.Player");
NetworkManager = Class.forName("net.minecraft.network.Connection");
Packet = Class.forName("net.minecraft.network.protocol.Packet");
EnumChatFormat = Class.forName("net.minecraft.ChatFormatting");
EntityPlayer = Class.forName("net.minecraft.server.level.ServerPlayer");
Entity = Class.forName("net.minecraft.world.entity.Entity");
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) {
ChatMessageType = Class.forName("net.minecraft.network.chat.ChatType");
}
// DataWatcher
DataWatcher = Class.forName("net.minecraft.network.syncher.SynchedEntityData");
DataWatcherItem = Class.forName("net.minecraft.network.syncher.SynchedEntityData$DataItem");
DataWatcherObject = Class.forName("net.minecraft.network.syncher.EntityDataAccessor");
DataWatcherRegistry = Class.forName("net.minecraft.network.syncher.EntityDataSerializers");
DataWatcherSerializer = Class.forName("net.minecraft.network.syncher.EntityDataSerializer");
// Entities
PacketPlayOutSpawnEntityLiving = getModernClass("net.minecraft.network.protocol.game.ClientboundAddMobPacket",
"net.minecraft.network.protocol.game.ClientboundAddEntityPacket");
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");
PacketPlayOutEntity = Class.forName("net.minecraft.network.protocol.game.ClientboundMoveEntityPacket");
PacketPlayOutEntityDestroy = Class.forName("net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket");
PacketPlayOutEntityLook = Class.forName("net.minecraft.network.protocol.game.ClientboundMoveEntityPacket$Rot");
PacketPlayOutEntityMetadata = Class.forName("net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket");
PacketPlayOutNamedEntitySpawn = Class.forName("net.minecraft.network.protocol.game.ClientboundAddPlayerPacket");
EnumEntityUseAction = Class.forName("net.minecraft.network.protocol.game.ServerboundInteractPacket$Action");
if (minorVersion >= 19) {
Registry = Class.forName("net.minecraft.core.IdMap");
IRegistry = Class.forName("net.minecraft.core.Registry");
}
// Player Info
PacketPlayOutPlayerInfo = Class.forName("net.minecraft.network.protocol.game.ClientboundPlayerInfoPacket");
EnumPlayerInfoAction = Class.forName("net.minecraft.network.protocol.game.ClientboundPlayerInfoPacket$Action");
PlayerInfoData = Class.forName("net.minecraft.network.protocol.game.ClientboundPlayerInfoPacket$PlayerUpdate");
EnumGamemode = Class.forName("net.minecraft.world.level.GameType");
// Scoreboard
PacketPlayOutScoreboardDisplayObjective = Class.forName("net.minecraft.network.protocol.game.ClientboundSetDisplayObjectivePacket");
PacketPlayOutScoreboardObjective = Class.forName("net.minecraft.network.protocol.game.ClientboundSetObjectivePacket");
Scoreboard = Class.forName("net.minecraft.world.scores.Scoreboard");
PacketPlayOutScoreboardScore = Class.forName("net.minecraft.network.protocol.game.ClientboundSetScorePacket");
ScoreboardObjective = Class.forName("net.minecraft.world.scores.Objective");
ScoreboardScore = Class.forName("net.minecraft.world.scores.Score");
IScoreboardCriteria = Class.forName("net.minecraft.world.scores.criteria.ObjectiveCriteria");
EnumScoreboardHealthDisplay = Class.forName("net.minecraft.world.scores.criteria.ObjectiveCriteria$RenderType");
EnumScoreboardAction = Class.forName("net.minecraft.server.ServerScoreboard$Method");
PacketPlayOutScoreboardTeam = Class.forName("net.minecraft.network.protocol.game.ClientboundSetPlayerTeamPacket");
ScoreboardTeam = Class.forName("net.minecraft.world.scores.PlayerTeam");
EnumNameTagVisibility = Class.forName("net.minecraft.world.scores.Team$Visibility");
EnumTeamPush = Class.forName("net.minecraft.world.scores.Team$CollisionRule");
PacketPlayOutScoreboardTeam_PlayerAction = Class.forName("net.minecraft.network.protocol.game.ClientboundSetPlayerTeamPacket$Action");
}
}
@@ -1,152 +1,134 @@
package me.neznamy.tab.platforms.bukkit.nms;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
import org.bukkit.Bukkit;
import com.google.gson.JsonElement;
import com.mojang.authlib.GameProfile;
import io.netty.channel.Channel;
import me.neznamy.tab.api.ProtocolVersion;
import me.neznamy.tab.platforms.bukkit.Main;
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcherRegistry;
import me.neznamy.tab.shared.TAB;
import org.bukkit.Bukkit;
import java.lang.reflect.*;
import java.util.*;
@SuppressWarnings("rawtypes")
public final class NMSStorage {
public abstract class NMSStorage {
//instance of this class
private static NMSStorage instance;
//server package, such as "v1_16_R3"
private final String serverPackage = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
protected final String serverPackage = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
//server minor version such as "16"
private final int minorVersion = Integer.parseInt(serverPackage.split("_")[1]);
protected final int minorVersion = Integer.parseInt(serverPackage.split("_")[1]);
//another field due to fabric which uses 1.16 package on 1.17 server
private final ProtocolVersion serverVersion = ProtocolVersion.fromFriendlyName(Bukkit.getBukkitVersion().split("-")[0]);
//base
private final Class<?> Packet = getNMSClass("net.minecraft.network.protocol.Packet", "Packet");
public final Class<?> EnumChatFormat = getNMSClass("net.minecraft.EnumChatFormat", "EnumChatFormat");
public final Class<?> EntityPlayer = getNMSClass("net.minecraft.server.level.EntityPlayer", "EntityPlayer");
private final Class<?> Entity = getNMSClass("net.minecraft.world.entity.Entity", "Entity");
private final Class<?> EntityLiving = getNMSClass("net.minecraft.world.entity.EntityLiving", "EntityLiving");
private final Class<?> PlayerConnection = getNMSClass("net.minecraft.server.network.PlayerConnection", "PlayerConnection");
public final Field PING = getField(EntityPlayer, "ping", "latency", "field_71138_i", "field_13967", "e");
public final Field PLAYER_CONNECTION = getFields(EntityPlayer, PlayerConnection).get(0);
protected Class<?> Packet;
protected Class<?> NetworkManager;
protected Class<?> EntityArmorStand;
protected Class<?> World;
public Class<?> EnumChatFormat;
public Class<?> EntityPlayer;
protected Class<?> EntityHuman;
protected Class<?> Entity;
protected Class<?> EntityLiving;
protected Class<?> PlayerConnection;
public Field PING;
public Field PLAYER_CONNECTION;
public Field NETWORK_MANAGER;
public Field CHANNEL;
public final Method getHandle = Class.forName("org.bukkit.craftbukkit." + serverPackage + ".entity.CraftPlayer").getMethod("getHandle");
public final Method sendPacket = getMethods(PlayerConnection, void.class, Packet).get(0);
public Method getHandle;
public Method sendPacket;
public Method getProfile;
public final Enum[] EnumChatFormat_values = getEnumValues(EnumChatFormat);
public Enum[] EnumChatFormat_values;
//chat
public Class<?> EnumClickAction;
private Class<?> IChatBaseComponent;
public Constructor<?> newChatComponentText;
public Constructor<?> newChatClickable;
public Constructor<?> newChatModifier;
public Constructor<?> newChatHoverable;
public Field ChatBaseComponent_modifier;
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 ChatModifier_color;
public Method ChatComponentText_addSibling;
public Method EnumHoverAction_a;
public Method ChatHexColor_ofInt;
public Method ChatHexColor_ofString;
public Method EnumHoverAction_fromJson;
public Method EnumHoverAction_fromLegacyComponent;
protected Class<?> IChatBaseComponent;
protected Class<?> ChatSerializer;
public Method ChatSerializer_DESERIALIZE;
//PacketPlayOutChat
protected Class<?> PacketPlayOutChat;
public Class<?> ChatMessageType;
public Constructor<?> newPacketPlayOutChat;
public Enum[] ChatMessageType_values;
//DataWatcher
private final Class<?> DataWatcher = getNMSClass("net.minecraft.network.syncher.DataWatcher", "DataWatcher");
private final Class<?> DataWatcherItem = getNMSClass("net.minecraft.network.syncher.DataWatcher$Item", "DataWatcher$Item", "DataWatcher$WatchableObject", "WatchableObject");
protected Class<?> DataWatcher;
protected Class<?> DataWatcherItem;
protected Class<?> DataWatcherObject;
protected Class<?> DataWatcherSerializer;
public Class<?> DataWatcherRegistry;
public final Constructor<?> newDataWatcher = DataWatcher.getConstructors()[0];
public Constructor<?> newDataWatcher;
public Constructor<?> newDataWatcherObject;
public Field DataWatcherItem_TYPE;
public final Field DataWatcherItem_VALUE = getFields(DataWatcherItem, Object.class).get(0);
public Field DataWatcherItem_VALUE;
public Field DataWatcherObject_SLOT;
public Field DataWatcherObject_SERIALIZER;
public Method DataWatcher_REGISTER;
private DataWatcherRegistry registry;
private final DataWatcherRegistry registry;
//PacketPlayOutSpawnEntityLiving
public final Class<?> PacketPlayOutSpawnEntityLiving = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutSpawnEntityLiving", "PacketPlayOutSpawnEntityLiving", "Packet24MobSpawn");
public Class<?> PacketPlayOutSpawnEntityLiving;
public Constructor<?> newPacketPlayOutSpawnEntityLiving;
public final Field PacketPlayOutSpawnEntityLiving_ENTITYID = getFields(PacketPlayOutSpawnEntityLiving, int.class).get(0);
public final Field PacketPlayOutSpawnEntityLiving_ENTITYTYPE = getFields(PacketPlayOutSpawnEntityLiving, int.class).get(1);
public final Field PacketPlayOutSpawnEntityLiving_YAW = getFields(PacketPlayOutSpawnEntityLiving, byte.class).get(0);
public final Field PacketPlayOutSpawnEntityLiving_PITCH = getFields(PacketPlayOutSpawnEntityLiving, byte.class).get(0);
public Field PacketPlayOutSpawnEntityLiving_ENTITYID;
public Field PacketPlayOutSpawnEntityLiving_ENTITYTYPE;
public Field PacketPlayOutSpawnEntityLiving_YAW;
public Field PacketPlayOutSpawnEntityLiving_PITCH;
public Field PacketPlayOutSpawnEntityLiving_UUID;
public Field PacketPlayOutSpawnEntityLiving_X;
public Field PacketPlayOutSpawnEntityLiving_Y;
public Field PacketPlayOutSpawnEntityLiving_Z;
public Field PacketPlayOutSpawnEntityLiving_DATAWATCHER;
public Method Registry_a;
public Object IRegistry_X;
//PacketPlayOutEntityTeleport
public final Class<?> PacketPlayOutEntityTeleport = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutEntityTeleport", "PacketPlayOutEntityTeleport", "Packet34EntityTeleport");
public Class<?> PacketPlayOutEntityTeleport;
public Constructor<?> newPacketPlayOutEntityTeleport;
public final Field PacketPlayOutEntityTeleport_ENTITYID = getFields(PacketPlayOutEntityTeleport, int.class).get(0);
public Field PacketPlayOutEntityTeleport_ENTITYID;
public Field PacketPlayOutEntityTeleport_X;
public Field PacketPlayOutEntityTeleport_Y;
public Field PacketPlayOutEntityTeleport_Z;
public final Field PacketPlayOutEntityTeleport_YAW = getFields(PacketPlayOutEntityTeleport, byte.class).get(0);
public final Field PacketPlayOutEntityTeleport_PITCH = getFields(PacketPlayOutEntityTeleport, byte.class).get(1);
public Field PacketPlayOutEntityTeleport_YAW;
public Field PacketPlayOutEntityTeleport_PITCH;
//PacketPlayOutPlayerListHeaderFooter
protected Class<?> PacketPlayOutPlayerListHeaderFooter;
public Constructor<?> newPacketPlayOutPlayerListHeaderFooter;
public Field PacketPlayOutPlayerListHeaderFooter_HEADER;
public Field PacketPlayOutPlayerListHeaderFooter_FOOTER;
//other entity packets
public final Class<?> PacketPlayInUseEntity = getNMSClass("net.minecraft.network.protocol.game.PacketPlayInUseEntity", "PacketPlayInUseEntity", "Packet7UseEntity");
public Class<?> PacketPlayInUseEntity;
public Class<?> PacketPlayInUseEntity$d;
protected Class<?> EnumEntityUseAction;
public Field PacketPlayInUseEntity_ENTITY;
public Field PacketPlayInUseEntity_ACTION;
public final Class<?> PacketPlayOutEntity = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutEntity", "PacketPlayOutEntity", "Packet30Entity");
public final Field PacketPlayOutEntity_ENTITYID = getFields(PacketPlayOutEntity, int.class).get(0);
public Class<?> PacketPlayOutEntity;
public Field PacketPlayOutEntity_ENTITYID;
public final Class<?> PacketPlayOutEntityDestroy = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutEntityDestroy", "PacketPlayOutEntityDestroy", "Packet29DestroyEntity");
public Class<?> PacketPlayOutEntityDestroy;
public Constructor<?> newPacketPlayOutEntityDestroy;
public final Field PacketPlayOutEntityDestroy_ENTITIES = setAccessible(PacketPlayOutEntityDestroy.getDeclaredFields()[0]);
public Field PacketPlayOutEntityDestroy_ENTITIES;
public final Class<?> PacketPlayOutEntityLook = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutEntity$PacketPlayOutEntityLook", "PacketPlayOutEntity$PacketPlayOutEntityLook", "PacketPlayOutEntityLook", "Packet32EntityLook");
public Class<?> PacketPlayOutEntityLook;
public final Class<?> PacketPlayOutEntityMetadata = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutEntityMetadata", "PacketPlayOutEntityMetadata", "Packet40EntityMetadata");
public final Constructor<?> newPacketPlayOutEntityMetadata = PacketPlayOutEntityMetadata.getConstructor(int.class, DataWatcher, boolean.class);
public final Field PacketPlayOutEntityMetadata_LIST = getFields(PacketPlayOutEntityMetadata, List.class).get(0);
public Class<?> PacketPlayOutEntityMetadata;
public Constructor<?> newPacketPlayOutEntityMetadata;
public Field PacketPlayOutEntityMetadata_LIST;
public final Class<?> PacketPlayOutNamedEntitySpawn = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutNamedEntitySpawn", "PacketPlayOutNamedEntitySpawn", "Packet20NamedEntitySpawn");
public final Field PacketPlayOutNamedEntitySpawn_ENTITYID = getFields(PacketPlayOutNamedEntitySpawn, int.class).get(0);
public Class<?> PacketPlayOutNamedEntitySpawn;
public Field PacketPlayOutNamedEntitySpawn_ENTITYID;
//PacketPlayOutPlayerInfo
public Class<?> PacketPlayOutPlayerInfo;
protected Class<?> EnumPlayerInfoAction;
protected Class<?> PlayerInfoData;
protected Class<?> EnumGamemode;
public Constructor<?> newPacketPlayOutPlayerInfo;
public Constructor<?> newPlayerInfoData;
public Field PacketPlayOutPlayerInfo_ACTION;
@@ -159,35 +141,40 @@ public final class NMSStorage {
public Enum[] EnumGamemode_values;
//scoreboard objectives
public final Class<?> PacketPlayOutScoreboardDisplayObjective = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutScoreboardDisplayObjective", "PacketPlayOutScoreboardDisplayObjective", "Packet208SetScoreboardDisplayObjective");
public final Class<?> PacketPlayOutScoreboardObjective = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutScoreboardObjective", "PacketPlayOutScoreboardObjective", "Packet206SetScoreboardObjective");
private final Class<?> Scoreboard = getNMSClass("net.minecraft.world.scores.Scoreboard", "Scoreboard");
private final Class<?> PacketPlayOutScoreboardScore = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutScoreboardScore", "PacketPlayOutScoreboardScore", "Packet207SetScoreboardScore");
private final Class<?> ScoreboardObjective = getNMSClass("net.minecraft.world.scores.ScoreboardObjective", "ScoreboardObjective");
private final Class<?> ScoreboardScore = getNMSClass("net.minecraft.world.scores.ScoreboardScore", "ScoreboardScore");
private final Class<?> IScoreboardCriteria = getNMSClass("net.minecraft.world.scores.criteria.IScoreboardCriteria", "IScoreboardCriteria");
public Class<?> PacketPlayOutScoreboardDisplayObjective;
public Class<?> PacketPlayOutScoreboardObjective;
protected Class<?> Scoreboard;
protected Class<?> PacketPlayOutScoreboardScore;
protected Class<?> ScoreboardObjective;
protected Class<?> ScoreboardScore;
protected Class<?> IScoreboardCriteria;
public Class<?> EnumScoreboardHealthDisplay;
public final Constructor<?> newScoreboardObjective = ScoreboardObjective.getConstructors()[0];
private final Constructor<?> newScoreboard = Scoreboard.getConstructor();
public final Constructor<?> newScoreboardScore = ScoreboardScore.getConstructor(Scoreboard, ScoreboardObjective, String.class);
public final Constructor<?> newPacketPlayOutScoreboardDisplayObjective = PacketPlayOutScoreboardDisplayObjective.getConstructor(int.class, ScoreboardObjective);
protected Class<?> EnumScoreboardAction;
public Constructor<?> newScoreboardObjective;
protected Constructor<?> newScoreboard;
public Constructor<?> newScoreboardScore;
public Constructor<?> newPacketPlayOutScoreboardDisplayObjective;
public Constructor<?> newPacketPlayOutScoreboardObjective;
public Constructor<?> newPacketPlayOutScoreboardScore_1_13;
public Constructor<?> newPacketPlayOutScoreboardScore_String;
public Constructor<?> newPacketPlayOutScoreboardScore;
public final Field PacketPlayOutScoreboardDisplayObjective_POSITION = getFields(PacketPlayOutScoreboardDisplayObjective, int.class).get(0);
public final Field PacketPlayOutScoreboardDisplayObjective_OBJECTIVENAME = getFields(PacketPlayOutScoreboardDisplayObjective, String.class).get(0);
public final Field PacketPlayOutScoreboardObjective_OBJECTIVENAME = getFields(PacketPlayOutScoreboardObjective, String.class).get(0);
public Field PacketPlayOutScoreboardDisplayObjective_POSITION;
public Field PacketPlayOutScoreboardDisplayObjective_OBJECTIVENAME;
public Field PacketPlayOutScoreboardObjective_OBJECTIVENAME;
public Field PacketPlayOutScoreboardObjective_METHOD;
public final Field IScoreboardCriteria_self = getFields(IScoreboardCriteria, IScoreboardCriteria).get(0);
public Field IScoreboardCriteria_self;
public Field PacketPlayOutScoreboardObjective_RENDERTYPE;
public Field PacketPlayOutScoreboardObjective_DISPLAYNAME;
public final Method ScoreboardScore_setScore = getMethod(ScoreboardScore, new String[]{"setScore", "func_96647_c", "method_1128", "b"}, int.class);
public Method ScoreboardScore_setScore;
public Enum[] EnumScoreboardHealthDisplay_values;
public Enum[] EnumScoreboardAction_values;
//PacketPlayOutScoreboardTeam
public Class<?> PacketPlayOutScoreboardTeam;
protected Class<?> ScoreboardTeam;
protected Class<?> EnumNameTagVisibility;
protected Class<?> EnumTeamPush;
protected Class<?> PacketPlayOutScoreboardTeam_PlayerAction;
public Constructor<?> newScoreboardTeam;
public Constructor<?> newPacketPlayOutScoreboardTeam;
public Field PacketPlayOutScoreboardTeam_NAME;
@@ -209,42 +196,37 @@ public final class NMSStorage {
public Enum[] PacketPlayOutScoreboardTeam_PlayerAction_values;
//other
public final Object emptyScoreboard = newScoreboard.newInstance();
public Object emptyScoreboard;
public Object dummyEntity;
/**
* Creates new instance, initializes required NMS classes and fields
*
* @throws ReflectiveOperationException
* If any class, field or method fails to load
*/
public NMSStorage() throws ReflectiveOperationException {
ProtocolVersion.UNKNOWN_SERVER_VERSION.setMinorVersion(minorVersion); //fixing compatibility with forks that set version field value to "Unknown"
Class<?> NetworkManager = getNMSClass("net.minecraft.network.NetworkManager", "NetworkManager");
loadClasses();
if (minorVersion >= 7) {
NETWORK_MANAGER = getFields(PlayerConnection, NetworkManager).get(0);
}
if (minorVersion >= 8) {
CHANNEL = getFields(NetworkManager, Channel.class).get(0);
getProfile = getMethods(getNMSClass("net.minecraft.world.entity.player.EntityHuman", "EntityHuman"), GameProfile.class).get(0);
Constructor<?> newEntityArmorStand = getNMSClass("net.minecraft.world.entity.decoration.EntityArmorStand", "EntityArmorStand")
.getConstructor(getNMSClass("net.minecraft.world.level.World", "World"), double.class, double.class, double.class);
getProfile = getMethods(EntityHuman, GameProfile.class).get(0);
Constructor<?> newEntityArmorStand = EntityArmorStand.getConstructor(World, double.class, double.class, double.class);
Method World_getHandle = Class.forName("org.bukkit.craftbukkit." + serverPackage + ".CraftWorld").getMethod("getHandle");
dummyEntity = newEntityArmorStand.newInstance(World_getHandle.invoke(Bukkit.getWorlds().get(0)), 0, 0, 0);
}
initializeChatComponents();
initializeChatPacket();
initializeDataWatcher();
initializeEntityPackets();
initializeHeaderFooterPacket();
initializePlayerInfoPacket();
initializeScoreboardPackets();
try {
initializeTeamPackets();
} catch (ClassNotFoundException e) {
Bukkit.getConsoleSender().sendMessage(me.neznamy.tab.api.chat.EnumChatFormat.color("&c[TAB] Failed to load PacketPlayOutScoreboardTeam"));
//fabric with missing team packet
}
PLAYER_CONNECTION = getFields(EntityPlayer, PlayerConnection).get(0);
getHandle = Class.forName("org.bukkit.craftbukkit." + serverPackage + ".entity.CraftPlayer").getMethod("getHandle");
sendPacket = getMethods(PlayerConnection, void.class, Packet).get(0);
EnumChatFormat_values = getEnumValues(EnumChatFormat);
registry = new DataWatcherRegistry(this);
dataWatcher();
entityTeleport();
spawnEntityLiving();
chat();
playerListHeaderFooter();
playerInfo();
otherEntity();
scoreboard();
scoreboardTeam();
loadNamedFieldsAndMethods();
}
/**
@@ -266,53 +248,18 @@ public final class NMSStorage {
return instance;
}
private void initializeChatComponents() throws ReflectiveOperationException {
if (minorVersion < 7) return;
Class<?> ChatBaseComponent = getNMSClass("net.minecraft.network.chat.ChatBaseComponent", "ChatBaseComponent");
Class<?> ChatClickable = getNMSClass("net.minecraft.network.chat.ChatClickable", "ChatClickable");
Class<?> ChatComponentText = getNMSClass("net.minecraft.network.chat.ChatComponentText", "ChatComponentText");
Class<?> ChatHoverable = getNMSClass("net.minecraft.network.chat.ChatHoverable", "ChatHoverable");
Class<?> ChatModifier = getNMSClass("net.minecraft.network.chat.ChatModifier", "ChatModifier");
EnumClickAction = getNMSClass("net.minecraft.network.chat.ChatClickable$EnumClickAction", "ChatClickable$EnumClickAction", "EnumClickAction");
Class<?> EnumHoverAction = getNMSClass("net.minecraft.network.chat.ChatHoverable$EnumHoverAction", "ChatHoverable$EnumHoverAction", "EnumHoverAction");
IChatBaseComponent = getNMSClass("net.minecraft.network.chat.IChatBaseComponent", "IChatBaseComponent");
newChatComponentText = ChatComponentText.getConstructor(String.class);
newChatClickable = ChatClickable.getConstructor(EnumClickAction, String.class);
ChatBaseComponent_modifier = getFields(ChatBaseComponent, ChatModifier).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);
ChatComponentText_addSibling = getMethod(ChatComponentText, new String[]{"addSibling", "a", "func_150257_a", "method_10852"}, IChatBaseComponent);
EnumHoverAction_a = getMethod(EnumHoverAction, new String[]{"a", "func_150684_a", "method_27670"}, String.class);
if (minorVersion >= 16) {
Class<?> ChatHexColor = getNMSClass("net.minecraft.network.chat.ChatHexColor", "ChatHexColor");
Class<?> MinecraftKey = getNMSClass("net.minecraft.resources.MinecraftKey", "MinecraftKey");
newChatModifier = setAccessible(ChatModifier.getDeclaredConstructor(ChatHexColor, Boolean.class, Boolean.class, Boolean.class, Boolean.class, Boolean.class, ChatClickable, ChatHoverable, String.class, MinecraftKey));
newChatHoverable = ChatHoverable.getConstructor(EnumHoverAction, Object.class);
ChatModifier_color = getFields(ChatModifier, ChatHexColor).get(0);
ChatHexColor_ofInt = getMethods(ChatHexColor, ChatHexColor, int.class).get(0);
ChatHexColor_ofString = getMethods(ChatHexColor, ChatHexColor, String.class).get(0);
EnumHoverAction_fromJson = getMethods(EnumHoverAction, ChatHoverable, JsonElement.class).get(0);
EnumHoverAction_fromLegacyComponent = getMethods(EnumHoverAction, ChatHoverable, IChatBaseComponent).get(0);
} else {
newChatModifier = ChatModifier.getConstructor();
newChatHoverable = ChatHoverable.getConstructor(EnumHoverAction, IChatBaseComponent);
ChatModifier_color = getFields(ChatModifier, EnumChatFormat).get(0);
}
}
private void initializeChatPacket() throws ReflectiveOperationException {
Class<?> PacketPlayOutChat = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutChat", "PacketPlayOutChat", "Packet3Chat");
if (minorVersion >= 12) {
ChatMessageType = getNMSClass("net.minecraft.network.chat.ChatMessageType", "ChatMessageType");
protected void chat() throws ReflectiveOperationException {
if (minorVersion >= 12 && minorVersion <= 18) {
ChatMessageType_values = getEnumValues(ChatMessageType);
}
if (minorVersion >= 16) {
if (minorVersion >= 19) {
try {
newPacketPlayOutChat = PacketPlayOutChat.getConstructor(IChatBaseComponent, boolean.class);
} catch (NoSuchMethodException e) {
//1.19.0
newPacketPlayOutChat = PacketPlayOutChat.getConstructor(IChatBaseComponent, int.class);
}
} else if (minorVersion >= 16) {
newPacketPlayOutChat = PacketPlayOutChat.getConstructor(IChatBaseComponent, ChatMessageType, UUID.class);
} else if (minorVersion >= 12) {
newPacketPlayOutChat = PacketPlayOutChat.getConstructor(IChatBaseComponent, ChatMessageType);
@@ -323,84 +270,8 @@ public final class NMSStorage {
}
}
private void initializeDataWatcher() throws ReflectiveOperationException {
if (minorVersion >= 9) {
Class<?> DataWatcherObject = getNMSClass("net.minecraft.network.syncher.DataWatcherObject", "DataWatcherObject");
DataWatcherRegistry = getNMSClass("net.minecraft.network.syncher.DataWatcherRegistry", "DataWatcherRegistry");
Class<?> DataWatcherSerializer = getNMSClass("net.minecraft.network.syncher.DataWatcherSerializer", "DataWatcherSerializer");
newDataWatcherObject = DataWatcherObject.getConstructor(int.class, DataWatcherSerializer);
DataWatcherItem_TYPE = getFields(DataWatcherItem, DataWatcherObject).get(0);
DataWatcherObject_SLOT = getFields(DataWatcherObject, int.class).get(0);
DataWatcherObject_SERIALIZER = getFields(DataWatcherObject, DataWatcherSerializer).get(0);
DataWatcher_REGISTER = getMethod(DataWatcher, new String[]{"register", "method_12784", "a"}, DataWatcherObject, Object.class);
} else {
DataWatcherItem_TYPE = getFields(DataWatcherItem, int.class).get(1);
DataWatcher_REGISTER = getMethod(DataWatcher, new String[]{"a", "func_75682_a"}, int.class, Object.class);
}
registry = new DataWatcherRegistry(this);
}
private void initializeEntityPackets() throws ReflectiveOperationException {
if (minorVersion >= 17 || serverVersion.getMinorVersion() >= 17) {
newPacketPlayOutSpawnEntityLiving = PacketPlayOutSpawnEntityLiving.getConstructor(EntityLiving);
newPacketPlayOutEntityTeleport = PacketPlayOutEntityTeleport.getConstructor(Entity);
} else {
newPacketPlayOutSpawnEntityLiving = PacketPlayOutSpawnEntityLiving.getConstructor();
newPacketPlayOutEntityTeleport = PacketPlayOutEntityTeleport.getConstructor();
}
if (minorVersion >= 17) {
PacketPlayInUseEntity$d = Class.forName("net.minecraft.network.protocol.game.PacketPlayInUseEntity$d");
}
try {
newPacketPlayOutEntityDestroy = PacketPlayOutEntityDestroy.getConstructor(int[].class);
} catch (NoSuchMethodException e) {
//1.17.0
newPacketPlayOutEntityDestroy = PacketPlayOutEntityDestroy.getConstructor(int.class);
}
if (minorVersion >= 7) {
Class<?> EnumEntityUseAction = getNMSClass("net.minecraft.network.protocol.game.PacketPlayInUseEntity$EnumEntityUseAction", "PacketPlayInUseEntity$EnumEntityUseAction", "EnumEntityUseAction", "net.minecraft.class_2824$class_5906");
PacketPlayInUseEntity_ENTITY = getFields(PacketPlayInUseEntity, int.class).get(0);
PacketPlayInUseEntity_ACTION = getFields(PacketPlayInUseEntity, EnumEntityUseAction).get(0);
}
if (minorVersion >= 9) {
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);
PacketPlayOutEntityTeleport_X = getFields(PacketPlayOutEntityTeleport, double.class).get(0);
PacketPlayOutEntityTeleport_Y = getFields(PacketPlayOutEntityTeleport, double.class).get(1);
PacketPlayOutEntityTeleport_Z = getFields(PacketPlayOutEntityTeleport, double.class).get(2);
} else {
PacketPlayOutSpawnEntityLiving_X = getFields(PacketPlayOutSpawnEntityLiving, int.class).get(2);
PacketPlayOutSpawnEntityLiving_Y = getFields(PacketPlayOutSpawnEntityLiving, int.class).get(3);
PacketPlayOutSpawnEntityLiving_Z = getFields(PacketPlayOutSpawnEntityLiving, int.class).get(4);
PacketPlayOutEntityTeleport_X = getFields(PacketPlayOutEntityTeleport, int.class).get(1);
PacketPlayOutEntityTeleport_Y = getFields(PacketPlayOutEntityTeleport, int.class).get(2);
PacketPlayOutEntityTeleport_Z = getFields(PacketPlayOutEntityTeleport, int.class).get(3);
}
if (minorVersion <= 14) {
PacketPlayOutSpawnEntityLiving_DATAWATCHER = getFields(PacketPlayOutSpawnEntityLiving, DataWatcher).get(0);
}
}
private void initializeHeaderFooterPacket() throws ReflectiveOperationException {
protected void playerInfo() throws ReflectiveOperationException {
if (minorVersion < 8) return;
Class<?> PacketPlayOutPlayerListHeaderFooter = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutPlayerListHeaderFooter", "PacketPlayOutPlayerListHeaderFooter");
PacketPlayOutPlayerListHeaderFooter_HEADER = getFields(PacketPlayOutPlayerListHeaderFooter, IChatBaseComponent).get(0);
PacketPlayOutPlayerListHeaderFooter_FOOTER = getFields(PacketPlayOutPlayerListHeaderFooter, IChatBaseComponent).get(1);
if (minorVersion >= 17 || serverVersion.getMinorVersion() >= 17) {
newPacketPlayOutPlayerListHeaderFooter = PacketPlayOutPlayerListHeaderFooter.getConstructor(IChatBaseComponent, IChatBaseComponent);
} else {
newPacketPlayOutPlayerListHeaderFooter = PacketPlayOutPlayerListHeaderFooter.getConstructor();
}
}
private void initializePlayerInfoPacket() throws ReflectiveOperationException {
if (minorVersion < 8) return;
PacketPlayOutPlayerInfo = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo", "PacketPlayOutPlayerInfo");
Class<?> EnumPlayerInfoAction = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo$EnumPlayerInfoAction", "PacketPlayOutPlayerInfo$EnumPlayerInfoAction", "EnumPlayerInfoAction", "net.minecraft.class_2703$class_5893");
Class<?> PlayerInfoData = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo$PlayerInfoData", "PacketPlayOutPlayerInfo$PlayerInfoData", "PlayerInfoData");
Class<?> EnumGamemode = getNMSClass("net.minecraft.world.level.EnumGamemode", "EnumGamemode", "WorldSettings$EnumGamemode");
newPacketPlayOutPlayerInfo = PacketPlayOutPlayerInfo.getConstructor(EnumPlayerInfoAction, Array.newInstance(EntityPlayer, 0).getClass());
newPlayerInfoData = PlayerInfoData.getConstructors()[0];
PacketPlayOutPlayerInfo_ACTION = getFields(PacketPlayOutPlayerInfo, EnumPlayerInfoAction).get(0);
@@ -413,14 +284,115 @@ public final class NMSStorage {
EnumGamemode_values = getEnumValues(EnumGamemode);
}
private void initializeScoreboardPackets() throws ReflectiveOperationException {
protected void spawnEntityLiving() throws ReflectiveOperationException {
if (minorVersion >= 17 || serverVersion.getMinorVersion() >= 17) {
newPacketPlayOutSpawnEntityLiving = PacketPlayOutSpawnEntityLiving.getConstructor(EntityLiving);
} else {
newPacketPlayOutSpawnEntityLiving = PacketPlayOutSpawnEntityLiving.getConstructor();
}
PacketPlayOutSpawnEntityLiving_ENTITYID = getFields(PacketPlayOutSpawnEntityLiving, int.class).get(0);
PacketPlayOutSpawnEntityLiving_YAW = getFields(PacketPlayOutSpawnEntityLiving, byte.class).get(0);
PacketPlayOutSpawnEntityLiving_PITCH = getFields(PacketPlayOutSpawnEntityLiving, byte.class).get(0);
if (minorVersion >= 9) {
PacketPlayOutSpawnEntityLiving_UUID = getFields(PacketPlayOutSpawnEntityLiving, UUID.class).get(0);
if (minorVersion >= 19) {
PacketPlayOutSpawnEntityLiving_X = getFields(PacketPlayOutSpawnEntityLiving, double.class).get(2);
PacketPlayOutSpawnEntityLiving_Y = getFields(PacketPlayOutSpawnEntityLiving, double.class).get(3);
PacketPlayOutSpawnEntityLiving_Z = getFields(PacketPlayOutSpawnEntityLiving, double.class).get(4);
} else {
PacketPlayOutSpawnEntityLiving_X = getFields(PacketPlayOutSpawnEntityLiving, double.class).get(0);
PacketPlayOutSpawnEntityLiving_Y = getFields(PacketPlayOutSpawnEntityLiving, double.class).get(1);
PacketPlayOutSpawnEntityLiving_Z = getFields(PacketPlayOutSpawnEntityLiving, double.class).get(2);
}
} else {
PacketPlayOutSpawnEntityLiving_X = getFields(PacketPlayOutSpawnEntityLiving, int.class).get(2);
PacketPlayOutSpawnEntityLiving_Y = getFields(PacketPlayOutSpawnEntityLiving, int.class).get(3);
PacketPlayOutSpawnEntityLiving_Z = getFields(PacketPlayOutSpawnEntityLiving, int.class).get(4);
}
if (minorVersion < 19) {
PacketPlayOutSpawnEntityLiving_ENTITYTYPE = getFields(PacketPlayOutSpawnEntityLiving, int.class).get(1);
}
if (minorVersion <= 14) {
PacketPlayOutSpawnEntityLiving_DATAWATCHER = getFields(PacketPlayOutSpawnEntityLiving, DataWatcher).get(0);
}
}
protected void entityTeleport() throws ReflectiveOperationException {
PacketPlayOutEntityTeleport_ENTITYID = getFields(PacketPlayOutEntityTeleport, int.class).get(0);
PacketPlayOutEntityTeleport_YAW = getFields(PacketPlayOutEntityTeleport, byte.class).get(0);
PacketPlayOutEntityTeleport_PITCH = getFields(PacketPlayOutEntityTeleport, byte.class).get(1);
if (minorVersion >= 17 || serverVersion.getMinorVersion() >= 17) {
newPacketPlayOutEntityTeleport = PacketPlayOutEntityTeleport.getConstructor(Entity);
} else {
newPacketPlayOutEntityTeleport = PacketPlayOutEntityTeleport.getConstructor();
}
if (minorVersion >= 9) {
PacketPlayOutEntityTeleport_X = getFields(PacketPlayOutEntityTeleport, double.class).get(0);
PacketPlayOutEntityTeleport_Y = getFields(PacketPlayOutEntityTeleport, double.class).get(1);
PacketPlayOutEntityTeleport_Z = getFields(PacketPlayOutEntityTeleport, double.class).get(2);
} else {
PacketPlayOutEntityTeleport_X = getFields(PacketPlayOutEntityTeleport, int.class).get(1);
PacketPlayOutEntityTeleport_Y = getFields(PacketPlayOutEntityTeleport, int.class).get(2);
PacketPlayOutEntityTeleport_Z = getFields(PacketPlayOutEntityTeleport, int.class).get(3);
}
}
protected void playerListHeaderFooter() throws ReflectiveOperationException {
if (minorVersion < 8) return;
PacketPlayOutPlayerListHeaderFooter_HEADER = getFields(PacketPlayOutPlayerListHeaderFooter, IChatBaseComponent).get(0);
PacketPlayOutPlayerListHeaderFooter_FOOTER = getFields(PacketPlayOutPlayerListHeaderFooter, IChatBaseComponent).get(1);
if (minorVersion >= 17 || serverVersion.getMinorVersion() >= 17) {
newPacketPlayOutPlayerListHeaderFooter = PacketPlayOutPlayerListHeaderFooter.getConstructor(IChatBaseComponent, IChatBaseComponent);
} else {
newPacketPlayOutPlayerListHeaderFooter = PacketPlayOutPlayerListHeaderFooter.getConstructor();
}
}
protected void otherEntity() throws ReflectiveOperationException {
PacketPlayOutEntity_ENTITYID = getFields(PacketPlayOutEntity, int.class).get(0);
PacketPlayOutEntityDestroy_ENTITIES = setAccessible(PacketPlayOutEntityDestroy.getDeclaredFields()[0]);
newPacketPlayOutEntityMetadata = PacketPlayOutEntityMetadata.getConstructor(int.class, DataWatcher, boolean.class);
PacketPlayOutEntityMetadata_LIST = getFields(PacketPlayOutEntityMetadata, List.class).get(0);
PacketPlayOutNamedEntitySpawn_ENTITYID = getFields(PacketPlayOutNamedEntitySpawn, int.class).get(0);
if (minorVersion >= 7) {
PacketPlayInUseEntity_ENTITY = getFields(PacketPlayInUseEntity, int.class).get(0);
PacketPlayInUseEntity_ACTION = getFields(PacketPlayInUseEntity, EnumEntityUseAction).get(0);
}
try {
newPacketPlayOutEntityDestroy = PacketPlayOutEntityDestroy.getConstructor(int[].class);
} catch (NoSuchMethodException e) {
//1.17.0
newPacketPlayOutEntityDestroy = PacketPlayOutEntityDestroy.getConstructor(int.class);
}
}
protected void dataWatcher() throws ReflectiveOperationException {
newDataWatcher = DataWatcher.getConstructors()[0];
DataWatcherItem_VALUE = getFields(DataWatcherItem, Object.class).get(0);
if (minorVersion >= 9) {
newDataWatcherObject = DataWatcherObject.getConstructor(int.class, DataWatcherSerializer);
DataWatcherItem_TYPE = getFields(DataWatcherItem, DataWatcherObject).get(0);
DataWatcherObject_SLOT = getFields(DataWatcherObject, int.class).get(0);
DataWatcherObject_SERIALIZER = getFields(DataWatcherObject, DataWatcherSerializer).get(0);
} else {
DataWatcherItem_TYPE = getFields(DataWatcherItem, int.class).get(1);
}
}
protected void scoreboard() throws ReflectiveOperationException {
newScoreboardObjective = ScoreboardObjective.getConstructors()[0];
newScoreboard = Scoreboard.getConstructor();
emptyScoreboard = newScoreboard.newInstance();
newScoreboardScore = ScoreboardScore.getConstructor(Scoreboard, ScoreboardObjective, String.class);
newPacketPlayOutScoreboardDisplayObjective = PacketPlayOutScoreboardDisplayObjective.getConstructor(int.class, ScoreboardObjective);
PacketPlayOutScoreboardDisplayObjective_POSITION = getFields(PacketPlayOutScoreboardDisplayObjective, int.class).get(0);
PacketPlayOutScoreboardDisplayObjective_OBJECTIVENAME = getFields(PacketPlayOutScoreboardDisplayObjective, String.class).get(0);
PacketPlayOutScoreboardObjective_OBJECTIVENAME = getFields(PacketPlayOutScoreboardObjective, String.class).get(0);
IScoreboardCriteria_self = getFields(IScoreboardCriteria, IScoreboardCriteria).get(0);
List<Field> list = getFields(PacketPlayOutScoreboardObjective, int.class);
PacketPlayOutScoreboardObjective_METHOD = list.get(list.size()-1);
Class<?> EnumScoreboardAction = null;
if (minorVersion >= 8) {
EnumScoreboardHealthDisplay = getNMSClass("net.minecraft.world.scores.criteria.IScoreboardCriteria$EnumScoreboardHealthDisplay", "IScoreboardCriteria$EnumScoreboardHealthDisplay", "EnumScoreboardHealthDisplay");
EnumScoreboardHealthDisplay_values = getEnumValues(EnumScoreboardHealthDisplay);
EnumScoreboardAction = getNMSClass("net.minecraft.server.ScoreboardServer$Action", "ScoreboardServer$Action", "PacketPlayOutScoreboardScore$EnumScoreboardAction", "EnumScoreboardAction");
EnumScoreboardAction_values = getEnumValues(EnumScoreboardAction);
PacketPlayOutScoreboardObjective_RENDERTYPE = getFields(PacketPlayOutScoreboardObjective, EnumScoreboardHealthDisplay).get(0);
}
@@ -440,36 +412,23 @@ public final class NMSStorage {
}
}
private void initializeTeamPackets() throws ReflectiveOperationException {
PacketPlayOutScoreboardTeam = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutScoreboardTeam", "PacketPlayOutScoreboardTeam", "Packet209SetScoreboardTeam");
Class<?> ScoreboardTeam = getNMSClass("net.minecraft.world.scores.ScoreboardTeam", "ScoreboardTeam");
protected void scoreboardTeam() throws ReflectiveOperationException {
newScoreboardTeam = ScoreboardTeam.getConstructor(Scoreboard, String.class);
PacketPlayOutScoreboardTeam_NAME = getFields(PacketPlayOutScoreboardTeam, String.class).get(0);
PacketPlayOutScoreboardTeam_ACTION = getInstanceFields(PacketPlayOutScoreboardTeam, int.class).get(0);
PacketPlayOutScoreboardTeam_PLAYERS = getFields(PacketPlayOutScoreboardTeam, Collection.class).get(0);
ScoreboardTeam_getPlayerNameSet = getMethods(ScoreboardTeam, Collection.class).get(0);
ScoreboardTeam_setAllowFriendlyFire = getMethod(ScoreboardTeam, new String[]{"setAllowFriendlyFire", "a", "func_96660_a"}, boolean.class);
ScoreboardTeam_setCanSeeFriendlyInvisibles = getMethod(ScoreboardTeam, new String[]{"setCanSeeFriendlyInvisibles", "b", "func_98300_b"}, boolean.class);
if (minorVersion >= 8) {
Class<?> EnumNameTagVisibility = getNMSClass("net.minecraft.world.scores.ScoreboardTeamBase$EnumNameTagVisibility", "ScoreboardTeamBase$EnumNameTagVisibility", "EnumNameTagVisibility");
EnumNameTagVisibility_values = getEnumValues(EnumNameTagVisibility);
ScoreboardTeam_setNameTagVisibility = getMethod(ScoreboardTeam, new String[]{"setNameTagVisibility", "a", "method_1149"}, EnumNameTagVisibility);
}
if (minorVersion >= 9) {
Class<?> EnumTeamPush = getNMSClass("net.minecraft.world.scores.ScoreboardTeamBase$EnumTeamPush", "ScoreboardTeamBase$EnumTeamPush");
EnumTeamPush_values = getEnumValues(EnumTeamPush);
ScoreboardTeam_setCollisionRule = getMethods(ScoreboardTeam, void.class, EnumTeamPush).get(0);
}
if (minorVersion >= 13) {
ScoreboardTeam_setPrefix = getMethod(ScoreboardTeam, new String[]{"setPrefix", "method_1138", "b"}, IChatBaseComponent);
ScoreboardTeam_setSuffix = getMethod(ScoreboardTeam, new String[]{"setSuffix", "method_1139", "c"}, IChatBaseComponent);
ScoreboardTeam_setColor = getMethods(ScoreboardTeam, void.class, EnumChatFormat).get(0);
} else {
ScoreboardTeam_setPrefix = getMethod(ScoreboardTeam, new String[]{"setPrefix", "func_96666_b"}, String.class);
ScoreboardTeam_setSuffix = getMethod(ScoreboardTeam, new String[]{"setSuffix", "func_96662_c"}, String.class);
}
if (minorVersion >= 17 || serverVersion.getMinorVersion() >= 17) {
Class<?> PacketPlayOutScoreboardTeam_PlayerAction = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutScoreboardTeam$a");
if (minorVersion >= 17) {
PacketPlayOutScoreboardTeam_of = getMethods(PacketPlayOutScoreboardTeam, PacketPlayOutScoreboardTeam, ScoreboardTeam).get(0);
PacketPlayOutScoreboardTeam_ofBoolean = getMethods(PacketPlayOutScoreboardTeam, PacketPlayOutScoreboardTeam, ScoreboardTeam, boolean.class).get(0);
PacketPlayOutScoreboardTeam_ofString = getMethods(PacketPlayOutScoreboardTeam, PacketPlayOutScoreboardTeam, ScoreboardTeam, String.class, PacketPlayOutScoreboardTeam_PlayerAction).get(0);
@@ -479,53 +438,9 @@ public final class NMSStorage {
}
}
/**
* 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
*/
private Class<?> getNMSClass(String fullPath_1_17, String... names) throws ClassNotFoundException {
if (minorVersion >= 17) {
return Class.forName(fullPath_1_17);
}
for (String name : names) {
try {
return getLegacyClass(name);
} catch (ClassNotFoundException e) {
//not the first class name in array
}
}
throw new ClassNotFoundException("No class found with possible names {modern = " + fullPath_1_17 + ", legacy = " + Arrays.toString(names) + "}");
}
public abstract void loadClasses() throws ClassNotFoundException;
/**
* Returns class from given name
*
* @param name
* class name
* @return class from given name
* @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;
throw new ClassNotFoundException(name);
} catch (ClassNotFoundException | NullPointerException e1) {
//maybe fabric?
return Class.forName(name);
}
}
}
public abstract void loadNamedFieldsAndMethods() throws ReflectiveOperationException;
/**
* Returns method with specified possible names and parameters. Throws exception if no such method was found
@@ -540,7 +455,7 @@ public final class NMSStorage {
* @throws NoSuchMethodException
* if no such method exists
*/
private Method getMethod(Class<?> clazz, String[] names, Class<?>... parameterTypes) throws NoSuchMethodException {
protected Method getMethod(Class<?> clazz, String[] names, Class<?>... parameterTypes) throws NoSuchMethodException {
for (String name : names) {
try {
return getMethod(clazz, name, parameterTypes);
@@ -565,7 +480,7 @@ public final class NMSStorage {
Arrays.toString(parameterTypes) + " in class " + clazz.getName() + ". Methods with matching parameters: " + list);
}
private Method getMethod(Class<?> clazz, String name, Class<?>... parameterTypes) throws NoSuchMethodException {
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;
@@ -583,7 +498,7 @@ public final class NMSStorage {
throw new NoSuchMethodException("No method found with name " + name + " in class " + clazz.getName() + " with parameters " + Arrays.toString(parameterTypes));
}
private List<Method> getMethods(Class<?> clazz, Class<?> returnType, Class<?>... parameterTypes){
protected List<Method> getMethods(Class<?> clazz, Class<?> returnType, Class<?>... parameterTypes){
List<Method> list = new ArrayList<>();
for (Method m : clazz.getDeclaredMethods()) {
if (m.getReturnType() != returnType || m.getParameterCount() != parameterTypes.length || !Modifier.isPublic(m.getModifiers())) continue;
@@ -609,7 +524,7 @@ public final class NMSStorage {
* field type to check for
* @return list of all fields with specified class type
*/
private List<Field> getFields(Class<?> clazz, Class<?> type){
protected List<Field> getFields(Class<?> clazz, Class<?> type){
if (clazz == null) throw new IllegalArgumentException("Source class cannot be null");
List<Field> list = new ArrayList<>();
for (Field field : clazz.getDeclaredFields()) {
@@ -651,7 +566,7 @@ public final class NMSStorage {
* @throws NoSuchFieldException
* if field was not found
*/
private Field getField(Class<?> clazz, String name) throws NoSuchFieldException {
protected Field getField(Class<?> clazz, String name) throws NoSuchFieldException {
for (Field f : clazz.getDeclaredFields()) {
if (f.getName().equals(name) || (f.getName().split("_").length == 3 && f.getName().split("_")[2].equals(name))) {
return setAccessible(f);
@@ -660,7 +575,7 @@ public final class NMSStorage {
throw new NoSuchFieldException("Field \"" + name + "\" was not found in class " + clazz.getName());
}
private Field getField(Class<?> clazz, String... potentialNames) throws NoSuchFieldException {
protected Field getField(Class<?> clazz, String... potentialNames) throws NoSuchFieldException {
for (String name : potentialNames) {
try {
return getField(clazz, name);
@@ -671,14 +586,13 @@ public final class NMSStorage {
throw new NoSuchFieldException("No field found in class " + clazz.getName() + " with potential names " + Arrays.toString(potentialNames));
}
private Enum[] getEnumValues(Class<?> enumClass) {
protected Enum[] getEnumValues(Class<?> enumClass) {
if (enumClass == null) throw new IllegalArgumentException("Class cannot be null");
if (!enumClass.isEnum()) throw new IllegalArgumentException(enumClass.getName() + " is not an enum class");
try {
return (Enum[]) enumClass.getMethod("values").invoke(null);
} catch (ReflectiveOperationException e) {
//this should never happen
TAB.getInstance().getErrorManager().criticalError("Failed to load enum constants of " + enumClass.getName(), e);
return new Enum[0];
}
}
@@ -699,4 +613,26 @@ public final class NMSStorage {
o.setAccessible(true);
return o;
}
/**
* Gets values of all static fields in a class
*
* @param clazz
* class to return field values from
* @return map of values
*/
public Map<String, Object> getStaticFields(Class<?> clazz){
Map<String, Object> fields = new HashMap<>();
for (Field field : clazz.getDeclaredFields()) {
if (Modifier.isStatic(field.getModifiers())) {
setAccessible(field);
try {
fields.put(field.getName(), field.get(null));
} catch (IllegalAccessException e) {
//this will never happen
}
}
}
return fields;
}
}
@@ -1,13 +1,14 @@
package me.neznamy.tab.platforms.bukkit.nms.datawatcher;
import java.util.Optional;
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.shared.TAB;
import java.util.Optional;
/**
* A class to help to assign DataWatcher items as positions often change per-version
*/
@@ -39,16 +40,16 @@ public class DataWatcherHelper {
* @return armor stand flags position based on server version
*/
private int getArmorStandFlagsPosition() {
if (TAB.getInstance().getServerVersion().getMinorVersion() >= 17) {
//1.17.x, 1.18.x
if (TabAPI.getInstance().getServerVersion().getMinorVersion() >= 17) {
//1.17.x, 1.18.x, 1.19.x
return 15;
} else if (TAB.getInstance().getServerVersion().getMinorVersion() >= 15) {
} else if (TabAPI.getInstance().getServerVersion().getMinorVersion() >= 15) {
//1.15.x, 1.16.x
return 14;
} else if (TAB.getInstance().getServerVersion().getMinorVersion() >= 14) {
} else if (TabAPI.getInstance().getServerVersion().getMinorVersion() >= 14) {
//1.14.x
return 13;
} else if (TAB.getInstance().getServerVersion().getMinorVersion() >= 10) {
} else if (TabAPI.getInstance().getServerVersion().getMinorVersion() >= 10) {
//1.10.x - 1.13.x
return 11;
} else {
@@ -76,18 +77,18 @@ public class DataWatcherHelper {
* client version
*/
public void setCustomName(String customName, ProtocolVersion clientVersion) {
if (TAB.getInstance().getServerVersion().getMinorVersion() >= 13) {
if (TabAPI.getInstance().getServerVersion().getMinorVersion() >= 13) {
try {
data.setValue(new DataWatcherObject(2, registry.getOptionalComponent()), Optional.ofNullable(((BukkitPacketBuilder)TAB.getInstance().getPlatform().getPacketBuilder()).toNMSComponent(IChatBaseComponent.optimizedComponent(customName), clientVersion)));
} catch (ReflectiveOperationException e) {
TAB.getInstance().getErrorManager().printError("Failed to create component", e);
}
} else if (TAB.getInstance().getServerVersion().getMinorVersion() >= 8){
} else if (TabAPI.getInstance().getServerVersion().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);
if (TAB.getInstance().getServerVersion().getMinorVersion() >= 6){
if (TabAPI.getInstance().getServerVersion().getMinorVersion() >= 6){
data.setValue(new DataWatcherObject(10, null), cutName);
} else {
data.setValue(new DataWatcherObject(5, null), cutName);
@@ -102,7 +103,7 @@ public class DataWatcherHelper {
* if visible or not
*/
public void setCustomNameVisible(boolean visible) {
if (TAB.getInstance().getServerVersion().getMinorVersion() >= 9) {
if (TabAPI.getInstance().getServerVersion().getMinorVersion() >= 9) {
data.setValue(new DataWatcherObject(3, registry.getBoolean()), visible);
} else {
data.setValue(new DataWatcherObject(3, null), (byte)(visible?1:0));
@@ -116,7 +117,7 @@ public class DataWatcherHelper {
* health of entity
*/
public void setHealth(float health) {
if (TAB.getInstance().getServerVersion().getMinorVersion() >= 6) {
if (TabAPI.getInstance().getServerVersion().getMinorVersion() >= 6) {
data.setValue(new DataWatcherObject(6, registry.getFloat()), health);
} else {
data.setValue(new DataWatcherObject(16, null), (int)health);
@@ -132,4 +133,15 @@ public class DataWatcherHelper {
public void setArmorStandFlags(byte flags) {
data.setValue(new DataWatcherObject(armorStandFlagsPosition, registry.getByte()), flags);
}
/**
* Writes wither invulnerable time
* @param time
* Time, apparently
*/
public void setWitherInvulnerableTime(int time) {
if (TAB.getInstance().getServerVersion().getMinorVersion() > 8)
throw new UnsupportedOperationException("Not supported on 1.9+");
data.setValue(new DataWatcherObject(20, null), time);
}
}
@@ -1,8 +1,8 @@
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.shared.TAB;
public class DataWatcherItem {
@@ -38,7 +38,7 @@ public class DataWatcherItem {
*/
public static DataWatcherItem fromNMS(Object nmsItem) throws ReflectiveOperationException {
NMSStorage nms = NMSStorage.getInstance();
if (TAB.getInstance().getServerVersion().getMinorVersion() >= 9) {
if (TabAPI.getInstance().getServerVersion().getMinorVersion() >= 9) {
Object nmsObject = nms.DataWatcherItem_TYPE.get(nmsItem);
return new DataWatcherItem(new DataWatcherObject(nms.DataWatcherObject_SLOT.getInt(nmsObject), nms.DataWatcherObject_SERIALIZER.get(nmsObject)), nms.DataWatcherItem_VALUE.get(nmsItem));
} else {
@@ -1,12 +1,9 @@
package me.neznamy.tab.platforms.bukkit.nms.datawatcher;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
import me.neznamy.tab.platforms.bukkit.nms.NMSStorage;
import java.util.Map;
/**
* A class representing the n.m.s.DataWatcherRegistry class to make work with it much easier
*/
@@ -23,39 +20,27 @@ public class DataWatcherRegistry {
*/
public DataWatcherRegistry(NMSStorage nms) {
if (nms.getMinorVersion() >= 9) {
Map<String, Object> fields = getStaticFields(nms.DataWatcherRegistry, nms);
registryByte = fields.get("a");
registryFloat = fields.get("c");
registryString = fields.get("d");
if (nms.getMinorVersion() >= 13) {
registryOptionalIChatBaseComponent = fields.get("f");
registryBoolean = fields.get("i");
} else {
registryBoolean = fields.get("h");
}
}
}
/**
* Gets values of all static fields in a class
*
* @param clazz
* class to return field values from
* @return map of values
*/
private Map<String, Object> getStaticFields(Class<?> clazz, NMSStorage nms){
Map<String, Object> fields = new HashMap<>();
for (Field field : clazz.getDeclaredFields()) {
if (Modifier.isStatic(field.getModifiers())) {
nms.setAccessible(field);
try {
fields.put(field.getName(), field.get(null));
} catch (IllegalAccessException e) {
//this will never happen
Map<String, Object> fields = nms.getStaticFields(nms.DataWatcherRegistry);
if (fields.containsKey("a")) {
// Bukkit mapping
registryByte = fields.get("a");
registryFloat = fields.get("c");
registryString = fields.get("d");
if (nms.getMinorVersion() >= 13) {
registryOptionalIChatBaseComponent = fields.get("f");
registryBoolean = fields.get("i");
} else {
registryBoolean = fields.get("h");
}
} else {
// Mojang mapping
registryByte = fields.get("BYTE");
registryFloat = fields.get("FLOAT");
registryString = fields.get("STRING");
registryOptionalIChatBaseComponent = fields.get("OPTIONAL_COMPONENT");
registryBoolean = fields.get("BOOLEAN");
}
}
return fields;
}
public Object getByte() {
@@ -1,6 +1,6 @@
package me.neznamy.tab.platforms.bukkit.permission;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
import org.bukkit.entity.Player;
import me.neznamy.tab.api.TabPlayer;
@@ -55,7 +55,6 @@ scoreboard-teams:
enabled: false
use-marker-tag-for-1-8-x-clients: false
disable-on-boats: true
space-between-lines: 0.22
disable-in-worlds:
- disabledworld
dynamic-lines:
@@ -1,8 +1,7 @@
package me.neznamy.tab.platforms.bungeecord;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.shared.proxy.ProxyPlatform;
import me.neznamy.tab.api.TabAPI;
import me.neznamy.tab.api.TabConstants;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.ChatEvent;
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
@@ -16,6 +15,12 @@ import net.md_5.bungee.event.EventHandler;
*/
public class BungeeEventListener implements Listener {
private final BungeePlatform platform;
public BungeeEventListener(BungeePlatform platform) {
this.platform = platform;
}
/**
* Disconnect event listener to forward the event to all features
*
@@ -24,9 +29,9 @@ public class BungeeEventListener implements Listener {
*/
@EventHandler
public void onQuit(PlayerDisconnectEvent e){
if (TAB.getInstance().isDisabled()) return;
TAB.getInstance().getCPUManager().runTask(() ->
TAB.getInstance().getFeatureManager().onQuit(TAB.getInstance().getPlayer(e.getPlayer().getUniqueId())));
if (TabAPI.getInstance().isPluginDisabled()) return;
TabAPI.getInstance().getThreadManager().runTask(() ->
TabAPI.getInstance().getFeatureManager().onQuit(TabAPI.getInstance().getPlayer(e.getPlayer().getUniqueId())));
}
/**
@@ -37,12 +42,12 @@ public class BungeeEventListener implements Listener {
*/
@EventHandler
public void onSwitch(ServerSwitchEvent e){
if (TAB.getInstance().isDisabled()) return;
TAB.getInstance().getCPUManager().runTask(() -> {
if (TAB.getInstance().getPlayer(e.getPlayer().getUniqueId()) == null) {
TAB.getInstance().getFeatureManager().onJoin(new BungeeTabPlayer(e.getPlayer()));
if (TabAPI.getInstance().isPluginDisabled()) return;
TabAPI.getInstance().getThreadManager().runTask(() -> {
if (TabAPI.getInstance().getPlayer(e.getPlayer().getUniqueId()) == null) {
TabAPI.getInstance().getFeatureManager().onJoin(new BungeeTabPlayer(e.getPlayer()));
} else {
TAB.getInstance().getFeatureManager().onServerChange(e.getPlayer().getUniqueId(), e.getPlayer().getServer().getInfo().getName());
TabAPI.getInstance().getFeatureManager().onServerChange(e.getPlayer().getUniqueId(), e.getPlayer().getServer().getInfo().getName());
}
});
}
@@ -55,8 +60,9 @@ public class BungeeEventListener implements Listener {
*/
@EventHandler
public void onChat(ChatEvent e) {
if (TAB.getInstance().isDisabled()) return;
if (e.isCommand() && TAB.getInstance().getFeatureManager().onCommand(TAB.getInstance().getPlayer(((ProxiedPlayer)e.getSender()).getUniqueId()), e.getMessage())) e.setCancelled(true);
if (TabAPI.getInstance().isPluginDisabled()) return;
if (e.isCommand() && TabAPI.getInstance().getFeatureManager().onCommand(TabAPI.getInstance().getPlayer(
((ProxiedPlayer)e.getSender()).getUniqueId()), e.getMessage())) e.setCancelled(true);
}
/**
@@ -70,15 +76,8 @@ public class BungeeEventListener implements Listener {
if (!event.getTag().equals(TabConstants.PLUGIN_MESSAGE_CHANNEL_NAME)) return;
if (event.getReceiver() instanceof ProxiedPlayer) {
event.setCancelled(true);
TAB.getInstance().getCPUManager().getThreadPool().submit(() -> {
try {
while (TAB.getInstance().getPlayer(((ProxiedPlayer) event.getReceiver()).getUniqueId()) == null) {
Thread.sleep(100);
}
((ProxyPlatform)TAB.getInstance().getPlatform()).getPluginMessageHandler().onPluginMessage(
((ProxiedPlayer) event.getReceiver()).getUniqueId(), event.getData());
} catch (InterruptedException ignored) {}
});
platform.getPluginMessageHandler().onPluginMessage(
((ProxiedPlayer) event.getReceiver()).getUniqueId(), event.getData());
}
}
}
@@ -10,16 +10,10 @@ import me.neznamy.tab.api.protocol.*;
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 net.md_5.bungee.protocol.packet.BossBar;
import net.md_5.bungee.protocol.packet.Chat;
import net.md_5.bungee.protocol.packet.PlayerListHeaderFooter;
import net.md_5.bungee.protocol.packet.PlayerListItem;
import net.md_5.bungee.protocol.Property;
import net.md_5.bungee.protocol.packet.*;
import net.md_5.bungee.protocol.packet.PlayerListItem.Item;
import net.md_5.bungee.protocol.packet.ScoreboardDisplay;
import net.md_5.bungee.protocol.packet.ScoreboardObjective;
import net.md_5.bungee.protocol.packet.ScoreboardObjective.HealthDisplay;
import net.md_5.bungee.protocol.packet.ScoreboardScore;
import net.md_5.bungee.protocol.packet.Team;
/**
* Packet builder for BungeeCord platform
@@ -40,7 +34,11 @@ public class BungeePacketBuilder extends PacketBuilder {
@Override
public Object build(PacketPlayOutChat packet, ProtocolVersion clientVersion) {
return new Chat(packet.getMessage().toString(clientVersion), (byte) packet.getType().ordinal());
if (clientVersion.getMinorVersion() >= 19) {
return new SystemChat(packet.getMessage().toString(clientVersion), (byte) packet.getType().ordinal());
} else {
return new Chat(packet.getMessage().toString(clientVersion), (byte) packet.getType().ordinal());
}
}
@Override
@@ -55,14 +53,14 @@ public class BungeePacketBuilder extends PacketBuilder {
item.setDisplayName(data.getDisplayName().toLegacyText());
}
} else if (clientVersion.getMinorVersion() < 8) {
item.setDisplayName(data.getName()); //avoiding NPE, 1.7 client requires this, 1.8 added a leading boolean
item.setDisplayName(String.valueOf(data.getName())); //avoiding NPE, 1.7 client requires this, 1.8 added a leading boolean
}
if (data.getGameMode() != null) item.setGamemode(data.getGameMode().ordinal()-1);
item.setPing(data.getLatency());
if (data.getSkin() != null) {
item.setProperties(new String[][]{{"textures", data.getSkin().getValue(), data.getSkin().getSignature()}});
item.setProperties(new Property[]{new Property("textures", data.getSkin().getValue(), data.getSkin().getSignature())});
} else {
item.setProperties(new String[0][0]);
item.setProperties(new Property[0]);
}
item.setUsername(data.getName());
item.setUuid(data.getUniqueId());
@@ -109,7 +107,7 @@ public class BungeePacketBuilder extends PacketBuilder {
PlayerListItem item = (PlayerListItem) bungeePacket;
List<PlayerInfoData> listData = new ArrayList<>();
for (Item i : item.getItems()) {
Skin skin = i.getProperties() == null || i.getProperties().length == 0 ? null : new Skin(i.getProperties()[0][1], i.getProperties()[0][2]);
Skin skin = i.getProperties() == null || i.getProperties().length == 0 ? null : new Skin(i.getProperties()[0].getValue(), i.getProperties()[0].getSignature());
listData.add(new PlayerInfoData(i.getUsername(), i.getUuid(), skin, i.getPing(), EnumGamemode.VALUES[i.getGamemode()+1], IChatBaseComponent.deserialize(i.getDisplayName())));
}
return new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.valueOf(item.getAction().toString().replace("GAMEMODE", "GAME_MODE")), listData);
@@ -8,7 +8,7 @@ import io.netty.channel.ChannelPromise;
import me.neznamy.tab.api.TabFeature;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
import me.neznamy.tab.shared.features.PipelineInjector;
import me.neznamy.tab.shared.features.redis.RedisPlayer;
import net.md_5.bungee.api.connection.ProxiedPlayer;
@@ -2,7 +2,7 @@ package me.neznamy.tab.platforms.bungeecord;
import com.imaginarycode.minecraft.redisbungee.RedisBungeeAPI;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
import me.neznamy.tab.shared.proxy.ProxyPlatform;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.connection.ProxiedPlayer;
@@ -3,11 +3,12 @@ package me.neznamy.tab.platforms.bungeecord;
import de.myzelyam.api.vanish.BungeeVanishAPI;
import io.netty.channel.Channel;
import me.neznamy.tab.api.ProtocolVersion;
import me.neznamy.tab.api.TabConstants;
import me.neznamy.tab.api.protocol.Skin;
import me.neznamy.tab.api.util.Preconditions;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.shared.proxy.ProxyTabPlayer;
import net.md_5.bungee.api.ProxyConfig;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.protocol.DefinedPacket;
@@ -33,6 +34,9 @@ public class BungeeTabPlayer extends ProxyTabPlayer {
private static Object directionData;
private static Method getId;
/** Rewriting offline tablist uuids coming from backend servers to online uuids on online servers */
private static boolean tablistRewriteEnabled = true;
static {
try {
Class<?> initialHandler = Class.forName("net.md_5.bungee.connection.InitialHandler");
@@ -40,7 +44,7 @@ public class BungeeTabPlayer extends ProxyTabPlayer {
Class<?> channelWrapper = Class.forName("net.md_5.bungee.netty.ChannelWrapper");
ChannelWrapper_getHandle = channelWrapper.getMethod("getHandle");
Class<?> loginResult = Class.forName("net.md_5.bungee.connection.LoginResult");
Class<?> loginResult_Property = Class.forName("net.md_5.bungee.connection.LoginResult$Property");
Class<?> loginResult_Property = Class.forName("net.md_5.bungee.protocol.Property");
LoginResult_Property_getValue = loginResult_Property.getMethod("getValue");
LoginResult_Property_getSignature = loginResult_Property.getMethod("getSignature");
LoginResult_getProperties = loginResult.getMethod("getProperties");
@@ -56,6 +60,11 @@ public class BungeeTabPlayer extends ProxyTabPlayer {
} catch (ReflectiveOperationException e) {
TAB.getInstance().getErrorManager().criticalError("Failed to initialize bungee internal fields", e);
}
try {
tablistRewriteEnabled = !(boolean) ProxyConfig.class.getMethod("isDisableTabListRewrite").invoke(ProxyServer.getInstance().getConfig());
} catch (ReflectiveOperationException e) {
// not Waterfall, always true on BungeeCord
}
}
/**
@@ -65,7 +74,7 @@ public class BungeeTabPlayer extends ProxyTabPlayer {
* BungeeCord player
*/
public BungeeTabPlayer(ProxiedPlayer p) {
super(p, p.getUniqueId(), p.getName(), p.getServer() != null ? p.getServer().getInfo().getName() : "-", -1);
super(p, p.getUniqueId(), p.getName(), p.getServer() != null ? p.getServer().getInfo().getName() : "-", -1, tablistRewriteEnabled);
try {
channel = (Channel) ChannelWrapper_getHandle.invoke(wrapperField.get(getPlayer().getPendingConnection()));
} catch (IllegalAccessException | InvocationTargetException e) {
@@ -9,7 +9,7 @@ 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.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.chat.TextComponent;
@@ -26,12 +26,13 @@ public class Main extends Plugin {
@Override
public void onEnable(){
if (!isVersionSupported()) {
getLogger().info(EnumChatFormat.color("&cThe plugin requires BungeeCord build #1330 and up to work. Get it at https://ci.md-5.net/job/BungeeCord/"));
getLogger().info(EnumChatFormat.color("&cThe plugin requires BungeeCord build #1637 and up to work. Get it at https://ci.md-5.net/job/BungeeCord/"));
return;
}
BungeePlatform platform = new BungeePlatform();
ProxyServer.getInstance().registerChannel(TabConstants.PLUGIN_MESSAGE_CHANNEL_NAME);
TAB.setInstance(new TAB(new BungeePlatform(), ProtocolVersion.PROXY, getProxy().getVersion(), getDataFolder(), getLogger()));
getProxy().getPluginManager().registerListener(this, new BungeeEventListener());
TAB.setInstance(new TAB(platform, ProtocolVersion.PROXY, getProxy().getVersion(), getDataFolder(), getLogger()));
getProxy().getPluginManager().registerListener(this, new BungeeEventListener(platform));
getProxy().getPluginManager().registerCommand(this, new BTABCommand());
TAB.getInstance().load();
Metrics metrics = new Metrics(this, 10535);
@@ -46,7 +47,7 @@ public class Main extends Plugin {
*/
private boolean isVersionSupported() {
try {
Class.forName("net.md_5.bungee.protocol.packet.ScoreboardObjective$HealthDisplay");
Class.forName("net.md_5.bungee.protocol.Property");
return true;
} catch (ClassNotFoundException e) {
return false;
@@ -72,7 +73,7 @@ public class Main extends Plugin {
@Override
public void execute(CommandSender sender, String[] args) {
if (TAB.getInstance().isDisabled()) {
if (TAB.getInstance().isPluginDisabled()) {
for (String message : TAB.getInstance().getDisabledCommand().execute(args, sender.hasPermission(TabConstants.Permission.COMMAND_RELOAD), sender.hasPermission(TabConstants.Permission.COMMAND_ALL))) {
sender.sendMessage(new TextComponent(EnumChatFormat.color(message)));
}
@@ -2,7 +2,7 @@ package me.neznamy.tab.platforms.bungeecord;
import com.imaginarycode.minecraft.redisbungee.RedisBungeeAPI;
import com.imaginarycode.minecraft.redisbungee.events.PubSubMessageEvent;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
import me.neznamy.tab.shared.features.redis.RedisSupport;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.plugin.Listener;
@@ -61,7 +61,6 @@ scoreboard-teams:
enabled: false
use-marker-tag-for-1-8-x-clients: false
disable-on-boats: true
space-between-lines: 0.22
disable-in-worlds:
- disabledworld
disable-in-servers:
+1 -1
View File
@@ -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.1.1
projectVersion=3.1.3
# Gradle properties
org.gradle.daemon=true
+14 -12
View File
@@ -3,12 +3,13 @@ metadata.format.version = "1.1"
[versions]
# API
netty = "4.1.75.Final"
netty = "4.1.78.Final"
jsonSimple = "1.1.1"
snakeyaml = "1.30"
yamlAssist = "1.0.5"
gson = "2.9.0"
slf4j = "1.7.36"
minimessage = "4.11.0"
# General
luckperms = "5.4"
@@ -19,20 +20,19 @@ event = "3.0.0"
# Platforms
bukkit = "1.16.5-R0.1-SNAPSHOT"
bungeecord = "1.18-R0.1-SNAPSHOT"
bungeecord = "1.19-R0.1-SNAPSHOT"
krypton = "0.59.2"
velocity = "1.1.0"
velocity = "3.0.1"
# Platform extras
placeholderapi = "2.10.9"
placeholderapi = "2.11.1"
vault = "1.7"
via = "4.0.0"
authlib = "1.11"
bstats = "2.2.1"
libsDisguises = "10.0.26"
essentials = "2.19.2"
via = "4.3.1"
authlib = "1.5.25"
bstats = "3.0.0"
essentials = "2.19.4"
premiumVanish = "2.0.3"
redisBungee = "0.6.5-SNAPSHOT"
redisBungee = "0.7.2"
[libraries]
@@ -43,6 +43,9 @@ snakeyaml = { group = "org.yaml", name = "snakeyaml", version.ref = "snakeyaml"
yamlAssist = { group = "me.neznamy", name = "yamlassist", version.ref = "yamlAssist" }
gson = { group = "com.google.code.gson", name = "gson", version.ref = "gson" }
slf4j = { group = "org.slf4j", name = "slf4j-api", version.ref = "slf4j"}
adventureMiniMessage = { group = "net.kyori", name = "adventure-text-minimessage", version.ref = "minimessage" }
adventureApi = { group = "net.kyori", name = "adventure-api", version.ref = "minimessage" }
adventureLegacy = { group = "net.kyori", name = "adventure-text-serializer-legacy", version.ref = "minimessage" }
# General
luckperms = { group = "net.luckperms", name = "api", version.ref = "luckperms" }
@@ -64,10 +67,9 @@ placeholderapi = { group = "me.clip", name = "placeholderapi", version.ref = "pl
vault = { group = "com.github.MilkBowl", name = "VaultAPI", version.ref = "vault" }
via = { group = "com.viaversion", name = "viaversion-api", version.ref = "via" }
authlib = { group = "com.mojang", name = "authlib", version.ref = "authlib" }
libsDisguises = { group = "LibsDisguises", name = "LibsDisguises", version.ref = "libsDisguises" }
essentials = { group = "net.essentialsx", name = "EssentialsX", version.ref = "essentials" }
premiumVanish = { group = "com.github.MyzelYam", name = "PremiumVanishAPI", version.ref = "premiumVanish" }
redisBungee = { group = "com.imaginarycode.minecraft", name = "RedisBungee", version.ref = "redisBungee" }
redisBungee = { group = "com.github.limework.redisbungee", name = "RedisBungee-Bungee", version.ref = "redisBungee" }
# Metrics
bstats-bukkit = { group = "org.bstats", name = "bstats-bukkit", version.ref = "bstats" }
+1 -1
View File
@@ -8,7 +8,7 @@ val platforms = setOf(
rootProject.projects.bukkit,
rootProject.projects.bungeecord,
// rootProject.projects.krypton,
// rootProject.projects.velocity
rootProject.projects.velocity
).map { it.dependencyProject }
tasks {
+4 -3
View File
@@ -3,7 +3,7 @@ enableFeaturePreview("VERSION_CATALOGS")
dependencyResolutionManagement {
repositories {
mavenCentral() // Netty, SnakeYaml, json-simple, Gson, slf4j, Guava, Kyori event, bStats
mavenCentral() // Netty, SnakeYaml, json-simple, Gson, slf4j, Guava, Kyori event, bStats, AuthLib
maven("https://jitpack.io") // PremiumVanish
maven("https://repo.extendedclip.com/content/repositories/placeholderapi/") // PlaceholderAPI
maven("https://repo.viaversion.com/") // ViaVersion
@@ -11,7 +11,8 @@ dependencyResolutionManagement {
maven("https://repo.codemc.org/repository/maven-public/") // RedisBungee, BungeeCord
maven("https://repo.kryptonmc.org/releases") // YamlAssist, LuckPerms
maven("https://repo.opencollab.dev/maven-snapshots/") // Floodgate
maven("https://repo.purpurmc.org/snapshots") // Purpur, LibsDisguises, AuthLib, Vault
maven("https://repo.purpurmc.org/snapshots") // Purpur, Vault
maven("https://repo.papermc.io/repository/maven-public/") // Velocity
}
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
}
@@ -25,7 +26,7 @@ rootProject.name = "TAB"
include(":api")
include(":shared")
//include(":krypton")
//include(":velocity")
include(":velocity")
include(":bukkit")
include(":bungeecord")
include(":jar")
+1 -10
View File
@@ -1,7 +1,3 @@
plugins {
id("net.kyori.blossom") version "1.2.0"
}
dependencies {
api(projects.api)
api(libs.event) {
@@ -12,9 +8,4 @@ dependencies {
compileOnlyApi(libs.guava)
compileOnlyApi(libs.floodgate)
compileOnlyApi(libs.slf4j)
}
blossom {
replaceToken("@plugin_version@", project.version)
replaceTokenIn("src/main/java/me/neznamy/tab/shared/TabConstants.java")
}
}
@@ -9,7 +9,6 @@ import java.util.concurrent.atomic.AtomicLong;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import me.neznamy.tab.api.TabFeature;
import me.neznamy.tab.api.task.RepeatingTask;
import me.neznamy.tab.api.task.ThreadManager;
/**
@@ -48,7 +47,7 @@ public class CpuManager implements ThreadManager {
private 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 ThreadPoolExecutor threadPool = (ThreadPoolExecutor) Executors.newCachedThreadPool(
private final ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(20,
new ThreadFactoryBuilder().setNameFormat("TAB Repeating / Delayed Thread %d").build());
/** Tasks submitted to main thread before plugin was fully enabled */
@@ -359,34 +358,22 @@ public class CpuManager implements ThreadManager {
}
@Override
public RepeatingTask startRepeatingMeasuredTask(int intervalMilliseconds, TabFeature feature, String type, Runnable task) {
return new TabRepeatingTask(threadPool, task, feature, type, intervalMilliseconds);
public Future<?> startRepeatingMeasuredTask(int intervalMilliseconds, TabFeature feature, String type, Runnable task) {
return threadPool.scheduleAtFixedRate(() -> runMeasuredTask(feature, type, task), 0, intervalMilliseconds, TimeUnit.MILLISECONDS);
}
@Override
public RepeatingTask startRepeatingTask(int intervalMilliseconds, Runnable task) {
return new TabRepeatingTask(threadPool, task, null, null, intervalMilliseconds);
public Future<?> startRepeatingTask(int intervalMilliseconds, Runnable task) {
return threadPool.scheduleAtFixedRate(() -> runTask(task), 0, intervalMilliseconds, TimeUnit.MILLISECONDS);
}
@Override
public Future<?> runTaskLater(int delayMilliseconds, TabFeature feature, String type, Runnable task) {
try {
return threadPool.submit(() -> {
try {
Thread.sleep(delayMilliseconds);
runMeasuredTask(feature, type, task);
} catch (InterruptedException pluginDisabled) {
Thread.currentThread().interrupt();
}
});
} catch (OutOfMemoryError e) {
TAB.getInstance().getErrorManager().criticalError("Failed to create new delayed task, active thread count: " +
threadPool.getActiveCount() + " / " + threadPool.getPoolSize(), e);
return null;
}
return threadPool.schedule(() -> runMeasuredTask(feature, type, task), delayMilliseconds, TimeUnit.MILLISECONDS);
}
public ThreadPoolExecutor getThreadPool() {
return threadPool;
@Override
public Future<?> runTaskLater(int delayMilliseconds, Runnable task) {
return threadPool.schedule(() -> submit(task), delayMilliseconds, TimeUnit.MILLISECONDS);
}
}
@@ -9,6 +9,7 @@ import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.*;
import me.neznamy.tab.api.TabConstants;
import me.neznamy.tab.api.chat.EnumChatFormat;
import me.neznamy.tab.api.chat.IChatBaseComponent;
@@ -5,6 +5,7 @@ import java.util.Map;
import java.util.UUID;
import me.neznamy.tab.api.FeatureManager;
import me.neznamy.tab.api.TabConstants;
import me.neznamy.tab.api.TabFeature;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.api.placeholder.PlayerPlaceholder;
@@ -28,6 +29,10 @@ public class FeatureManagerImpl implements FeatureManager {
/** All registered features in an array to avoid memory allocations on iteration */
private TabFeature[] values = new TabFeature[0];
private boolean objectiveListeners = false;
private boolean displayObjectiveListeners = false;
/**
* Calls load() on all features.
* This function is called on plugin startup.
@@ -94,12 +99,7 @@ public class FeatureManagerImpl implements FeatureManager {
return pack;
}
/**
* Calls onQuit(TabPlayer) on all features
*
* @param disconnectedPlayer
* player who disconnected
*/
@Override
public void onQuit(TabPlayer disconnectedPlayer) {
if (disconnectedPlayer == null) return;
long millis = System.currentTimeMillis();
@@ -113,12 +113,7 @@ public class FeatureManagerImpl implements FeatureManager {
TAB.getInstance().debug("Player quit of " + disconnectedPlayer.getName() + " processed in " + (System.currentTimeMillis()-millis) + "ms");
}
/**
* Calls onJoin(TabPlayer) on all features
*
* @param connectedPlayer
* player who connected
*/
@Override
public void onJoin(TabPlayer connectedPlayer) {
if (!connectedPlayer.isOnline()) return;
long millis = System.currentTimeMillis();
@@ -142,14 +137,7 @@ public class FeatureManagerImpl implements FeatureManager {
}
}
/**
* Calls onWorldChange(TabPlayer, String, String) on all features
*
* @param playerUUID
* player who switched world
* @param to
* name of the new world
*/
@Override
public void onWorldChange(UUID playerUUID, String to) {
TabPlayer changed = TAB.getInstance().getPlayer(playerUUID);
if (changed == null) return;
@@ -164,14 +152,7 @@ public class FeatureManagerImpl implements FeatureManager {
((PlayerPlaceholder)TAB.getInstance().getPlaceholderManager().getPlaceholder(TabConstants.Placeholder.WORLD)).updateValue(changed, to);
}
/**
* Calls onServerChange(TabPlayer, String, String) on all features
*
* @param playerUUID
* player who switched server
* @param to
* name of the new server
*/
@Override
public void onServerChange(UUID playerUUID, String to) {
TabPlayer changed = TAB.getInstance().getPlayer(playerUUID);
if (changed == null) return;
@@ -188,15 +169,7 @@ public class FeatureManagerImpl implements FeatureManager {
((PlayerPlaceholder)TAB.getInstance().getPlaceholderManager().getPlaceholder(TabConstants.Placeholder.SERVER)).updateValue(changed, to);
}
/**
* Calls onCommand(TabPlayer, String) on all features
*
* @param sender
* command sender
* @param command
* command line including /
* @return {@code true} if command should be cancelled, {@code false} if not
*/
@Override
public boolean onCommand(TabPlayer sender, String command) {
if (sender == null) return false;
boolean cancel = false;
@@ -209,6 +182,16 @@ public class FeatureManagerImpl implements FeatureManager {
return cancel;
}
@Override
public void markObjective() {
objectiveListeners = true;
}
@Override
public void markDisplayObjective() {
displayObjectiveListeners = true;
}
/**
* Calls onPacketReceive(TabPlayer, Object) on all features
*
@@ -281,6 +264,7 @@ public class FeatureManagerImpl implements FeatureManager {
* if reflective operation fails
*/
public void onDisplayObjective(TabPlayer packetReceiver, Object packet) throws ReflectiveOperationException {
if (!displayObjectiveListeners) return;
long time = System.nanoTime();
PacketPlayOutScoreboardDisplayObjective display = TAB.getInstance().getPlatform().getPacketBuilder().readDisplayObjective(packet);
TAB.getInstance().getCPUManager().addTime(TabConstants.Feature.PACKET_DESERIALIZING, TabConstants.CpuUsageCategory.PACKET_DISPLAY_OBJECTIVE, System.nanoTime()-time);
@@ -301,6 +285,7 @@ public class FeatureManagerImpl implements FeatureManager {
* if reflective operation fails
*/
public void onObjective(TabPlayer packetReceiver, Object packet) throws ReflectiveOperationException {
if (!objectiveListeners) return;
long time = System.nanoTime();
PacketPlayOutScoreboardObjective display = TAB.getInstance().getPlatform().getPacketBuilder().readObjective(packet);
TAB.getInstance().getCPUManager().addTime(TabConstants.Feature.PACKET_DESERIALIZING, TabConstants.CpuUsageCategory.PACKET_OBJECTIVE, System.nanoTime()-time);
@@ -1,5 +1,6 @@
package me.neznamy.tab.shared;
import me.neznamy.tab.api.TabConstants;
import me.neznamy.tab.api.TabFeature;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.permission.PermissionPlugin;
@@ -1,12 +1,10 @@
package me.neznamy.tab.shared;
import java.nio.charset.StandardCharsets;
import java.util.*;
import io.netty.channel.Channel;
import me.neznamy.tab.api.Property;
import me.neznamy.tab.api.ProtocolVersion;
import me.neznamy.tab.api.TabFeature;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.api.*;
import me.neznamy.tab.api.chat.IChatBaseComponent;
import me.neznamy.tab.api.placeholder.PlayerPlaceholder;
import me.neznamy.tab.api.protocol.*;
@@ -31,6 +29,9 @@ public abstract class ITabPlayer implements TabPlayer {
/** Player's unique ID */
private final UUID uniqueId;
/** Player's tablist UUID */
private final UUID tabListId;
/**
* World the player is currently in, {@code "N/A"} if TAB is
* installed on proxy and bukkit bridge is not installed
@@ -94,8 +95,10 @@ public abstract class ITabPlayer implements TabPlayer {
* Player's world
* @param protocolVersion
* Player's game version
* @param useRealId
* Whether tablist uses real uuid or offline
*/
protected ITabPlayer(Object player, UUID uniqueId, String name, String server, String world, int protocolVersion) {
protected ITabPlayer(Object player, UUID uniqueId, String name, String server, String world, int protocolVersion, boolean useRealId) {
this.player = player;
this.uniqueId = uniqueId;
this.name = name;
@@ -105,6 +108,8 @@ public abstract class ITabPlayer implements TabPlayer {
this.version = ProtocolVersion.fromNetworkId(protocolVersion);
this.bedrockPlayer = TAB.getInstance().isFloodgateInstalled() && FloodgateApi.getInstance() != null && FloodgateApi.getInstance().isFloodgatePlayer(uniqueId);
this.permissionGroup = TAB.getInstance().getGroupManager().detectPermissionGroup(this);
UUID offlineId = UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(StandardCharsets.UTF_8));
this.tabListId = useRealId ? getUniqueId() : offlineId;
}
/**
@@ -241,12 +246,12 @@ public abstract class ITabPlayer implements TabPlayer {
} else {
component = new IChatBaseComponent(message);
}
sendCustomPacket(new PacketPlayOutChat(component, ChatMessageType.CHAT));
sendCustomPacket(new PacketPlayOutChat(component, ChatMessageType.SYSTEM));
}
@Override
public void sendMessage(IChatBaseComponent message) {
sendCustomPacket(new PacketPlayOutChat(message, ChatMessageType.CHAT));
sendCustomPacket(new PacketPlayOutChat(message, ChatMessageType.SYSTEM));
}
@Override
@@ -261,7 +266,7 @@ public abstract class ITabPlayer implements TabPlayer {
@Override
public UUID getTablistUUID() {
return uniqueId;
return tabListId;
}
@Override
@@ -286,7 +291,7 @@ public abstract class ITabPlayer implements TabPlayer {
}
@Override
public synchronized void sendCustomPacket(TabPacket packet) {
public void sendCustomPacket(TabPacket packet) {
if (packet == null) return;
//avoiding BungeeCord bug kicking all players
if (packet instanceof PacketPlayOutScoreboardTeam) {
@@ -188,7 +188,7 @@ public class TAB extends TabAPI {
if (configuration.getMysql() != null) configuration.getMysql().closeConnection();
featureManager.unload();
sendConsoleMessage("&aDisabled in " + (System.currentTimeMillis()-time) + "ms", true);
} catch (Exception e) {
} catch (Exception | NoClassDefFoundError e) {
errorManager.criticalError("Failed to disable", e);
}
kill();
@@ -337,15 +337,6 @@ public class TAB extends TabAPI {
return configuration;
}
/**
* Returns {@link #disabled}
*
* @return {@link #disabled}
*/
public boolean isDisabled() {
return disabled;
}
/**
* Returns {@link #command}
*
@@ -497,6 +488,11 @@ public class TAB extends TabAPI {
@Override
public void debug(String message) {
if (configuration.isDebugMode()) sendConsoleMessage("&9[DEBUG] " + message, true);
if (configuration != null && configuration.isDebugMode()) sendConsoleMessage("&9[DEBUG] " + message, true);
}
@Override
public boolean isPluginDisabled() {
return disabled;
}
}
@@ -1,100 +0,0 @@
package me.neznamy.tab.shared;
import me.neznamy.tab.api.TabFeature;
import me.neznamy.tab.api.task.RepeatingTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
/**
* Implementation of RepeatingTask interface which submits provided task
* to TAB's processing thread in configured interval.
*/
public class TabRepeatingTask implements RepeatingTask {
/** Executor service to submit the repeating task to */
private final ExecutorService exe;
/** Task to run periodically */
private final Runnable runnable;
/** Feature creating this task, used in cpu command output */
private final TabFeature feature;
/** Sub-feature creating this task, used in cpu command output */
private final String type;
/** Interval in milliseconds how often to submit the task to main thread */
private int interval;
/** Task pointer returned by executor service to allow this task to be cancelled */
private Future<?> task;
/**
* Constructs new instance with given parameters and starts the task.
*
* @param exe
* Executor service to submit the repeating task to
* @param runnable
* Task to run periodically
* @param feature
* Feature creating this task, used in cpu command output
* @param type
* Sub-feature creating this task, used in cpu command output
* @param interval
* Interval in milliseconds how often to submit the task to main thread
*/
public TabRepeatingTask(ExecutorService exe, Runnable runnable, TabFeature feature, String type, int interval) {
if (interval < 0) throw new IllegalArgumentException("Interval cannot be negative");
this.exe = exe;
this.runnable = runnable;
this.feature = feature;
this.type = type;
this.interval = interval;
createTask();
}
/**
* Creates the repeating task and submits it to executor service.
*/
private void createTask() {
task = exe.submit(() -> {
long nextLoop = System.currentTimeMillis();
while (true) {
try {
nextLoop += interval;
long sleep = nextLoop - System.currentTimeMillis();
if (sleep > interval) sleep = interval; //servers who travel back in time
if (sleep > 0) Thread.sleep(sleep);
if (feature != null) {
TAB.getInstance().getCPUManager().runMeasuredTask(feature, type, runnable);
} else {
TAB.getInstance().getCPUManager().runTask(runnable);
}
} catch (InterruptedException pluginDisabled) {
Thread.currentThread().interrupt();
break;
}
}
});
}
@Override
public int getInterval() {
return interval;
}
@Override
public void setInterval(int interval) {
if (interval < 0) throw new IllegalArgumentException("Interval cannot be negative");
//restarting task to break sleep in case of interval reduction
cancel();
this.interval = interval;
createTask();
}
@Override
public void cancel() {
task.cancel(true);
}
}
@@ -3,7 +3,7 @@ package me.neznamy.tab.shared.command;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.api.bossbar.BossBarManager;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
/**
* Handler for "/tab bossbar" subcommand
@@ -12,7 +12,7 @@ import me.neznamy.tab.api.chat.EnumChatFormat;
import me.neznamy.tab.api.chat.IChatBaseComponent;
import me.neznamy.tab.api.placeholder.Placeholder;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
/**
* Handler for "/tab cpu" subcommand
@@ -9,7 +9,7 @@ import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.api.chat.EnumChatFormat;
import me.neznamy.tab.shared.DynamicText;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
import me.neznamy.tab.shared.features.PlayerList;
import me.neznamy.tab.shared.features.nametags.NameTag;
@@ -5,7 +5,7 @@ import java.util.stream.Collectors;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
/**
* Handler for "/tab group" subcommand
@@ -41,11 +41,11 @@ public class GroupCommand extends PropertyCommand {
String server = null;
if (args[args.length-2].equals("-w")) {
world = args[args.length-1];
value = value.substring(0, value.length()-world.length()-4);
value = value.startsWith("-w") ? "" : value.substring(0, value.length()-world.length()-4);
}
if (args[args.length-2].equals("-s")) {
server = args[args.length-1];
value = value.substring(0, value.length()-server.length()-4);
value = value.startsWith("-s") ? "" : value.substring(0, value.length()-server.length()-4);
}
if ((value.startsWith("\"") && value.endsWith("\"")) || (value.startsWith("'") && value.endsWith("'"))) {
value = value.substring(1, value.length()-1);
@@ -2,7 +2,7 @@ package me.neznamy.tab.shared.command;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
/**
* Handler for "/tab groups" subcommand
@@ -3,7 +3,7 @@ package me.neznamy.tab.shared.command;
import me.neznamy.tab.api.PropertyConfiguration;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
import me.neznamy.tab.shared.config.Configs;
import me.neznamy.tab.shared.config.MySQL;
import me.neznamy.tab.shared.config.file.YamlPropertyConfigurationFile;
@@ -3,7 +3,7 @@ package me.neznamy.tab.shared.command;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.api.team.TeamManager;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
import me.neznamy.tab.shared.features.nametags.unlimited.NameTagX;
import java.util.Arrays;
@@ -11,7 +11,7 @@ import me.neznamy.tab.api.chat.IChatBaseComponent;
import me.neznamy.tab.api.placeholder.Placeholder;
import me.neznamy.tab.shared.DynamicText;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
/**
* Handler for "/tab parse <player> <placeholder>" subcommand
@@ -5,7 +5,7 @@ import java.util.List;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
/**
* Handler for "/tab player" subcommand
@@ -33,11 +33,11 @@ public class PlayerCommand extends PropertyCommand {
String server = null;
if (args[args.length-2].equals("-w")) {
world = args[args.length-1];
value = value.substring(0, value.length()-world.length()-4);
value = value.startsWith("-w") ? "" : value.substring(0, value.length()-world.length()-4);
}
if (args[args.length-2].equals("-s")) {
server = args[args.length-1];
value = value.substring(0, value.length()-server.length()-4);
value = value.startsWith("-s") ? "" : value.substring(0, value.length()-server.length()-4);
}
if ((value.startsWith("\"") && value.endsWith("\"")) || (value.startsWith("'") && value.endsWith("'"))) {
value = value.substring(1, value.length()-1);
@@ -5,7 +5,7 @@ import java.util.List;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
/**
* Handler for "/tab playeruuid" subcommand
@@ -38,11 +38,11 @@ public class PlayerUUIDCommand extends PropertyCommand {
String server = null;
if (args[args.length-2].equals("-w")) {
world = args[args.length-1];
value = value.substring(0, value.length()-world.length()-4);
value = value.startsWith("-w") ? "" : value.substring(0, value.length()-world.length()-4);
}
if (args[args.length-2].equals("-s")) {
server = args[args.length-1];
value = value.substring(0, value.length()-server.length()-4);
value = value.startsWith("-s") ? "" : value.substring(0, value.length()-server.length()-4);
}
if ((value.startsWith("\"") && value.endsWith("\"")) || (value.startsWith("'") && value.endsWith("'"))) {
value = value.substring(1, value.length()-1);
@@ -2,7 +2,7 @@ package me.neznamy.tab.shared.command;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
/**
* Handler for "/tab reload" subcommand
@@ -8,7 +8,7 @@ import java.util.List;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.api.scoreboard.Scoreboard;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
import me.neznamy.tab.shared.features.scoreboard.ScoreboardManagerImpl;
/**
@@ -40,6 +40,7 @@ public class ScoreboardCommand extends SubCommand {
return;
}
TabPlayer p = getTarget(sender, args);
if (p == null) return;
if (scoreboard.getOtherPluginScoreboards().containsKey(p)) return; //not overriding other plugins
boolean silent = args.length >= 3 && args[2].equals("-s");
switch(args[0]) {
@@ -88,6 +89,10 @@ public class ScoreboardCommand extends SubCommand {
sendMessage(sender, getMessages().getNoPermission());
return;
}
if (sender == null) {
sendMessage(sender, getMessages().getCommandOnlyFromGame());
return;
}
target = sender;
} else {
if (!hasPermission(sender,TabConstants.Permission.COMMAND_SCOREBOARD_SHOW_OTHER)) {
@@ -104,15 +109,20 @@ public class ScoreboardCommand extends SubCommand {
}
private TabPlayer getTarget(TabPlayer sender, String[] args) {
TabPlayer target = sender;
if (args.length >= 2 && TAB.getInstance().getPlayer(args[1]) != null) {
if (hasPermission(sender, TabConstants.Permission.COMMAND_SCOREBOARD_TOGGLE_OTHER)) {
target = TAB.getInstance().getPlayer(args[1]);
return TAB.getInstance().getPlayer(args[1]);
} else {
sendMessage(sender, getMessages().getNoPermission());
}
} else {
if (hasPermission(sender, TabConstants.Permission.COMMAND_SCOREBOARD_TOGGLE)) {
return sender;
} else {
sendMessage(sender, getMessages().getNoPermission());
}
}
return target;
return null;
}
private ScoreboardManagerImpl getScoreboardManager() {
@@ -7,7 +7,7 @@ import java.util.List;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.api.team.TeamManager;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
public class SetCollisionCommand extends SubCommand {
@@ -10,7 +10,7 @@ import java.util.stream.Collectors;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
import me.neznamy.tab.shared.config.MessageFile;
/**
* Abstract class representing a subcommand of "/tab" command
@@ -11,7 +11,7 @@ import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.api.chat.EnumChatFormat;
import me.neznamy.tab.api.chat.IChatBaseComponent;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
/**
* The core command handler
@@ -39,6 +39,7 @@ public class TabCommand extends SubCommand {
registerSubCommand(new SetCollisionCommand());
registerSubCommand(new ScoreboardCommand());
registerSubCommand(new WidthCommand());
//registerSubCommand(new WidthCheckCommand());
List<String> properties = Lists.newArrayList(TabConstants.Property.TABPREFIX, TabConstants.Property.TABSUFFIX, TabConstants.Property.TAGPREFIX, TabConstants.Property.TAGSUFFIX, TabConstants.Property.CUSTOMTABNAME, TabConstants.Property.ABOVENAME, TabConstants.Property.BELOWNAME, TabConstants.Property.CUSTOMTAGNAME);
properties.addAll(((DebugCommand) getSubcommands().get("debug")).getExtraLines());
SubCommand.setAllProperties(properties.toArray(new String[0]));
@@ -0,0 +1,100 @@
package me.neznamy.tab.shared.command;
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.IChatBaseComponent;
import me.neznamy.tab.shared.TAB;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Map;
import java.util.stream.Collectors;
/**
* Handler for "/tab width" subcommand
*/
public class WidthCheckCommand extends SubCommand {
private final byte[] widths = loadWidths();
/**
* Constructs new instance
*/
public WidthCheckCommand() {
super("widthcheck", TabConstants.Permission.COMMAND_WIDTH);
}
private byte[] loadWidths() {
byte[] widths = new byte[65536];
InputStream file = getClass().getClassLoader().getResourceAsStream("widths.txt");
if (file == null) {
TAB.getInstance().getErrorManager().criticalError("Failed to load widths.txt file. Is it inside the jar? Aligned suffix will not work.", null);
return widths;
}
int characterId = 1;
for (String line : new BufferedReader(new InputStreamReader(file)).lines().collect(Collectors.toList())) {
widths[characterId++] = (byte) Float.parseFloat(line);
}
Map<Integer, Integer> widthOverrides = TAB.getInstance().getConfiguration().getConfig().getConfigurationSection("tablist-name-formatting.character-width-overrides");
for (Map.Entry<Integer, Integer> entry : widthOverrides.entrySet()) {
widths[entry.getKey()] = entry.getValue().byteValue();
}
return widths;
}
@Override
public void execute(TabPlayer sender, String[] args) {
if (sender == null) {
sendMessage(null, getMessages().getCommandOnlyFromGame());
return;
}
if (args.length == 1) {
int i = Integer.parseInt(args[0]);
if (i > Character.MAX_VALUE) {
sendMessage(sender, "&cCharacter ID out of range: 0-" + (int) Character.MAX_VALUE);
return;
}
int ROWS = 15;
int COLUMNS = 10;
StringBuilder line = new StringBuilder();
for (int row = 0; row < ROWS; row++) {
line.append(".");
for (int column = 0; column < COLUMNS; column++) {
int character = row*COLUMNS+column + i;
if (character >= Character.MAX_VALUE) continue;
line.append(buildSpaces(21-widths[character]));
line.append((char)character);
line.append("&e|&r");
}
line.append(" ").append(row * COLUMNS + i).append("-").append((row + 1) * COLUMNS + i - 1).append("\n");
}
IChatBaseComponent msg = IChatBaseComponent.fromColoredText(line + "§7§l[Previous]");
msg.getModifier().onClickRunCommand("/tab widthcheck " + (i-ROWS*COLUMNS));
IChatBaseComponent next = new IChatBaseComponent(" §7§l[Next]");
next.getModifier().onClickRunCommand("/tab widthcheck " + (i+ROWS*COLUMNS));
msg.addExtra(next);
sender.sendMessage(msg);
}
}
private String buildSpaces(int pixelWidth) {
if (pixelWidth < 12) throw new IllegalArgumentException("Cannot build space lower than 12 pixels wide (" + pixelWidth + ")");
int pixelsLeft = pixelWidth;
StringBuilder output = new StringBuilder();
while (pixelsLeft % 5 != 0) {
pixelsLeft -= 4;
output.append(' ');
}
output.append(EnumChatFormat.COLOR_CHAR);
output.append('l');
while (pixelsLeft > 0) {
pixelsLeft -= 5;
output.append(' ');
}
output.append(EnumChatFormat.COLOR_CHAR);
output.append('r');
return output.toString();
}
}
@@ -4,7 +4,7 @@ import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.api.chat.EnumChatFormat;
import me.neznamy.tab.api.chat.IChatBaseComponent;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
import java.util.ArrayList;
import java.util.Arrays;
@@ -152,7 +152,7 @@ public class WidthCommand extends SubCommand {
public void sendWidth(TabPlayer sender, char character, int amount) {
List<IChatBaseComponent> messages = new ArrayList<>();
IChatBaseComponent charMessage = new IChatBaseComponent(EnumChatFormat.color("&2" + character + " &d|"));
IChatBaseComponent charMessage = new IChatBaseComponent(EnumChatFormat.color("|&2" + character + " &d|"));
messages.add(new IChatBaseComponent(EnumChatFormat.color("&b[TAB] Click the line with closest width &7(ID: &f" + (int) character + "&7)")));
@@ -188,7 +188,7 @@ public class WidthCommand extends SubCommand {
pixelsRemaining -= 2;
text.append('i');
}
IChatBaseComponent component = new IChatBaseComponent(EnumChatFormat.color("&b&k" + text + " &e|&b (" + width + " pixels) &7&l[Click to apply]"));
IChatBaseComponent component = new IChatBaseComponent(EnumChatFormat.color("|&b&k" + text + " &e|&b (" + width + " pixels) &7&l[Click to apply]"));
component.getModifier().onClickRunCommand("/tab width set " + c + " " + width);
component.getModifier().onHoverShowText(new IChatBaseComponent("Click to set width to " + width + " pixels"));
return component;
@@ -8,9 +8,8 @@ import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.api.bossbar.BossBar;
import me.neznamy.tab.api.bossbar.BossBarManager;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
import me.neznamy.tab.shared.command.SubCommand;
import me.neznamy.tab.shared.features.bossbar.BossBarLine;
/**
* Handler for "/tab announce bar" subcommand
@@ -48,7 +47,7 @@ public class AnnounceBarCommand extends SubCommand {
sendMessage(sender, getMessages().getBossBarNotFound(barName));
return;
}
if (!((BossBarLine)bar).isAnnouncementOnly()) {
if (!bar.isAnnouncementBar()) {
sendMessage(sender, getMessages().getBossBarNotMarkedAsAnnouncement());
return;
}
@@ -66,8 +65,9 @@ public class AnnounceBarCommand extends SubCommand {
if (b == null) return new ArrayList<>();
List<String> suggestions = new ArrayList<>();
if (arguments.length == 1) {
for (String bar : b.getRegisteredBossBars().keySet()) {
if (bar.toLowerCase().startsWith(arguments[0].toLowerCase())) suggestions.add(bar);
for (BossBar bar : b.getRegisteredBossBars().values()) {
if (bar.getName().toLowerCase().startsWith(arguments[0].toLowerCase()) &&
bar.isAnnouncementBar()) suggestions.add(bar.getName());
}
} else if (arguments.length == 2 && b.getBossBar(arguments[0]) != null){
for (String time : Arrays.asList("5", "10", "30", "60", "120")) {
@@ -8,7 +8,7 @@ import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.api.scoreboard.Scoreboard;
import me.neznamy.tab.api.scoreboard.ScoreboardManager;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
import me.neznamy.tab.shared.command.SubCommand;
/**
@@ -8,9 +8,8 @@ import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.api.bossbar.BossBar;
import me.neznamy.tab.api.bossbar.BossBarManager;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
import me.neznamy.tab.shared.command.SubCommand;
import me.neznamy.tab.shared.features.bossbar.BossBarLine;
/**
* Handler for "/tab announce bar" subcommand
@@ -53,7 +52,7 @@ public class SendBarCommand extends SubCommand {
sendMessage(sender, getMessages().getBossBarNotFound(barName));
return;
}
if (!((BossBarLine)bar).isAnnouncementOnly()) {
if (!bar.isAnnouncementBar()) {
sendMessage(sender, getMessages().getBossBarNotMarkedAsAnnouncement());
return;
}
@@ -4,7 +4,7 @@ import me.neznamy.tab.api.ProtocolVersion;
import me.neznamy.tab.api.config.ConfigurationFile;
import me.neznamy.tab.api.config.YamlConfigurationFile;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
import java.io.File;
import java.io.IOException;
@@ -5,7 +5,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
import org.yaml.snakeyaml.error.YAMLException;
import me.neznamy.tab.api.PropertyConfiguration;
@@ -2,7 +2,7 @@ package me.neznamy.tab.shared.config.mysql;
import me.neznamy.tab.api.PropertyConfiguration;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
import me.neznamy.tab.shared.config.MySQL;
import javax.sql.rowset.CachedRowSet;
@@ -11,7 +11,7 @@ import me.neznamy.tab.api.protocol.PacketPlayOutScoreboardObjective.EnumScoreboa
import me.neznamy.tab.api.protocol.PacketPlayOutScoreboardScore;
import me.neznamy.tab.api.protocol.PacketPlayOutScoreboardScore.Action;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
import me.neznamy.tab.shared.features.redis.RedisSupport;
/**
@@ -5,7 +5,7 @@ import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.api.protocol.PacketPlayOutPlayerInfo;
import me.neznamy.tab.api.protocol.PacketPlayOutPlayerInfo.EnumPlayerInfoAction;
import me.neznamy.tab.api.protocol.PacketPlayOutPlayerInfo.PlayerInfoData;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
import me.neznamy.tab.shared.TAB;
/**
@@ -10,7 +10,7 @@ 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.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
/**
* Feature handler for header and footer
@@ -12,7 +12,7 @@ import me.neznamy.tab.api.protocol.PacketPlayOutPlayerInfo.PlayerInfoData;
import me.neznamy.tab.api.protocol.PacketPlayOutScoreboardScore.Action;
import me.neznamy.tab.api.protocol.PacketPlayOutScoreboardTeam;
import me.neznamy.tab.shared.ITabPlayer;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.features.nametags.NameTag;
import me.neznamy.tab.shared.features.redis.RedisPlayer;
@@ -2,13 +2,19 @@ package me.neznamy.tab.shared.features;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import me.neznamy.tab.api.TabConstants;
import me.neznamy.tab.api.TabFeature;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.api.protocol.PacketPlayOutPlayerInfo;
import me.neznamy.tab.api.protocol.PacketPlayOutPlayerInfo.EnumPlayerInfoAction;
import me.neznamy.tab.api.protocol.PacketPlayOutPlayerInfo.PlayerInfoData;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.features.layout.Layout;
import me.neznamy.tab.shared.features.layout.LayoutManager;
import me.neznamy.tab.shared.features.layout.ParentGroup;
import me.neznamy.tab.shared.features.layout.PlayerSlot;
/**
* Sets ping of all players in the packet to configured value to prevent hacked clients from seeing exact ping value of each player
@@ -18,6 +24,8 @@ public class PingSpoof extends TabFeature {
//fake ping value
private final int value = TAB.getInstance().getConfiguration().getConfig().getInt("ping-spoof.value", 0);
private LayoutManager layoutManager;
/**
* Constructs new instance and loads config options
*/
@@ -31,11 +39,24 @@ public class PingSpoof extends TabFeature {
if (info.getAction() != EnumPlayerInfoAction.UPDATE_LATENCY && info.getAction() != EnumPlayerInfoAction.ADD_PLAYER) return;
for (PlayerInfoData playerInfoData : info.getEntries()) {
if (TAB.getInstance().getPlayerByTabListUUID(playerInfoData.getUniqueId()) != null) playerInfoData.setLatency(value);
if (layoutManager != null) {
Layout layout = layoutManager.getPlayerViews().get(receiver);
if (layout != null) {
for (ParentGroup group : layout.getGroups()) {
for (Map.Entry<Integer, PlayerSlot> entry : group.getPlayerSlots().entrySet()) {
if (layoutManager.getUUID(entry.getKey()) == playerInfoData.getUniqueId() && entry.getValue().getPlayer() != null) {
playerInfoData.setLatency(value);
}
}
}
}
}
}
}
@Override
public void load() {
layoutManager = (LayoutManager) TAB.getInstance().getFeatureManager().getFeature(TabConstants.Feature.LAYOUT);
updateAll(false);
}
@@ -3,6 +3,7 @@ package me.neznamy.tab.shared.features;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiFunction;
import java.util.function.Function;
@@ -18,8 +19,7 @@ import me.neznamy.tab.api.placeholder.PlaceholderManager;
import me.neznamy.tab.api.placeholder.PlayerPlaceholder;
import me.neznamy.tab.api.placeholder.RelationalPlaceholder;
import me.neznamy.tab.api.placeholder.ServerPlaceholder;
import me.neznamy.tab.api.task.RepeatingTask;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.event.impl.TabPlaceholderRegisterEvent;
import me.neznamy.tab.shared.placeholders.PlayerPlaceholderImpl;
@@ -47,7 +47,8 @@ public class PlaceholderManagerImpl extends TabFeature implements PlaceholderMan
private Placeholder[] usedPlaceholders = new Placeholder[0];
private final AtomicInteger atomic = new AtomicInteger();
private final RepeatingTask refreshTask = TAB.getInstance().getCPUManager().startRepeatingMeasuredTask(10000, this, "Refreshing placeholders", this::refresh);
private int refreshInterval = 10000;
private Future<?> refreshTask = TAB.getInstance().getCPUManager().startRepeatingMeasuredTask(refreshInterval, this, "Refreshing placeholders", this::refresh);
private TabExpansion tabExpansion;
@@ -56,7 +57,7 @@ public class PlaceholderManagerImpl extends TabFeature implements PlaceholderMan
}
private void refresh() {
int loopTime = atomic.addAndGet(refreshTask.getInterval());
int loopTime = atomic.addAndGet(refreshInterval);
int size = TAB.getInstance().getOnlinePlayers().length;
Map<TabPlayer, Set<TabFeature>> update = new HashMap<>(size);
Map<TabPlayer, Set<TabFeature>> forceUpdate = new HashMap<>(size);
@@ -219,6 +220,7 @@ public class PlaceholderManagerImpl extends TabFeature implements PlaceholderMan
return placeholders;
}
@Override
public TabPlaceholder getPlaceholder(String identifier) {
TabPlaceholder p = (TabPlaceholder) registeredPlaceholders.get(identifier);
if (p == null) {
@@ -251,10 +253,12 @@ public class PlaceholderManagerImpl extends TabFeature implements PlaceholderMan
}
}
if (p.getRefresh() % 50 == 0 && p.getRefresh() > 0) {
int refresh = gcd(p.getRefresh(), refreshTask.getInterval());
if (refreshTask.getInterval() != refresh) {
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.setInterval(refresh);
refreshTask.cancel(true);
refreshInterval = refresh;
refreshTask = TAB.getInstance().getCPUManager().startRepeatingMeasuredTask(refreshInterval, this, "Refreshing placeholders", this::refresh);
atomic.set(0);
}
}
@@ -14,7 +14,7 @@ import me.neznamy.tab.api.protocol.PacketPlayOutPlayerInfo;
import me.neznamy.tab.api.protocol.PacketPlayOutPlayerInfo.EnumPlayerInfoAction;
import me.neznamy.tab.api.protocol.PacketPlayOutPlayerInfo.PlayerInfoData;
import me.neznamy.tab.api.util.Preconditions;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.features.layout.Layout;
import me.neznamy.tab.shared.features.layout.LayoutManager;
@@ -10,7 +10,7 @@ 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.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
/**
* Cancelling GameMode change packet to spectator GameMode to avoid players being moved on
@@ -17,7 +17,11 @@ public interface TabExpansion {
}
default void setNameTagPreview(TabPlayer player, boolean previewing) {
setValue(player, "ntpreview", previewing ? "Enabled" : "Disabled");
setValue(player, "nametag_preview", previewing ? "Enabled" : "Disabled");
}
default void setNameTagVisibility(TabPlayer player, boolean visible) {
setValue(player, "nametag_visibility", visible ? "Enabled" : "Disabled");
}
default void setPlaceholderValue(TabPlayer player, String placeholder, String value) {
@@ -10,7 +10,7 @@ import me.neznamy.tab.api.protocol.PacketPlayOutScoreboardObjective.EnumScoreboa
import me.neznamy.tab.api.protocol.PacketPlayOutScoreboardScore;
import me.neznamy.tab.api.protocol.PacketPlayOutScoreboardScore.Action;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
import me.neznamy.tab.shared.features.redis.RedisSupport;
/**
@@ -3,15 +3,13 @@ package me.neznamy.tab.shared.features.alignedplayerlist;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.api.chat.IChatBaseComponent;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
import me.neznamy.tab.shared.features.PlayerList;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.*;
import java.util.Map.Entry;
import java.util.stream.Collectors;
@@ -42,9 +40,16 @@ public class AlignedPlayerList extends PlayerList {
widths[characterId++] = (byte) Float.parseFloat(line);
}
Map<Integer, Integer> widthOverrides = TAB.getInstance().getConfiguration().getConfig().getConfigurationSection("tablist-name-formatting.character-width-overrides");
List<Integer> redundant = new ArrayList<>();
for (Entry<Integer, Integer> entry : widthOverrides.entrySet()) {
widths[entry.getKey()] = entry.getValue().byteValue();
if (widths[entry.getKey()] == entry.getValue().byteValue()) {
redundant.add(entry.getKey());
} else {
widths[entry.getKey()] = entry.getValue().byteValue();
}
}
redundant.forEach(widthOverrides::remove);
if (!redundant.isEmpty()) TAB.getInstance().getConfig().save();
return widths;
}
@@ -114,8 +119,9 @@ public class AlignedPlayerList extends PlayerList {
@Override
public IChatBaseComponent getTabFormat(TabPlayer p, TabPlayer viewer) {
if (!playerViews.containsKey(viewer)) return null;
return playerViews.get(viewer).formatName(p);
PlayerView view = playerViews.get(viewer);
if (view == null) return null;
return view.formatName(p);
}
@Override
@@ -5,7 +5,7 @@ import me.neznamy.tab.api.chat.EnumChatFormat;
import me.neznamy.tab.api.chat.IChatBaseComponent;
import me.neznamy.tab.api.protocol.PacketPlayOutPlayerInfo;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
import java.util.Map;
import java.util.WeakHashMap;
@@ -9,7 +9,7 @@ import me.neznamy.tab.api.bossbar.BarStyle;
import me.neznamy.tab.api.bossbar.BossBar;
import me.neznamy.tab.api.protocol.PacketPlayOutBoss;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.TabConstants;
import me.neznamy.tab.shared.placeholders.conditions.Condition;
/**
@@ -299,7 +299,8 @@ public class BossBarLine implements BossBar {
return players.contains(player);
}
public boolean isAnnouncementOnly() {
@Override
public boolean isAnnouncementBar() {
return announcementOnly;
}
}
Loaded 100 of 144 files, more files were not shown because too many files have changed in this diff. Show more