mirror of
https://github.com/NEZNAMY/TAB.git
synced 2026-11-13 12:42:06 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
27bae7fdbd | ||
|
|
174b4214de | ||
|
|
4ac524840c | ||
|
|
dd4ce4e2c3 | ||
|
|
2a03d69628 | ||
|
|
c28252e6ce | ||
|
|
da1768d833 | ||
|
|
b58c3e6b47 | ||
|
|
c7575bdc8f | ||
|
|
e275d22061 | ||
|
|
b5600ef22a | ||
|
|
b8e14c9256 | ||
|
|
1af5b9a308 | ||
|
|
2dd719c3a5 | ||
|
|
45d94694cd | ||
|
|
3ce8c6a192 | ||
|
|
7deb86f105 | ||
|
|
d9b4f6a43f | ||
|
|
54a7fb8721 | ||
|
|
d1dcb2f437 | ||
|
|
a92bab617a | ||
|
|
57e34bc595 | ||
|
|
953baa273c | ||
|
|
c403cb3187 | ||
|
|
ffd6dc5bb9 | ||
|
|
0f6504a3dc | ||
|
|
f376fea598 | ||
|
|
4896cdff91 | ||
|
|
b4c87431bc | ||
|
|
1cffbab97d | ||
|
|
9b0711075a | ||
|
|
17a8e902eb | ||
|
|
4bdb5ba245 | ||
|
|
fd7748d280 | ||
|
|
317b0292ff | ||
|
|
b87be649bc | ||
|
|
e2dda54011 | ||
|
|
d17518c39b | ||
|
|
48541dd0bd | ||
|
|
b83b023fee | ||
|
|
60e0c78033 | ||
|
|
a395f7f01f | ||
|
|
09c36ef69e | ||
|
|
9d5fa685a0 | ||
|
|
6794f593fa | ||
|
|
5e9965276f | ||
|
|
1473038955 | ||
|
|
2041ca57f3 | ||
|
|
098782d820 |
No files matched your search
@@ -3,7 +3,6 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- v3
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
jobs:
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ to make the plugin even better, there is a lot of ways to contribute:
|
||||
* Open a **pull request** containing a new feature or a bug fix, which you believe many users will benefit from.
|
||||
* Make detailed high-quality **bug reports**. The difference between a bug getting fixed in 1 week vs 1 hour
|
||||
is in quality of the report (typically providing correct steps to reproduce that actually work).
|
||||
* Test **experimental builds**, which can be found in [Github Actions](https://github.com/NEZNAMY/TAB/actions) for problems of any kind including bugs.
|
||||
* Test **experimental builds**, which can be found in [GitHub Actions](https://github.com/NEZNAMY/TAB/actions) for problems of any kind including bugs.
|
||||
This way you will help make the actual releases more stable / help get stable releases sooner.
|
||||
* Help improve the wiki by opening a [Wiki change issue](https://github.com/NEZNAMY/TAB/issues/new?assignees=&labels=Wiki&template=wiki_change.yml),
|
||||
where you can improve existing descriptions, add information you found missing, fix typos / grammar mistakes or add more examples of usage of functions.
|
||||
|
||||
@@ -9,14 +9,17 @@ 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)
|
||||
replaceToken("@name@", rootProject.name)
|
||||
replaceToken("@id@", rootProject.ext.get("id")!!.toString())
|
||||
replaceToken("@version@", project.version)
|
||||
replaceToken("@description@", project.description)
|
||||
replaceToken("@website@", rootProject.ext.get("website")!!.toString())
|
||||
replaceTokenIn("src/main/java/me/neznamy/tab/api/TabConstants.java")
|
||||
}
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ public enum ProtocolVersion {
|
||||
* @param networkId
|
||||
* network id of this version
|
||||
*/
|
||||
ProtocolVersion(int networkId){
|
||||
ProtocolVersion(int networkId) {
|
||||
this.networkId = networkId;
|
||||
this.minorVersion = Integer.parseInt(toString().split("_")[1]);
|
||||
this.friendlyName = toString().substring(1).replace("_", ".");
|
||||
@@ -102,7 +102,7 @@ public enum ProtocolVersion {
|
||||
* @param friendlyName
|
||||
* friendly name to display
|
||||
*/
|
||||
ProtocolVersion(String friendlyName){
|
||||
ProtocolVersion(String friendlyName) {
|
||||
this.networkId = 999;
|
||||
this.minorVersion = 18;
|
||||
this.friendlyName = friendlyName;
|
||||
|
||||
@@ -36,8 +36,12 @@ public abstract class TabAPI {
|
||||
* If instance is {@code null}
|
||||
*/
|
||||
public static TabAPI getInstance() {
|
||||
if (instance == null) throw new IllegalStateException("API instance is null. This likely means you shaded TAB's API into your project" +
|
||||
" instead of only using it, which is not allowed.");
|
||||
if (instance == null) throw new IllegalStateException("The API instance is null. This can have 2 possible causes: \n" +
|
||||
"#1 - API was called before TAB was loaded. This means your plugin was loaded before TAB was. To make sure your " +
|
||||
"plugin loads after TAB, add it as a depend or softdepend of your plugin.\n" +
|
||||
"#2 - You shaded TAB's classes into your plugin, instead of only using them. This is not allowed. To verify this " +
|
||||
"is your case, unzip your plugin and check for TAB's classes. If they are there, you will need to fix your compiler " +
|
||||
"to not include them, such as scope provided for maven compilation.");
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,26 +1,32 @@
|
||||
package me.neznamy.tab.api;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* A class containing various constants used everywhere in the plugin
|
||||
* to allow easier overview and modification to prevent inconsistencies.
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class TabConstants {
|
||||
|
||||
public static final String PLUGIN_VERSION = "@plugin_version@";
|
||||
public static final String PLUGIN_NAME = "@name@";
|
||||
public static final String PLUGIN_ID = "@id@";
|
||||
public static final String PLUGIN_VERSION = "@version@";
|
||||
public static final String PLUGIN_DESCRIPTION = "@description@";
|
||||
public static final String PLUGIN_WEBSITE = "@website@";
|
||||
|
||||
public static final String NO_GROUP = "NONE";
|
||||
public static final String DEFAULT_GROUP = "_DEFAULT_";
|
||||
public static final String PLUGIN_MESSAGE_CHANNEL_NAME = "tab:bridge-2";
|
||||
public static final String REDIS_CHANNEL_NAME = "TAB";
|
||||
|
||||
/**
|
||||
* Private constructor to prevent the class from being instantiated
|
||||
*/
|
||||
private TabConstants() {}
|
||||
public static final String REDIS_CHANNEL_NAME = PLUGIN_NAME;
|
||||
public static final String PIPELINE_HANDLER_NAME = PLUGIN_NAME;
|
||||
|
||||
/**
|
||||
* Feature sub-category explaining why / when a certain feature
|
||||
* needed CPU time to process tasks.
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public static class CpuUsageCategory {
|
||||
|
||||
public static final String PLAYER_JOIN = "Player Join";
|
||||
@@ -54,17 +60,13 @@ public class TabConstants {
|
||||
public static final String SCOREBOARD_PACKET_CHECK = "Checking for other plugins";
|
||||
public static final String PROCESSING_PLAYER_MOVEMENT = "Processing player movement";
|
||||
public static final String TELEPORTING_WITHER = "Teleporting wither";
|
||||
|
||||
/**
|
||||
* Private constructor to prevent the class from being instantiated
|
||||
*/
|
||||
private CpuUsageCategory() {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Information why a specific feature sent a packet
|
||||
* and what the packet sent is supposed to do.
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public static class PacketCategory {
|
||||
|
||||
public static final String BOSSBAR_COLOR_STYLE = "BossBar (Color and style)";
|
||||
@@ -94,16 +96,12 @@ public class TabConstants {
|
||||
public static final String UNLIMITED_NAMETAGS_TELEPORT = "Unlimited NameTags (Teleporting)";
|
||||
public static final String UNLIMITED_NAMETAGS_SNEAK = "Unlimited NameTags (Sneaking)";
|
||||
public static final String UNLIMITED_NAMETAGS_METADATA = "Unlimited NameTags (Metadata)";
|
||||
|
||||
/**
|
||||
* Private constructor to prevent the class from being instantiated
|
||||
*/
|
||||
private PacketCategory() {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Permission nodes used by the plugin
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public static class Permission {
|
||||
|
||||
public static final String COMMAND_ALL = "tab.admin";
|
||||
@@ -144,17 +142,13 @@ public class TabConstants {
|
||||
public static final String TEST_PERMISSION = "tab.testpermission";
|
||||
|
||||
public static final String GROUP_PREFIX = "tab.group.";
|
||||
|
||||
/**
|
||||
* Private constructor to prevent the class from being instantiated
|
||||
*/
|
||||
private Permission(){}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal property names used to store text
|
||||
* under a specific key
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public static class Property {
|
||||
|
||||
public static final String HEADER = "header";
|
||||
@@ -179,11 +173,6 @@ public class TabConstants {
|
||||
|
||||
public static final String YELLOW_NUMBER = "yellow-number";
|
||||
|
||||
/**
|
||||
* Private constructor to prevent the class from being instantiated
|
||||
*/
|
||||
private Property() {}
|
||||
|
||||
public static String bossbarTitle(String name) {
|
||||
return "bossbar-title-" + name;
|
||||
}
|
||||
@@ -217,6 +206,7 @@ public class TabConstants {
|
||||
* Feature names used to register features under in the
|
||||
* feature manager which they can be retrieved by.
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public static class Feature {
|
||||
|
||||
//universal features
|
||||
@@ -258,11 +248,6 @@ public class TabConstants {
|
||||
public static final String PACKET_SERIALIZING = "Packet serializing";
|
||||
public static final String PACKET_DESERIALIZING = "Packet deserializing";
|
||||
|
||||
/**
|
||||
* Private constructor to prevent the class from being instantiated
|
||||
*/
|
||||
private Feature(){}
|
||||
|
||||
public static String scoreboardLine(String line) {
|
||||
return "scoreboard-" + line;
|
||||
}
|
||||
@@ -295,6 +280,7 @@ public class TabConstants {
|
||||
/**
|
||||
* All internal placeholders offered by the plugin
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public static class Placeholder {
|
||||
|
||||
// Universal
|
||||
@@ -338,7 +324,6 @@ public class TabConstants {
|
||||
|
||||
public static final int MINIMUM_REFRESH_INTERVAL = 50;
|
||||
|
||||
|
||||
public static String condition(String name) {
|
||||
return "%condition:" + name + "%";
|
||||
}
|
||||
@@ -355,6 +340,7 @@ public class TabConstants {
|
||||
/**
|
||||
* All plugins TAB hooks into
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public static class Plugin {
|
||||
|
||||
public static final String LUCKPERMS = "LuckPerms";
|
||||
@@ -371,6 +357,7 @@ public class TabConstants {
|
||||
/**
|
||||
* TAB's custom metrics charts
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public static class MetricsChart {
|
||||
|
||||
public static final String PERMISSION_SYSTEM = "permission_system";
|
||||
|
||||
@@ -285,7 +285,7 @@ public abstract class TabFeature {
|
||||
* @param player
|
||||
* Player who changed vanish status
|
||||
*/
|
||||
public void onVanishStatusChange(TabPlayer player){
|
||||
public void onVanishStatusChange(TabPlayer player) {
|
||||
//empty by default
|
||||
}
|
||||
|
||||
|
||||
@@ -33,11 +33,11 @@ public interface TabPlayer {
|
||||
|
||||
/**
|
||||
* Returns player's uuid used in TabList. This may only be different from real uuid if
|
||||
* TAB is installed on velocity with some specific velocity setup
|
||||
* TAB is installed on a proxy which does not rewrite UUIDs.
|
||||
*
|
||||
* @return player's uuid in TabList
|
||||
*/
|
||||
UUID getTablistUUID();
|
||||
UUID getTablistId();
|
||||
|
||||
/**
|
||||
* Returns player's protocol version
|
||||
|
||||
@@ -44,7 +44,7 @@ public class ChatModifier {
|
||||
*
|
||||
* @return true if bold is defined and set to true, false otherwise
|
||||
*/
|
||||
public boolean isBold(){
|
||||
public boolean isBold() {
|
||||
return Boolean.TRUE.equals(bold);
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ public class ChatModifier {
|
||||
*
|
||||
* @return true if italic is defined and set to true, false otherwise
|
||||
*/
|
||||
public boolean isItalic(){
|
||||
public boolean isItalic() {
|
||||
return Boolean.TRUE.equals(italic);
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ public class ChatModifier {
|
||||
*
|
||||
* @return true if underlined is defined and set to true, false otherwise
|
||||
*/
|
||||
public boolean isUnderlined(){
|
||||
public boolean isUnderlined() {
|
||||
return Boolean.TRUE.equals(underlined);
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ public class ChatModifier {
|
||||
*
|
||||
* @return true if strikethrough is defined and set to true, false otherwise
|
||||
*/
|
||||
public boolean isStrikethrough(){
|
||||
public boolean isStrikethrough() {
|
||||
return Boolean.TRUE.equals(strikethrough);
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ public class ChatModifier {
|
||||
*
|
||||
* @return true if obfuscation is defined and set to true, false otherwise
|
||||
*/
|
||||
public boolean isObfuscated(){
|
||||
public boolean isObfuscated() {
|
||||
return Boolean.TRUE.equals(obfuscated);
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ public class DeserializedChatComponent extends IChatBaseComponent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IChatBaseComponent> getExtra(){
|
||||
public List<IChatBaseComponent> getExtra() {
|
||||
if (!deserialized) deserialize();
|
||||
return super.getExtra();
|
||||
}
|
||||
@@ -75,7 +75,7 @@ public class DeserializedChatComponent extends IChatBaseComponent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public IChatBaseComponent setExtra(List<IChatBaseComponent> components){
|
||||
public IChatBaseComponent setExtra(List<IChatBaseComponent> components) {
|
||||
if (!deserialized) deserialize();
|
||||
modified = true;
|
||||
return super.setExtra(components);
|
||||
|
||||
@@ -137,7 +137,7 @@ public enum EnumChatFormat {
|
||||
* exact blue value
|
||||
* @return enum value or null if no such combination exists
|
||||
*/
|
||||
public static EnumChatFormat fromRGBExact(int red, int green, int blue){
|
||||
public static EnumChatFormat fromRGBExact(int red, int green, int blue) {
|
||||
for (EnumChatFormat format : VALUES) {
|
||||
if (format.red == red && format.green == green && format.blue == blue) return format;
|
||||
}
|
||||
@@ -152,12 +152,12 @@ public enum EnumChatFormat {
|
||||
* text to replace color symbol in
|
||||
* @return colorized string from provided text
|
||||
*/
|
||||
public static String color(String textToTranslate){
|
||||
public static String color(String textToTranslate) {
|
||||
if (textToTranslate == null) return null;
|
||||
if (!textToTranslate.contains("&")) return textToTranslate;
|
||||
char[] b = textToTranslate.toCharArray();
|
||||
for (int i = 0; i < b.length - 1; i++) {
|
||||
if ((b[i] == '&') && ("0123456789AaBbCcDdEeFfKkLlMmNnOoRrXx".indexOf(b[(i + 1)]) > -1)){
|
||||
if ((b[i] == '&') && ("0123456789AaBbCcDdEeFfKkLlMmNnOoRrXx".indexOf(b[(i + 1)]) > -1)) {
|
||||
b[i] = COLOR_CHAR;
|
||||
b[(i + 1)] = Character.toLowerCase(b[(i + 1)]);
|
||||
}
|
||||
@@ -189,9 +189,9 @@ public enum EnumChatFormat {
|
||||
if (input == null) return "";
|
||||
StringBuilder result = new StringBuilder();
|
||||
int length = input.length();
|
||||
for (int index = length - 1; index > -1; index--){
|
||||
for (int index = length - 1; index > -1; index--) {
|
||||
char section = input.charAt(index);
|
||||
if ((section == COLOR_CHAR || section == '&') && (index < length - 1)){
|
||||
if ((section == COLOR_CHAR || section == '&') && (index < length - 1)) {
|
||||
char c = input.charAt(index + 1);
|
||||
if ("0123456789AaBbCcDdEeFfKkLlMmNnOoRr".contains(String.valueOf(c))) {
|
||||
result.insert(0, COLOR_CHAR);
|
||||
|
||||
@@ -69,7 +69,7 @@ public class IChatBaseComponent {
|
||||
*
|
||||
* @return list of extra components
|
||||
*/
|
||||
public List<IChatBaseComponent> getExtra(){
|
||||
public List<IChatBaseComponent> getExtra() {
|
||||
if (extra == null) return Collections.emptyList();
|
||||
return extra;
|
||||
}
|
||||
@@ -83,7 +83,7 @@ public class IChatBaseComponent {
|
||||
* @throws IllegalArgumentException
|
||||
* if {@code components} is an empty list
|
||||
*/
|
||||
public IChatBaseComponent setExtra(List<IChatBaseComponent> components){
|
||||
public IChatBaseComponent setExtra(List<IChatBaseComponent> components) {
|
||||
if (components.isEmpty()) throw new IllegalArgumentException("Unexpected empty array of components"); //exception taken from minecraft
|
||||
this.extra = components;
|
||||
return this;
|
||||
@@ -177,14 +177,14 @@ public class IChatBaseComponent {
|
||||
* text to convert
|
||||
* @return organized component from colored text
|
||||
*/
|
||||
public static IChatBaseComponent fromColoredText(@NonNull String originalText){
|
||||
public static IChatBaseComponent fromColoredText(@NonNull String originalText) {
|
||||
String text = RGBUtils.getInstance().applyFormats(EnumChatFormat.color(originalText));
|
||||
List<IChatBaseComponent> components = new ArrayList<>();
|
||||
StringBuilder builder = new StringBuilder();
|
||||
IChatBaseComponent component = new IChatBaseComponent();
|
||||
for (int i = 0; i < text.length(); i++){
|
||||
for (int i = 0; i < text.length(); i++) {
|
||||
char c = text.charAt(i);
|
||||
if (c == EnumChatFormat.COLOR_CHAR){
|
||||
if (c == EnumChatFormat.COLOR_CHAR) {
|
||||
i++;
|
||||
if (i >= text.length()) {
|
||||
break;
|
||||
@@ -194,7 +194,7 @@ public class IChatBaseComponent {
|
||||
c = (char)(c + ' ');
|
||||
}
|
||||
EnumChatFormat format = EnumChatFormat.getByChar(c);
|
||||
if (format != null){
|
||||
if (format != null) {
|
||||
if (builder.length() > 0) {
|
||||
component.setText(builder.toString());
|
||||
components.add(component);
|
||||
@@ -202,7 +202,7 @@ public class IChatBaseComponent {
|
||||
component.text = null;
|
||||
builder = new StringBuilder();
|
||||
}
|
||||
switch (format){
|
||||
switch (format) {
|
||||
case BOLD:
|
||||
component.modifier.setBold(true);
|
||||
break;
|
||||
@@ -228,7 +228,7 @@ public class IChatBaseComponent {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (c == '#' && text.length() > i+6){
|
||||
} else if (c == '#' && text.length() > i+6) {
|
||||
String hex = text.substring(i+1, i+7);
|
||||
if (RGBUtils.getInstance().isHexCode(hex)) {
|
||||
TextColor color;
|
||||
@@ -239,7 +239,7 @@ public class IChatBaseComponent {
|
||||
color = new TextColor(hex);
|
||||
i += 6;
|
||||
}
|
||||
if (builder.length() > 0){
|
||||
if (builder.length() > 0) {
|
||||
component.setText(builder.toString());
|
||||
components.add(component);
|
||||
builder = new StringBuilder();
|
||||
@@ -367,7 +367,7 @@ public class IChatBaseComponent {
|
||||
* text to create component from
|
||||
* @return The most performance-optimized component based on text
|
||||
*/
|
||||
public static IChatBaseComponent optimizedComponent(String text){
|
||||
public static IChatBaseComponent optimizedComponent(String text) {
|
||||
return stringCache.get(text, null);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package me.neznamy.tab.api.chat;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.tab.api.ProtocolVersion;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -17,15 +18,7 @@ import java.util.List;
|
||||
public class WrappedChatComponent extends IChatBaseComponent {
|
||||
|
||||
/** Original NMS component */
|
||||
private final Object originalComponent;
|
||||
|
||||
/**
|
||||
* Returns the original NMS component
|
||||
* @return the original NMS component
|
||||
*/
|
||||
public Object get() {
|
||||
return originalComponent;
|
||||
}
|
||||
@Getter private final Object originalComponent;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
@@ -38,7 +31,7 @@ public class WrappedChatComponent extends IChatBaseComponent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IChatBaseComponent> getExtra(){
|
||||
public List<IChatBaseComponent> getExtra() {
|
||||
throw new UnsupportedOperationException("Not supported for " + getClass().getSimpleName());
|
||||
}
|
||||
|
||||
@@ -53,7 +46,7 @@ public class WrappedChatComponent extends IChatBaseComponent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public IChatBaseComponent setExtra(List<IChatBaseComponent> components){
|
||||
public IChatBaseComponent setExtra(List<IChatBaseComponent> components) {
|
||||
throw new UnsupportedOperationException("Not supported for " + getClass().getSimpleName());
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package me.neznamy.tab.api.chat.rgb;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.tab.api.chat.EnumChatFormat;
|
||||
import me.neznamy.tab.api.chat.TextColor;
|
||||
import me.neznamy.tab.api.chat.IChatBaseComponent;
|
||||
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;
|
||||
@@ -132,7 +132,9 @@ public class RGBUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts all hex codes in given string to legacy codes
|
||||
* Converts all hex codes in given string to legacy codes.
|
||||
* Also removes redundant color codes caused by this operation
|
||||
* to properly fit in limits.
|
||||
*
|
||||
* @param text
|
||||
* text to convert
|
||||
@@ -140,29 +142,7 @@ public class RGBUtils {
|
||||
*/
|
||||
public String convertRGBtoLegacy(String text) {
|
||||
if (text == null) return null;
|
||||
if (!text.contains("#")) return EnumChatFormat.color(text);
|
||||
String applied = applyFormats(text);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < applied.length(); i++){
|
||||
char c = applied.charAt(i);
|
||||
if (c == '#' && applied.length() > i+6) {
|
||||
String hexCode = applied.substring(i+1, i+7);
|
||||
if (isHexCode(hexCode)) {
|
||||
if (containsLegacyCode(applied, i)) {
|
||||
sb.append(new TextColor(hexCode, EnumChatFormat.getByChar(applied.charAt(i+8))).getLegacyColor().getFormat());
|
||||
i += 8;
|
||||
} else {
|
||||
sb.append(new TextColor(hexCode).getLegacyColor().getFormat());
|
||||
i += 6;
|
||||
}
|
||||
} else {
|
||||
sb.append(c);
|
||||
}
|
||||
} else {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
return IChatBaseComponent.fromColoredText(text).toLegacyText();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -75,10 +75,8 @@ public class PacketBuilder {
|
||||
* @param clientVersion
|
||||
* Protocol version of player to build the packet for
|
||||
* @return Platform-specific packet
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public Object build(PacketPlayOutChat packet, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
public Object build(PacketPlayOutChat packet, ProtocolVersion clientVersion) {
|
||||
return packet;
|
||||
}
|
||||
|
||||
@@ -105,10 +103,8 @@ public class PacketBuilder {
|
||||
* @param clientVersion
|
||||
* Protocol version of player to build the packet for
|
||||
* @return Platform-specific packet
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public Object build(PacketPlayOutPlayerListHeaderFooter packet, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
public Object build(PacketPlayOutPlayerListHeaderFooter packet, ProtocolVersion clientVersion) {
|
||||
return packet;
|
||||
}
|
||||
|
||||
@@ -120,10 +116,8 @@ public class PacketBuilder {
|
||||
* @param clientVersion
|
||||
* Protocol version of player to build the packet for
|
||||
* @return Platform-specific packet
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public Object build(PacketPlayOutScoreboardDisplayObjective packet, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
public Object build(PacketPlayOutScoreboardDisplayObjective packet, ProtocolVersion clientVersion) {
|
||||
return packet;
|
||||
}
|
||||
|
||||
@@ -135,10 +129,8 @@ public class PacketBuilder {
|
||||
* @param clientVersion
|
||||
* Protocol version of player to build the packet for
|
||||
* @return Platform-specific packet
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public Object build(PacketPlayOutScoreboardObjective packet, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
public Object build(PacketPlayOutScoreboardObjective packet, ProtocolVersion clientVersion) {
|
||||
return packet;
|
||||
}
|
||||
|
||||
@@ -150,10 +142,8 @@ public class PacketBuilder {
|
||||
* @param clientVersion
|
||||
* Protocol version of player to build the packet for
|
||||
* @return Platform-specific packet
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public Object build(PacketPlayOutScoreboardScore packet, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
public Object build(PacketPlayOutScoreboardScore packet, ProtocolVersion clientVersion) {
|
||||
return packet;
|
||||
}
|
||||
|
||||
@@ -165,10 +155,8 @@ public class PacketBuilder {
|
||||
* @param clientVersion
|
||||
* Protocol version of player to build the packet for
|
||||
* @return Platform-specific packet
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public Object build(PacketPlayOutScoreboardTeam packet, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
public Object build(PacketPlayOutScoreboardTeam packet, ProtocolVersion clientVersion) {
|
||||
return packet;
|
||||
}
|
||||
|
||||
|
||||
@@ -151,7 +151,7 @@ public class PacketPlayOutBoss implements TabPacket {
|
||||
*
|
||||
* @return the bitmask
|
||||
*/
|
||||
public byte getFlags(){
|
||||
public byte getFlags() {
|
||||
byte value = 0;
|
||||
if (darkenScreen) value += 1;
|
||||
if (playMusic) value += 2;
|
||||
|
||||
@@ -10,7 +10,8 @@ tasks {
|
||||
filter<ReplaceTokens>("tokens" to mapOf(
|
||||
"name" to rootProject.name,
|
||||
"version" to project.version,
|
||||
"description" to project.description
|
||||
"description" to project.description,
|
||||
"website" to rootProject.ext.get("website")!!.toString()
|
||||
))
|
||||
}
|
||||
javadoc {
|
||||
|
||||
@@ -9,5 +9,6 @@ tasks {
|
||||
relocate("org.bstats", "me.neznamy.tab.libs.org.bstats")
|
||||
relocate("org.json.simple", "me.neznamy.tab.libs.org.json.simple")
|
||||
relocate("net.kyori.event", "me.neznamy.tab.libs.net.kyori.event")
|
||||
relocate("me.neznamy.yamlassist", "me.neznamy.tab.libs.yamlassist")
|
||||
}
|
||||
}
|
||||
+6
-2
@@ -4,8 +4,11 @@ plugins {
|
||||
|
||||
allprojects {
|
||||
group = "me.neznamy"
|
||||
version = property("projectVersion") as String // from gradle.properties
|
||||
version = "3.3.0"
|
||||
description = "An all-in-one solution that works"
|
||||
|
||||
ext.set("id", "tab")
|
||||
ext.set("website", "https://github.com/NEZNAMY/TAB")
|
||||
}
|
||||
|
||||
val platforms = setOf(
|
||||
@@ -13,7 +16,8 @@ val platforms = setOf(
|
||||
projects.bungeecord,
|
||||
projects.krypton,
|
||||
projects.velocity,
|
||||
//projects.sponge
|
||||
projects.sponge7,
|
||||
projects.sponge8
|
||||
).map { it.dependencyProject }
|
||||
|
||||
val special = setOf(
|
||||
|
||||
@@ -4,6 +4,5 @@ dependencies {
|
||||
compileOnly(libs.bukkit)
|
||||
compileOnly(libs.placeholderapi)
|
||||
compileOnly(libs.vault)
|
||||
compileOnly(libs.via)
|
||||
compileOnly(libs.authlib)
|
||||
}
|
||||
@@ -26,7 +26,7 @@ public class BukkitEventListener implements Listener {
|
||||
* quit event
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onQuit(PlayerQuitEvent e){
|
||||
public void onQuit(PlayerQuitEvent e) {
|
||||
if (TabAPI.getInstance().isPluginDisabled()) return;
|
||||
TabAPI.getInstance().getThreadManager().runTask(() -> TabAPI.getInstance().getFeatureManager().onQuit(TabAPI.getInstance().getPlayer(e.getPlayer().getUniqueId())));
|
||||
}
|
||||
@@ -51,7 +51,7 @@ public class BukkitEventListener implements Listener {
|
||||
* world changed event
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onWorldChange(PlayerChangedWorldEvent e){
|
||||
public void onWorldChange(PlayerChangedWorldEvent e) {
|
||||
if (TabAPI.getInstance().isPluginDisabled()) return;
|
||||
TabAPI.getInstance().getThreadManager().runTask(() ->
|
||||
TabAPI.getInstance().getFeatureManager().onWorldChange(e.getPlayer().getUniqueId(), e.getPlayer().getWorld().getName()));
|
||||
|
||||
@@ -1,73 +1,38 @@
|
||||
package me.neznamy.tab.platforms.bukkit;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import me.neznamy.tab.api.ProtocolVersion;
|
||||
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.api.util.ComponentCache;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.PacketPlayOutEntityDestroy;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.PacketPlayOutEntityMetadata;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.PacketPlayOutEntityTeleport;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.PacketPlayOutSpawnEntityLiving;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcher;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.NMSStorage;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.nms.NMSStorage;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.packet.*;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.EntityType;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.UUID;
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public class BukkitPacketBuilder extends PacketBuilder {
|
||||
|
||||
/** NMS data storage */
|
||||
private final NMSStorage nms = NMSStorage.getInstance();
|
||||
|
||||
/** Map of entity type ids for entities used by the plugin */
|
||||
private final EnumMap<EntityType, Integer> entityIds = new EnumMap<>(EntityType.class);
|
||||
|
||||
/** Component cache for better performance (1.16+ players) */
|
||||
|
||||
private final ComponentCache<IChatBaseComponent, Object> componentCacheModern = new ComponentCache<>(10000,
|
||||
(component, clientVersion) -> nms.ChatSerializer_DESERIALIZE.invoke(null, component.toString(clientVersion)));
|
||||
|
||||
/** Component cache for better performance (1.15- players) */
|
||||
private final ComponentCache<IChatBaseComponent, Object> componentCacheLegacy = new ComponentCache<>(10000,
|
||||
(component, clientVersion) -> nms.ChatSerializer_DESERIALIZE.invoke(null, component.toString(clientVersion)));
|
||||
|
||||
|
||||
/**
|
||||
* Constructs new instance
|
||||
*/
|
||||
public BukkitPacketBuilder() {
|
||||
if (nms.getMinorVersion() >= 19) {
|
||||
entityIds.put(EntityType.ARMOR_STAND, 2);
|
||||
} else if (nms.getMinorVersion() >= 13) {
|
||||
entityIds.put(EntityType.ARMOR_STAND, 1);
|
||||
} else {
|
||||
entityIds.put(EntityType.WITHER, 64);
|
||||
if (nms.getMinorVersion() >= 8){
|
||||
entityIds.put(EntityType.ARMOR_STAND, 30);
|
||||
}
|
||||
}
|
||||
buildMap.put(PacketPlayOutEntityMetadata.class, (packet, version) -> build((PacketPlayOutEntityMetadata)packet));
|
||||
buildMap.put(PacketPlayOutEntityTeleport.class, (packet, version) -> build((PacketPlayOutEntityTeleport)packet));
|
||||
buildMap.put(PacketPlayOutEntityDestroy.class, (packet, version) -> build((PacketPlayOutEntityDestroy)packet));
|
||||
buildMap.put(PacketPlayOutSpawnEntityLiving.class, (packet, version) -> build((PacketPlayOutSpawnEntityLiving)packet));
|
||||
{
|
||||
buildMap.put(PacketPlayOutEntityMetadata.class, (packet, version) -> ((PacketPlayOutEntityMetadata)packet).build());
|
||||
buildMap.put(PacketPlayOutEntityTeleport.class, (packet, version) -> ((PacketPlayOutEntityTeleport)packet).build());
|
||||
buildMap.put(PacketPlayOutEntityDestroy.class, (packet, version) -> ((PacketPlayOutEntityDestroy)packet).build());
|
||||
buildMap.put(PacketPlayOutSpawnEntityLiving.class, (packet, version) -> ((PacketPlayOutSpawnEntityLiving)packet).build());
|
||||
buildMap.put(PacketPlayOutPlayerListHeaderFooter.class, (packet, version) -> PacketPlayOutPlayerListHeaderFooterStorage.build((PacketPlayOutPlayerListHeaderFooter) packet, version));
|
||||
buildMap.put(PacketPlayOutChat.class, (packet, version) -> PacketPlayOutChatStorage.build((PacketPlayOutChat) packet, version));
|
||||
buildMap.put(PacketPlayOutScoreboardObjective.class, (packet, version) -> PacketPlayOutScoreboardObjectiveStorage.build((PacketPlayOutScoreboardObjective) packet, version));
|
||||
buildMap.put(PacketPlayOutScoreboardDisplayObjective.class, (packet, version) -> PacketPlayOutScoreboardDisplayObjectiveStorage.build((PacketPlayOutScoreboardDisplayObjective) packet, version));
|
||||
buildMap.put(PacketPlayOutScoreboardTeam.class, (packet, version) -> PacketPlayOutScoreboardTeamStorage.build((PacketPlayOutScoreboardTeam) packet, version));
|
||||
buildMap.put(PacketPlayOutScoreboardScore.class, (packet, version) -> PacketPlayOutScoreboardScoreStorage.build((PacketPlayOutScoreboardScore) packet, version));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object build(PacketPlayOutBoss packet, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
if (nms.getMinorVersion() >= 9 || clientVersion.getMinorVersion() >= 9) {
|
||||
if (NMSStorage.getInstance().getMinorVersion() >= 9 || clientVersion.getMinorVersion() >= 9) {
|
||||
//1.9+ server or client, handled by bukkit api or ViaVersion
|
||||
return packet;
|
||||
}
|
||||
@@ -75,402 +40,24 @@ public class BukkitPacketBuilder extends PacketBuilder {
|
||||
return buildBossPacketEntity(packet, clientVersion);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object build(PacketPlayOutChat packet, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
Object component = toNMSComponent(packet.getMessage(), clientVersion);
|
||||
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, Enum.valueOf(nms.ChatMessageType, packet.getType().toString()), UUID.randomUUID());
|
||||
if (nms.getMinorVersion() >= 12)
|
||||
return nms.newPacketPlayOutChat.newInstance(component, Enum.valueOf(nms.ChatMessageType, packet.getType().toString()));
|
||||
if (nms.getMinorVersion() >= 8)
|
||||
return nms.newPacketPlayOutChat.newInstance(component, (byte) packet.getType().ordinal());
|
||||
if (nms.getMinorVersion() == 7)
|
||||
return nms.newPacketPlayOutChat.newInstance(component);
|
||||
return packet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object build(PacketPlayOutPlayerInfo packet, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
if (nms.getMinorVersion() < 8) return null;
|
||||
if (nms.ClientboundPlayerInfoRemovePacket != null) {
|
||||
//1.19.3+
|
||||
if (packet.getActions().contains(EnumPlayerInfoAction.REMOVE_PLAYER)) {
|
||||
return nms.newClientboundPlayerInfoRemovePacket.newInstance(
|
||||
packet.getEntries().stream().map(PlayerInfoData::getUniqueId).collect(Collectors.toList())
|
||||
);
|
||||
}
|
||||
Enum[] array = packet.getActions().stream().map(action -> Enum.valueOf(nms.EnumPlayerInfoAction, action.toString())).toArray(Enum[]::new);
|
||||
Object nmsPacket = nms.newPacketPlayOutPlayerInfo.newInstance(EnumSet.of(array[0], array), Collections.emptyList());
|
||||
List<Object> items = new ArrayList<>();
|
||||
for (PlayerInfoData data : packet.getEntries()) {
|
||||
GameProfile profile = new GameProfile(data.getUniqueId(), data.getName());
|
||||
if (data.getSkin() != null) profile.getProperties().put("textures",
|
||||
new Property("textures", data.getSkin().getValue(), data.getSkin().getSignature()));
|
||||
Object obj = nms.newPlayerInfoData.newInstance(
|
||||
data.getUniqueId(),
|
||||
profile,
|
||||
data.isListed(),
|
||||
data.getLatency(),
|
||||
data.getGameMode() == null ? null : Enum.valueOf(nms.EnumGamemode, data.getGameMode().toString()),
|
||||
data.getDisplayName() == null ? null : toNMSComponent(data.getDisplayName(), clientVersion),
|
||||
data.getProfilePublicKey() == null ? null : nms.newRemoteChatSession$Data.newInstance(data.getChatSessionId(), data.getProfilePublicKey()));
|
||||
items.add(obj);
|
||||
}
|
||||
nms.setField(nmsPacket, nms.PacketPlayOutPlayerInfo_PLAYERS, items);
|
||||
return nmsPacket;
|
||||
} else {
|
||||
//1.19.2-
|
||||
EnumPlayerInfoAction action = packet.getActions().contains(EnumPlayerInfoAction.ADD_PLAYER) ?
|
||||
EnumPlayerInfoAction.ADD_PLAYER : packet.getActions().iterator().next();
|
||||
Object nmsPacket = nms.newPacketPlayOutPlayerInfo.newInstance(Enum.valueOf(nms.EnumPlayerInfoAction, action.toString()), Array.newInstance(nms.EntityPlayer, 0));
|
||||
List<Object> items = new ArrayList<>();
|
||||
for (PlayerInfoData data : packet.getEntries()) {
|
||||
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.getParameterTypes()[0] == nms.PacketPlayOutPlayerInfo) {
|
||||
parameters.add(nmsPacket);
|
||||
}
|
||||
parameters.add(profile);
|
||||
parameters.add(data.getLatency());
|
||||
parameters.add(data.getGameMode() == null ? null : Enum.valueOf(nms.EnumGamemode, data.getGameMode().toString()));
|
||||
parameters.add(data.getDisplayName() == null ? null : toNMSComponent(data.getDisplayName(), clientVersion));
|
||||
if (nms.getMinorVersion() >= 19) parameters.add(data.getProfilePublicKey());
|
||||
items.add(nms.newPlayerInfoData.newInstance(parameters.toArray()));
|
||||
}
|
||||
nms.setField(nmsPacket, nms.PacketPlayOutPlayerInfo_PLAYERS, items);
|
||||
return nmsPacket;
|
||||
}
|
||||
return PacketPlayOutPlayerInfoStorage.build(packet, clientVersion);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object build(PacketPlayOutPlayerListHeaderFooter packet, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
if (nms.getMinorVersion() < 8) return null;
|
||||
if (nms.newPacketPlayOutPlayerListHeaderFooter.getParameterCount() == 2) {
|
||||
return nms.newPacketPlayOutPlayerListHeaderFooter.newInstance(toNMSComponent(packet.getHeader(), clientVersion), toNMSComponent(packet.getFooter(), clientVersion));
|
||||
}
|
||||
Object nmsPacket = nms.newPacketPlayOutPlayerListHeaderFooter.newInstance();
|
||||
nms.setField(nmsPacket, nms.PacketPlayOutPlayerListHeaderFooter_HEADER, toNMSComponent(packet.getHeader(), clientVersion));
|
||||
nms.setField(nmsPacket, nms.PacketPlayOutPlayerListHeaderFooter_FOOTER, toNMSComponent(packet.getFooter(), clientVersion));
|
||||
return nmsPacket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object build(PacketPlayOutScoreboardDisplayObjective packet, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
return nms.newPacketPlayOutScoreboardDisplayObjective.newInstance(packet.getSlot(), newScoreboardObjective(packet.getObjectiveName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object build(PacketPlayOutScoreboardObjective packet, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
String displayName = clientVersion.getMinorVersion() < 13 ? cutTo(packet.getDisplayName(), 32) : packet.getDisplayName();
|
||||
if (nms.getMinorVersion() >= 13) {
|
||||
return nms.newPacketPlayOutScoreboardObjective.newInstance(nms.newScoreboardObjective.newInstance(null, packet.getObjectiveName(), null,
|
||||
toNMSComponent(IChatBaseComponent.optimizedComponent(displayName), clientVersion),
|
||||
packet.getRenderType() == null ? null : Enum.valueOf(nms.EnumScoreboardHealthDisplay, packet.getRenderType().toString())),
|
||||
packet.getAction());
|
||||
}
|
||||
|
||||
Object nmsPacket = nms.newPacketPlayOutScoreboardObjective.newInstance();
|
||||
nms.setField(nmsPacket, nms.PacketPlayOutScoreboardObjective_OBJECTIVENAME, packet.getObjectiveName());
|
||||
nms.setField(nmsPacket, nms.PacketPlayOutScoreboardObjective_DISPLAYNAME, displayName);
|
||||
if (nms.getMinorVersion() >= 8 && packet.getRenderType() != null) {
|
||||
nms.setField(nmsPacket, nms.PacketPlayOutScoreboardObjective_RENDERTYPE, Enum.valueOf(nms.EnumScoreboardHealthDisplay, packet.getRenderType().toString()));
|
||||
}
|
||||
nms.setField(nmsPacket, nms.PacketPlayOutScoreboardObjective_METHOD, packet.getAction());
|
||||
return nmsPacket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object build(PacketPlayOutScoreboardScore packet, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
if (nms.getMinorVersion() >= 13) {
|
||||
return nms.newPacketPlayOutScoreboardScore_1_13.newInstance(Enum.valueOf(nms.EnumScoreboardAction, packet.getAction().toString()), packet.getObjectiveName(), packet.getPlayer(), packet.getScore());
|
||||
}
|
||||
if (packet.getAction() == PacketPlayOutScoreboardScore.Action.REMOVE) {
|
||||
return nms.newPacketPlayOutScoreboardScore_String.newInstance(packet.getPlayer());
|
||||
}
|
||||
Object score = nms.newScoreboardScore.newInstance(nms.emptyScoreboard, newScoreboardObjective(packet.getObjectiveName()), packet.getPlayer());
|
||||
nms.ScoreboardScore_setScore.invoke(score, packet.getScore());
|
||||
if (nms.getMinorVersion() >= 8) {
|
||||
return nms.newPacketPlayOutScoreboardScore.newInstance(score);
|
||||
}
|
||||
return nms.newPacketPlayOutScoreboardScore.newInstance(score, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object build(PacketPlayOutScoreboardTeam packet, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
if (nms.PacketPlayOutScoreboardTeam == null) return null; //fabric
|
||||
Object team = nms.newScoreboardTeam.newInstance(nms.emptyScoreboard, packet.getName());
|
||||
String prefix = packet.getPlayerPrefix();
|
||||
String suffix = packet.getPlayerSuffix();
|
||||
if (clientVersion.getMinorVersion() < 13) {
|
||||
prefix = cutTo(prefix, 16);
|
||||
suffix = cutTo(suffix, 16);
|
||||
}
|
||||
((Collection<String>)nms.ScoreboardTeam_getPlayerNameSet.invoke(team)).addAll(packet.getPlayers());
|
||||
nms.ScoreboardTeam_setAllowFriendlyFire.invoke(team, (packet.getOptions() & 0x1) > 0);
|
||||
nms.ScoreboardTeam_setCanSeeFriendlyInvisibles.invoke(team, (packet.getOptions() & 0x2) > 0);
|
||||
if (nms.getMinorVersion() >= 13) {
|
||||
createTeamModern(packet, clientVersion, team, prefix, suffix);
|
||||
} else {
|
||||
createTeamLegacy(packet, team, prefix, suffix);
|
||||
}
|
||||
if (nms.getMinorVersion() >= 17) {
|
||||
switch (packet.getAction()) {
|
||||
case 0:
|
||||
return nms.PacketPlayOutScoreboardTeam_ofBoolean.invoke(null, team, true);
|
||||
case 1:
|
||||
return nms.PacketPlayOutScoreboardTeam_of.invoke(null, team);
|
||||
case 2:
|
||||
return nms.PacketPlayOutScoreboardTeam_ofBoolean.invoke(null, team, false);
|
||||
case 3:
|
||||
return nms.PacketPlayOutScoreboardTeam_ofString.invoke(null, team, packet.getPlayers().iterator().next(), Enum.valueOf(nms.PacketPlayOutScoreboardTeam_PlayerAction, "ADD"));
|
||||
case 4:
|
||||
return nms.PacketPlayOutScoreboardTeam_ofString.invoke(null, team, packet.getPlayers().iterator().next(), Enum.valueOf(nms.PacketPlayOutScoreboardTeam_PlayerAction, "REMOVE"));
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid action: " + packet.getAction());
|
||||
}
|
||||
}
|
||||
return nms.newPacketPlayOutScoreboardTeam.newInstance(team, packet.getAction());
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds entity destroy packet from custom packet class
|
||||
*
|
||||
* @param packet
|
||||
* Destroy packet
|
||||
* @return NMS destroy packet
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public Object build(PacketPlayOutEntityDestroy packet) throws ReflectiveOperationException {
|
||||
try {
|
||||
return nms.newPacketPlayOutEntityDestroy.newInstance(new Object[]{packet.getEntities()});
|
||||
} catch (IllegalArgumentException e) {
|
||||
//1.17.0
|
||||
return nms.newPacketPlayOutEntityDestroy.newInstance(packet.getEntities()[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds entity metadata packet from custom packet class
|
||||
*
|
||||
* @param packet
|
||||
* Metadata packet
|
||||
* @return NMS metadata packet
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public Object build(PacketPlayOutEntityMetadata packet) throws ReflectiveOperationException {
|
||||
if (nms.newPacketPlayOutEntityMetadata.getParameterCount() == 2) {
|
||||
//1.19.3+
|
||||
return nms.newPacketPlayOutEntityMetadata.newInstance(packet.getEntityId(), nms.DataWatcher_b.invoke(packet.getDataWatcher().toNMS()));
|
||||
} else {
|
||||
return nms.newPacketPlayOutEntityMetadata.newInstance(packet.getEntityId(), packet.getDataWatcher().toNMS(), true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds entity spawn packet from custom packet class
|
||||
*
|
||||
* @param packet
|
||||
* Spawn packet
|
||||
* @return NMS spawn packet
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public Object build(PacketPlayOutSpawnEntityLiving packet) throws ReflectiveOperationException {
|
||||
Object nmsPacket;
|
||||
if (nms.getMinorVersion() >= 17) {
|
||||
nmsPacket = nms.newPacketPlayOutSpawnEntityLiving.newInstance(nms.dummyEntity);
|
||||
} else {
|
||||
nmsPacket = nms.newPacketPlayOutSpawnEntityLiving.newInstance();
|
||||
}
|
||||
nms.setField(nmsPacket, nms.PacketPlayOutSpawnEntityLiving_ENTITYID, packet.getEntityId());
|
||||
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) {
|
||||
nms.setField(nmsPacket, nms.PacketPlayOutSpawnEntityLiving_DATAWATCHER, packet.getDataWatcher().toNMS());
|
||||
}
|
||||
if (nms.getMinorVersion() >= 9) {
|
||||
nms.setField(nmsPacket, nms.PacketPlayOutSpawnEntityLiving_UUID, packet.getUniqueId());
|
||||
nms.setField(nmsPacket, nms.PacketPlayOutSpawnEntityLiving_X, packet.getLocation().getX());
|
||||
nms.setField(nmsPacket, nms.PacketPlayOutSpawnEntityLiving_Y, packet.getLocation().getY());
|
||||
nms.setField(nmsPacket, nms.PacketPlayOutSpawnEntityLiving_Z, packet.getLocation().getZ());
|
||||
} else {
|
||||
nms.setField(nmsPacket, nms.PacketPlayOutSpawnEntityLiving_X, floor(packet.getLocation().getX()*32));
|
||||
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.EntityTypes_ARMOR_STAND); // :(
|
||||
} else {
|
||||
nms.setField(nmsPacket, nms.PacketPlayOutSpawnEntityLiving_ENTITYTYPE, id);
|
||||
}
|
||||
return nmsPacket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds entity teleport packet from custom packet class
|
||||
*
|
||||
* @param packet
|
||||
* Teleport packet
|
||||
* @return NMS teleport packet
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public Object build(PacketPlayOutEntityTeleport packet) throws ReflectiveOperationException {
|
||||
Object nmsPacket;
|
||||
if (nms.getMinorVersion() >= 17) {
|
||||
nmsPacket = nms.newPacketPlayOutEntityTeleport.newInstance(nms.dummyEntity);
|
||||
} else {
|
||||
nmsPacket = nms.newPacketPlayOutEntityTeleport.newInstance();
|
||||
}
|
||||
nms.setField(nmsPacket, nms.PacketPlayOutEntityTeleport_ENTITYID, packet.getEntityId());
|
||||
if (nms.getMinorVersion() >= 9) {
|
||||
nms.setField(nmsPacket, nms.PacketPlayOutEntityTeleport_X, packet.getLocation().getX());
|
||||
nms.setField(nmsPacket, nms.PacketPlayOutEntityTeleport_Y, packet.getLocation().getY());
|
||||
nms.setField(nmsPacket, nms.PacketPlayOutEntityTeleport_Z, packet.getLocation().getZ());
|
||||
} else {
|
||||
nms.setField(nmsPacket, nms.PacketPlayOutEntityTeleport_X, floor(packet.getLocation().getX()*32));
|
||||
nms.setField(nmsPacket, nms.PacketPlayOutEntityTeleport_Y, floor(packet.getLocation().getY()*32));
|
||||
nms.setField(nmsPacket, nms.PacketPlayOutEntityTeleport_Z, floor(packet.getLocation().getZ()*32));
|
||||
}
|
||||
nms.setField(nmsPacket, nms.PacketPlayOutEntityTeleport_YAW, (byte) (packet.getLocation().getYaw()/360*256));
|
||||
nms.setField(nmsPacket, nms.PacketPlayOutEntityTeleport_PITCH, (byte) (packet.getLocation().getPitch()/360*256));
|
||||
return nmsPacket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes data into NMS team from custom team packet. Used on 1.13+ servers.
|
||||
*
|
||||
* @param packet
|
||||
* Packet to read from
|
||||
* @param clientVersion
|
||||
* Version of player
|
||||
* @param team
|
||||
* Team to write to
|
||||
* @param prefix
|
||||
* Prefix to use
|
||||
* @param suffix
|
||||
* Suffix to use
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
private void createTeamModern(PacketPlayOutScoreboardTeam packet, ProtocolVersion clientVersion, Object team, String prefix, String suffix) throws ReflectiveOperationException {
|
||||
if (prefix != null) nms.ScoreboardTeam_setPrefix.invoke(team, toNMSComponent(IChatBaseComponent.optimizedComponent(prefix), clientVersion));
|
||||
if (suffix != null) nms.ScoreboardTeam_setSuffix.invoke(team, toNMSComponent(IChatBaseComponent.optimizedComponent(suffix), clientVersion));
|
||||
EnumChatFormat format = packet.getColor() != null ? packet.getColor() : EnumChatFormat.lastColorsOf(prefix);
|
||||
nms.ScoreboardTeam_setColor.invoke(team, Enum.valueOf(nms.EnumChatFormat, format.toString()));
|
||||
nms.ScoreboardTeam_setNameTagVisibility.invoke(team, Enum.valueOf(nms.EnumNameTagVisibility, String.valueOf(packet.getNameTagVisibility()).equals("always") ? "ALWAYS" : "NEVER"));
|
||||
nms.ScoreboardTeam_setCollisionRule.invoke(team, Enum.valueOf(nms.EnumTeamPush, String.valueOf(packet.getCollisionRule()).equals("always") ? "ALWAYS" : "NEVER"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes data into NMS team from custom team packet. Used on 1.12- servers.
|
||||
*
|
||||
* @param packet
|
||||
* Packet to read from
|
||||
* @param team
|
||||
* Team to write to
|
||||
* @param prefix
|
||||
* Prefix to use
|
||||
* @param suffix
|
||||
* Suffix to use
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
private void createTeamLegacy(PacketPlayOutScoreboardTeam packet, Object team, String prefix, String suffix) throws ReflectiveOperationException {
|
||||
if (prefix != null) nms.ScoreboardTeam_setPrefix.invoke(team, prefix);
|
||||
if (suffix != null) nms.ScoreboardTeam_setSuffix.invoke(team, suffix);
|
||||
if (nms.getMinorVersion() >= 8) nms.ScoreboardTeam_setNameTagVisibility.invoke(team, Enum.valueOf(nms.EnumNameTagVisibility, String.valueOf(packet.getNameTagVisibility()).equals("always") ? "ALWAYS" : "NEVER"));
|
||||
if (nms.getMinorVersion() >= 9) nms.ScoreboardTeam_setCollisionRule.invoke(team, Enum.valueOf(nms.EnumTeamPush, String.valueOf(packet.getCollisionRule()).equals("always") ? "ALWAYS" : "NEVER"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketPlayOutPlayerInfo readPlayerInfo(Object nmsPacket, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
if (nms.getMinorVersion() < 8) return null;
|
||||
if (nms.ClientboundPlayerInfoRemovePacket != null) {
|
||||
//1.19.3+
|
||||
if (nms.ClientboundPlayerInfoRemovePacket.isInstance(nmsPacket)) {
|
||||
List<UUID> entries = (List<UUID>) nms.ClientboundPlayerInfoRemovePacket_getEntries.invoke(nmsPacket);
|
||||
return new PacketPlayOutPlayerInfo(
|
||||
EnumPlayerInfoAction.REMOVE_PLAYER,
|
||||
entries.stream().map(PlayerInfoData::new).collect(Collectors.toList())
|
||||
);
|
||||
}
|
||||
EnumSet<?> set = (EnumSet<?>) nms.PacketPlayOutPlayerInfo_ACTION.get(nmsPacket);
|
||||
EnumPlayerInfoAction[] array = set.stream().map(action -> EnumPlayerInfoAction.valueOf(action.toString())).toArray(EnumPlayerInfoAction[]::new);
|
||||
EnumSet<EnumPlayerInfoAction> actions = EnumSet.of(array[0], array);
|
||||
List<PlayerInfoData> listData = new ArrayList<>();
|
||||
for (Object nmsData : (List<?>) nms.PacketPlayOutPlayerInfo_PLAYERS.get(nmsPacket)) {
|
||||
Object nmsGameMode = nms.PlayerInfoData_getGamemode.invoke(nmsData);
|
||||
EnumGamemode gameMode = (nmsGameMode == null) ? null : EnumGamemode.valueOf(nmsGameMode.toString());
|
||||
GameProfile profile = (GameProfile) nms.PlayerInfoData_getProfile.invoke(nmsData);
|
||||
Object nmsComponent = nms.PlayerInfoData_getDisplayName.invoke(nmsData);
|
||||
Skin skin = null;
|
||||
if (!profile.getProperties().get("textures").isEmpty()) {
|
||||
Property pr = profile.getProperties().get("textures").iterator().next();
|
||||
skin = new Skin(pr.getValue(), pr.getSignature());
|
||||
}
|
||||
Object remoteChatSession = nms.PlayerInfoData_getProfilePublicKeyRecord.invoke(nmsData);
|
||||
listData.add(
|
||||
new PlayerInfoData(
|
||||
profile.getName(),
|
||||
profile.getId(),
|
||||
skin,
|
||||
(boolean) nms.PlayerInfoData_isListed.invoke(nmsData),
|
||||
(int) nms.PlayerInfoData_getLatency.invoke(nmsData),
|
||||
gameMode,
|
||||
nmsComponent == null ? null : new WrappedChatComponent(nmsComponent),
|
||||
remoteChatSession == null ? null : (UUID) nms.RemoteChatSession$Data_getSessionId.invoke(remoteChatSession),
|
||||
remoteChatSession == null ? null : nms.RemoteChatSession$Data_getProfilePublicKey.invoke(remoteChatSession)));
|
||||
}
|
||||
return new PacketPlayOutPlayerInfo(actions, listData);
|
||||
} else {
|
||||
//1.19.2-
|
||||
EnumPlayerInfoAction action = EnumPlayerInfoAction.valueOf(nms.PacketPlayOutPlayerInfo_ACTION.get(nmsPacket).toString());
|
||||
List<PlayerInfoData> listData = new ArrayList<>();
|
||||
for (Object nmsData : (List<?>) nms.PacketPlayOutPlayerInfo_PLAYERS.get(nmsPacket)) {
|
||||
Object nmsGameMode = nms.PlayerInfoData_getGamemode.invoke(nmsData);
|
||||
EnumGamemode gameMode = (nmsGameMode == null) ? null : EnumGamemode.valueOf(nmsGameMode.toString());
|
||||
GameProfile profile = (GameProfile) nms.PlayerInfoData_getProfile.invoke(nmsData);
|
||||
Object nmsComponent = nms.PlayerInfoData_getDisplayName.invoke(nmsData);
|
||||
IChatBaseComponent listName = nmsComponent == null ? null : new WrappedChatComponent(nmsComponent);
|
||||
Skin skin = null;
|
||||
if (!profile.getProperties().get("textures").isEmpty()) {
|
||||
Property pr = profile.getProperties().get("textures").iterator().next();
|
||||
skin = new Skin(pr.getValue(), pr.getSignature());
|
||||
}
|
||||
Object profilePublicKey = nms.getMinorVersion() >= 19 ? nms.PlayerInfoData_getProfilePublicKeyRecord.invoke(nmsData) : null;
|
||||
listData.add(new PlayerInfoData(profile.getName(), profile.getId(), skin, true,
|
||||
(int) nms.PlayerInfoData_getLatency.invoke(nmsData), gameMode, listName, null, profilePublicKey));
|
||||
}
|
||||
return new PacketPlayOutPlayerInfo(action, listData);
|
||||
}
|
||||
return PacketPlayOutPlayerInfoStorage.read(nmsPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketPlayOutScoreboardObjective readObjective(Object nmsPacket) throws ReflectiveOperationException {
|
||||
return new PacketPlayOutScoreboardObjective(nms.PacketPlayOutScoreboardObjective_METHOD.getInt(nmsPacket),
|
||||
(String) nms.PacketPlayOutScoreboardObjective_OBJECTIVENAME.get(nmsPacket), null,
|
||||
PacketPlayOutScoreboardObjective.EnumScoreboardHealthDisplay.INTEGER
|
||||
);
|
||||
return PacketPlayOutScoreboardObjectiveStorage.read(nmsPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketPlayOutScoreboardDisplayObjective readDisplayObjective(Object nmsPacket) throws ReflectiveOperationException {
|
||||
return new PacketPlayOutScoreboardDisplayObjective(
|
||||
nms.PacketPlayOutScoreboardDisplayObjective_POSITION.getInt(nmsPacket),
|
||||
(String) nms.PacketPlayOutScoreboardDisplayObjective_OBJECTIVENAME.get(nmsPacket)
|
||||
);
|
||||
return PacketPlayOutScoreboardDisplayObjectiveStorage.read(nmsPacket);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -489,7 +76,7 @@ public class BukkitPacketBuilder extends PacketBuilder {
|
||||
|
||||
int entityId = packet.getId().hashCode();
|
||||
if (packet.getAction() == Action.REMOVE) {
|
||||
return build(new PacketPlayOutEntityDestroy(entityId));
|
||||
return new PacketPlayOutEntityDestroy(entityId).build();
|
||||
}
|
||||
DataWatcher w = new DataWatcher();
|
||||
if (packet.getAction() == Action.UPDATE_PCT || packet.getAction() == Action.ADD) {
|
||||
@@ -503,55 +90,9 @@ public class BukkitPacketBuilder extends PacketBuilder {
|
||||
if (packet.getAction() == Action.ADD) {
|
||||
w.getHelper().setEntityFlags((byte) 32);
|
||||
w.getHelper().setWitherInvulnerableTime(880); // Magic number
|
||||
return build(new PacketPlayOutSpawnEntityLiving(entityId, new UUID(0, 0), EntityType.WITHER, new Location(null, 0,0,0), w));
|
||||
return new PacketPlayOutSpawnEntityLiving(entityId, new UUID(0, 0), EntityType.WITHER, new Location(null, 0,0,0), w).build();
|
||||
} else {
|
||||
return build(new PacketPlayOutEntityMetadata(entityId, w));
|
||||
return new PacketPlayOutEntityMetadata(entityId, w).build();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A method taken from minecraft code used to convert double to int
|
||||
*
|
||||
* @param paramDouble
|
||||
* double value
|
||||
* @return int value
|
||||
*/
|
||||
private int floor(double paramDouble){
|
||||
int i = (int)paramDouble;
|
||||
return paramDouble < i ? i - 1 : i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts TAB's IChatBaseComponent into minecraft's component using String deserialization.
|
||||
* If the requested component is found in cache, it is returned. If not, it is created, added into cache and returned.
|
||||
* If {@code component} is {@code null}, returns {@code null}
|
||||
*
|
||||
* @param component
|
||||
* component to convert
|
||||
* @param clientVersion
|
||||
* client version used to decide RGB conversion
|
||||
* @return converted component or {@code null} if {@code component} is {@code null}
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public Object toNMSComponent(IChatBaseComponent component, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
if (component instanceof WrappedChatComponent) return ((WrappedChatComponent) component).get();
|
||||
return (clientVersion.getMinorVersion() >= 16 ? componentCacheModern : componentCacheLegacy).get(component, clientVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Scoreboard Objective with given name.
|
||||
*
|
||||
* @param objectiveName
|
||||
* Objective name
|
||||
* @return NMS Objective
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
private Object newScoreboardObjective(String objectiveName) throws ReflectiveOperationException {
|
||||
if (nms.getMinorVersion() >= 13) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
@@ -8,10 +8,15 @@ import io.netty.channel.ChannelDuplexHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import me.neznamy.tab.api.TabFeature;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.NMSStorage;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.nms.NMSStorage;
|
||||
import me.neznamy.tab.api.TabConstants;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.packet.PacketPlayOutPlayerInfoStorage;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.packet.PacketPlayOutScoreboardDisplayObjectiveStorage;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.packet.PacketPlayOutScoreboardObjectiveStorage;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.packet.PacketPlayOutScoreboardTeamStorage;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.features.PipelineInjector;
|
||||
import me.neznamy.tab.shared.features.sorting.Sorting;
|
||||
@@ -25,18 +30,15 @@ public class BukkitPipelineInjector extends PipelineInjector {
|
||||
/** NMS data storage */
|
||||
private final NMSStorage nms = NMSStorage.getInstance();
|
||||
|
||||
@Getter private final Function<TabPlayer, ChannelDuplexHandler> channelFunction = BukkitChannelDuplexHandler::new;
|
||||
|
||||
/**
|
||||
* Constructs new instance
|
||||
*/
|
||||
public BukkitPipelineInjector(){
|
||||
public BukkitPipelineInjector() {
|
||||
super("packet_handler");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function<TabPlayer, ChannelDuplexHandler> getChannelFunction() {
|
||||
return BukkitChannelDuplexHandler::new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom channel duplex handler override
|
||||
*/
|
||||
@@ -51,7 +53,7 @@ public class BukkitPipelineInjector extends PipelineInjector {
|
||||
try {
|
||||
if (TAB.getInstance().getFeatureManager().onPacketReceive(player, packet)) return;
|
||||
super.channelRead(context, packet);
|
||||
} catch (Exception e){
|
||||
} catch (Exception e) {
|
||||
TAB.getInstance().getErrorManager().printError("An error occurred when reading packets", e);
|
||||
}
|
||||
}
|
||||
@@ -59,26 +61,27 @@ public class BukkitPipelineInjector extends PipelineInjector {
|
||||
@Override
|
||||
public void write(ChannelHandlerContext context, Object packet, ChannelPromise channelPromise) {
|
||||
try {
|
||||
if (nms.PacketPlayOutPlayerInfo.isInstance(packet) ||
|
||||
(nms.ClientboundPlayerInfoRemovePacket != null && nms.ClientboundPlayerInfoRemovePacket.isInstance(packet))) {
|
||||
if (PacketPlayOutPlayerInfoStorage.CLASS.isInstance(packet) ||
|
||||
(PacketPlayOutPlayerInfoStorage.ClientboundPlayerInfoRemovePacket != null &&
|
||||
PacketPlayOutPlayerInfoStorage.ClientboundPlayerInfoRemovePacket.isInstance(packet))) {
|
||||
super.write(context, TAB.getInstance().getFeatureManager().onPacketPlayOutPlayerInfo(player, packet), channelPromise);
|
||||
return;
|
||||
}
|
||||
if (antiOverrideTeams && nms.PacketPlayOutScoreboardTeam.isInstance(packet)) {
|
||||
if (antiOverrideTeams && PacketPlayOutScoreboardTeamStorage.CLASS.isInstance(packet)) {
|
||||
long time = System.nanoTime();
|
||||
modifyPlayers(packet);
|
||||
TAB.getInstance().getCPUManager().addTime("NameTags", TabConstants.CpuUsageCategory.ANTI_OVERRIDE, System.nanoTime()-time);
|
||||
super.write(context, packet, channelPromise);
|
||||
return;
|
||||
}
|
||||
if (nms.PacketPlayOutScoreboardDisplayObjective.isInstance(packet)){
|
||||
if (PacketPlayOutScoreboardDisplayObjectiveStorage.CLASS.isInstance(packet)) {
|
||||
TAB.getInstance().getFeatureManager().onDisplayObjective(player, packet);
|
||||
}
|
||||
if (nms.PacketPlayOutScoreboardObjective.isInstance(packet)) {
|
||||
if (PacketPlayOutScoreboardObjectiveStorage.CLASS.isInstance(packet)) {
|
||||
TAB.getInstance().getFeatureManager().onObjective(player, packet);
|
||||
}
|
||||
TAB.getInstance().getFeatureManager().onPacketSend(player, packet);
|
||||
} catch (Exception e){
|
||||
} catch (Exception e) {
|
||||
TAB.getInstance().getErrorManager().printError("An error occurred when reading packets", e);
|
||||
}
|
||||
try {
|
||||
@@ -98,10 +101,10 @@ public class BukkitPipelineInjector extends PipelineInjector {
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private void modifyPlayers(Object packetPlayOutScoreboardTeam) throws ReflectiveOperationException {
|
||||
int action = nms.PacketPlayOutScoreboardTeam_ACTION.getInt(packetPlayOutScoreboardTeam);
|
||||
int action = PacketPlayOutScoreboardTeamStorage.ACTION.getInt(packetPlayOutScoreboardTeam);
|
||||
if (action == 1 || action == 2 || action == 4) return;
|
||||
Collection<String> players = (Collection<String>) nms.PacketPlayOutScoreboardTeam_PLAYERS.get(packetPlayOutScoreboardTeam);
|
||||
String teamName = (String) nms.PacketPlayOutScoreboardTeam_NAME.get(packetPlayOutScoreboardTeam);
|
||||
Collection<String> players = (Collection<String>) PacketPlayOutScoreboardTeamStorage.PLAYERS.get(packetPlayOutScoreboardTeam);
|
||||
String teamName = (String) PacketPlayOutScoreboardTeamStorage.NAME.get(packetPlayOutScoreboardTeam);
|
||||
if (players == null) return;
|
||||
//creating a new list to prevent NoSuchFieldException in minecraft packet encoder when a player is removed
|
||||
Collection<String> newList = new ArrayList<>();
|
||||
@@ -119,7 +122,7 @@ public class BukkitPipelineInjector extends PipelineInjector {
|
||||
newList.add(entry);
|
||||
}
|
||||
}
|
||||
nms.setField(packetPlayOutScoreboardTeam, nms.PacketPlayOutScoreboardTeam_PLAYERS, newList);
|
||||
PacketPlayOutScoreboardTeamStorage.PLAYERS.set(packetPlayOutScoreboardTeam, newList);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-18
@@ -13,8 +13,6 @@ import org.bukkit.plugin.RegisteredServiceProvider;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
@@ -22,9 +20,6 @@ import java.util.UUID;
|
||||
*/
|
||||
public class BukkitPlaceholderRegistry extends UniversalPlaceholderRegistry {
|
||||
|
||||
/** Number formatter for 2 decimal places */
|
||||
private final NumberFormat numberFormat = NumberFormat.getNumberInstance(Locale.US);
|
||||
|
||||
/** Vault Chat hook */
|
||||
private Chat chat;
|
||||
|
||||
@@ -47,7 +42,6 @@ public class BukkitPlaceholderRegistry extends UniversalPlaceholderRegistry {
|
||||
* Constructs new instance and loads hooks
|
||||
*/
|
||||
public BukkitPlaceholderRegistry() {
|
||||
numberFormat.setMaximumFractionDigits(2);
|
||||
if (Bukkit.getPluginManager().isPluginEnabled(TabConstants.Plugin.VAULT)) {
|
||||
RegisteredServiceProvider<Chat> rspChat = Bukkit.getServicesManager().getRegistration(Chat.class);
|
||||
if (rspChat != null) chat = rspChat.getProvider();
|
||||
@@ -81,7 +75,7 @@ public class BukkitPlaceholderRegistry extends UniversalPlaceholderRegistry {
|
||||
manager.registerServerPlaceholder(TabConstants.Placeholder.TPS, -1, () -> -1);
|
||||
}
|
||||
if (paperMspt != null) {
|
||||
manager.registerServerPlaceholder(TabConstants.Placeholder.MSPT, 1000, () -> numberFormat.format(Bukkit.getAverageTickTime()));
|
||||
manager.registerServerPlaceholder(TabConstants.Placeholder.MSPT, 1000, () -> format(Bukkit.getAverageTickTime()));
|
||||
}
|
||||
Plugin essentials = Bukkit.getPluginManager().getPlugin(TabConstants.Plugin.ESSENTIALS);
|
||||
manager.registerPlayerPlaceholder(TabConstants.Placeholder.AFK, 500, p -> {
|
||||
@@ -108,15 +102,4 @@ public class BukkitPlaceholderRegistry extends UniversalPlaceholderRegistry {
|
||||
manager.registerPlayerPlaceholder(TabConstants.Placeholder.HEALTH, 100, p -> (int) Math.ceil(((Player) p.getPlayer()).getHealth()));
|
||||
super.registerPlaceholders(manager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats TPS using number formatter with 2 decimal places.
|
||||
*
|
||||
* @param tps
|
||||
* TPS to format
|
||||
* @return Formatted TPS as a String
|
||||
*/
|
||||
private String formatTPS(double tps) {
|
||||
return numberFormat.format(Math.min(20, tps));
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package me.neznamy.tab.platforms.bukkit;
|
||||
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
@@ -15,10 +14,10 @@ import me.neznamy.tab.platforms.bukkit.features.PerWorldPlayerList;
|
||||
import me.neznamy.tab.platforms.bukkit.features.PetFix;
|
||||
import me.neznamy.tab.platforms.bukkit.features.WitherBossBar;
|
||||
import me.neznamy.tab.platforms.bukkit.features.unlimitedtags.BukkitNameTagX;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.nms.NMSStorage;
|
||||
import me.neznamy.tab.platforms.bukkit.permission.Vault;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.backend.BackendPlatform;
|
||||
import me.neznamy.tab.shared.features.PipelineInjector;
|
||||
import me.neznamy.tab.shared.features.PlaceholderManagerImpl;
|
||||
import me.neznamy.tab.shared.features.TabExpansion;
|
||||
import me.neznamy.tab.shared.features.bossbar.BossBarManagerImpl;
|
||||
@@ -42,6 +41,9 @@ import java.util.Collection;
|
||||
*/
|
||||
public class BukkitPlatform extends BackendPlatform {
|
||||
|
||||
@Getter private final BukkitPacketBuilder packetBuilder = new BukkitPacketBuilder();
|
||||
@Getter private final BukkitPipelineInjector pipelineInjector = NMSStorage.getInstance().getMinorVersion() >= 8 ? new BukkitPipelineInjector() : null;
|
||||
|
||||
/** Plugin instance for registering tasks and events */
|
||||
private final JavaPlugin plugin;
|
||||
|
||||
@@ -58,7 +60,6 @@ public class BukkitPlatform extends BackendPlatform {
|
||||
* plugin instance
|
||||
*/
|
||||
public BukkitPlatform(JavaPlugin plugin) {
|
||||
super(new BukkitPacketBuilder());
|
||||
this.plugin = plugin;
|
||||
if (Bukkit.getPluginManager().isPluginEnabled(TabConstants.Plugin.VIAVERSION)) {
|
||||
if (ReflectionUtils.classExists("com.viaversion.viaversion.api.Via")) {
|
||||
@@ -106,11 +107,6 @@ public class BukkitPlatform extends BackendPlatform {
|
||||
new BukkitPlaceholderRegistry().registerPlaceholders(TAB.getInstance().getPlaceholderManager());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable PipelineInjector getPipelineInjector() {
|
||||
return new BukkitPipelineInjector();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NameTag getUnlimitedNametags() {
|
||||
return new BukkitNameTagX(plugin);
|
||||
@@ -204,13 +200,13 @@ public class BukkitPlatform extends BackendPlatform {
|
||||
* @return protocol version of the player
|
||||
*/
|
||||
public int getProtocolVersion(Player player) {
|
||||
if (protocolSupport){
|
||||
if (protocolSupport) {
|
||||
int version = getProtocolVersionPS(player);
|
||||
//some PS versions return -1 on unsupported server versions instead of throwing exception
|
||||
if (version != -1 && version < TAB.getInstance().getServerVersion().getNetworkId()) return version;
|
||||
}
|
||||
if (viaVersion != null) {
|
||||
return getProtocolVersionVia(player, 0);
|
||||
return getProtocolVersionVia(player.getUniqueId(), player.getName(), 0);
|
||||
}
|
||||
return TAB.getInstance().getServerVersion().getNetworkId();
|
||||
}
|
||||
@@ -222,7 +218,7 @@ public class BukkitPlatform extends BackendPlatform {
|
||||
* Player to get protocol version of
|
||||
* @return protocol version of the player using ProtocolSupport
|
||||
*/
|
||||
private int getProtocolVersionPS(Player player){
|
||||
private int getProtocolVersionPS(Player player) {
|
||||
try {
|
||||
Object protocolVersion = Class.forName("protocolsupport.api.ProtocolSupportAPI").getMethod("getProtocolVersion", Player.class).invoke(null, player);
|
||||
int version = (int) protocolVersion.getClass().getMethod("getId").invoke(protocolVersion);
|
||||
@@ -234,36 +230,6 @@ public class BukkitPlatform extends BackendPlatform {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns protocol version of requested player using ViaVersion
|
||||
*
|
||||
* @param player
|
||||
* Player to get protocol version of
|
||||
* @return protocol version of the player using ViaVersion
|
||||
*/
|
||||
private int getProtocolVersionVia(Player player, int retryLevel){
|
||||
try {
|
||||
if (retryLevel == 10) {
|
||||
TAB.getInstance().debug("Failed to get protocol version of " + player.getName() + " after 10 retries");
|
||||
return TAB.getInstance().getServerVersion().getNetworkId();
|
||||
}
|
||||
int version = Via.getAPI().getPlayerVersion(player.getUniqueId());
|
||||
if (version == -1) {
|
||||
if (!player.isOnline()) return TAB.getInstance().getServerVersion().getNetworkId();
|
||||
Thread.sleep(5);
|
||||
return getProtocolVersionVia(player, retryLevel + 1);
|
||||
}
|
||||
TAB.getInstance().debug("ViaVersion returned protocol version " + version + " for " + player.getName() + " (online=" + player.isOnline() + ")");
|
||||
return version;
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
return -1;
|
||||
} catch (Exception | LinkageError e) {
|
||||
TAB.getInstance().getErrorManager().printError(String.format("Failed to get protocol version of %s using ViaVersion v%s", player.getName(), viaVersion.getDescription().getVersion()), e);
|
||||
return TAB.getInstance().getServerVersion().getNetworkId();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends console message using ConsoleCommandSender, due to
|
||||
* Paper not translating colors correctly in Logger messages
|
||||
|
||||
+6
-7
@@ -6,7 +6,7 @@ import me.neznamy.tab.api.TabConstants;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import me.neznamy.tab.api.chat.EnumChatFormat;
|
||||
import me.neznamy.tab.api.util.SupplierWithException;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.*;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.nms.*;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import org.bstats.bukkit.Metrics;
|
||||
import org.bstats.charts.SimplePie;
|
||||
@@ -23,14 +23,14 @@ import java.util.List;
|
||||
/**
|
||||
* Main class for Bukkit platform
|
||||
*/
|
||||
public class Main extends JavaPlugin {
|
||||
public class BukkitTAB extends JavaPlugin {
|
||||
|
||||
@Override
|
||||
public void onEnable(){
|
||||
public void onEnable() {
|
||||
String version = Bukkit.getBukkitVersion().split("-")[0];
|
||||
String serverPackage = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
|
||||
Bukkit.getConsoleSender().sendMessage(EnumChatFormat.color("[TAB] Server version: " + version + " (" + serverPackage + ")"));
|
||||
if (!isVersionSupported()){
|
||||
if (!isVersionSupported()) {
|
||||
Bukkit.getPluginManager().disablePlugin(this);
|
||||
return;
|
||||
}
|
||||
@@ -66,7 +66,7 @@ public class Main extends JavaPlugin {
|
||||
*
|
||||
* @return {@code true} if server version is compatible, {@code false} if not
|
||||
*/
|
||||
private boolean isVersionSupported(){
|
||||
private boolean isVersionSupported() {
|
||||
List<String> supportedVersions = Arrays.asList(
|
||||
"v1_5_R1", "v1_5_R2", "v1_5_R3", "v1_6_R1", "v1_6_R2", "v1_6_R3",
|
||||
"v1_7_R1", "v1_7_R2", "v1_7_R3", "v1_7_R4", "v1_8_R1", "v1_8_R2", "v1_8_R3",
|
||||
@@ -76,7 +76,6 @@ public class Main extends JavaPlugin {
|
||||
String serverPackage = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
|
||||
try {
|
||||
long time = System.currentTimeMillis();
|
||||
int minorVersion = Integer.parseInt(serverPackage.split("_")[1]);
|
||||
NMSStorage.setInstance(getNMSLoader());
|
||||
if (supportedVersions.contains(serverPackage)) {
|
||||
Bukkit.getConsoleSender().sendMessage(EnumChatFormat.color("[TAB] Loaded NMS hook in " + (System.currentTimeMillis()-time) + "ms"));
|
||||
@@ -103,7 +102,7 @@ public class Main extends JavaPlugin {
|
||||
for (SupplierWithException<NMSStorage> loader : loaders) {
|
||||
try {
|
||||
return loader.get();
|
||||
} catch (Exception ignored){}
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
throw new IllegalStateException("Unsupported server version");
|
||||
}
|
||||
@@ -12,7 +12,7 @@ import me.neznamy.tab.api.chat.rgb.RGBUtils;
|
||||
import me.neznamy.tab.api.protocol.PacketPlayOutBoss;
|
||||
import me.neznamy.tab.api.protocol.PacketPlayOutChat;
|
||||
import me.neznamy.tab.api.protocol.Skin;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.NMSStorage;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.nms.NMSStorage;
|
||||
import me.neznamy.tab.shared.ITabPlayer;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import org.bukkit.Bukkit;
|
||||
@@ -55,7 +55,7 @@ public class BukkitTabPlayer extends ITabPlayer {
|
||||
* @param protocolVersion
|
||||
* Player's protocol network id
|
||||
*/
|
||||
public BukkitTabPlayer(Player p, int protocolVersion){
|
||||
public BukkitTabPlayer(Player p, int protocolVersion) {
|
||||
super(p, p.getUniqueId(), p.getName(), TAB.getInstance().getConfiguration().getServerName(), p.getWorld().getName(), protocolVersion, true);
|
||||
try {
|
||||
handle = NMSStorage.getInstance().getHandle.invoke(player);
|
||||
|
||||
+7
-17
@@ -1,5 +1,6 @@
|
||||
package me.neznamy.tab.platforms.bukkit.features;
|
||||
|
||||
import lombok.Getter;
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||
import me.neznamy.tab.api.TabAPI;
|
||||
@@ -23,28 +24,17 @@ public class BukkitTabExpansion extends PlaceholderExpansion implements TabExpan
|
||||
/** Map holding all values for all players for easy and high-performance access */
|
||||
private final Map<TabPlayer, Map<String, String>> values = new WeakHashMap<>();
|
||||
|
||||
@Getter private final String author = "NEZNAMY";
|
||||
@Getter private final String identifier = TabConstants.PLUGIN_ID;
|
||||
@Getter private final String version = TabConstants.PLUGIN_VERSION;
|
||||
|
||||
@Override
|
||||
public boolean persist(){
|
||||
public boolean persist() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getAuthor(){
|
||||
return "NEZNAMY";
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getIdentifier(){
|
||||
return "tab";
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getVersion() {
|
||||
return TabConstants.PLUGIN_VERSION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onPlaceholderRequest(Player player, @NotNull String identifier){
|
||||
public String onPlaceholderRequest(Player player, @NotNull String identifier) {
|
||||
if (identifier.startsWith("replace_")) {
|
||||
String text = "%" + identifier.substring(8) + "%";
|
||||
String textBefore;
|
||||
|
||||
+3
-3
@@ -43,12 +43,12 @@ public class PerWorldPlayerList extends TabFeature implements Listener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(){
|
||||
public void load() {
|
||||
Bukkit.getOnlinePlayers().forEach(this::checkPlayer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unload(){
|
||||
public void unload() {
|
||||
for (Player p : Bukkit.getOnlinePlayers()) {
|
||||
for (Player pl : Bukkit.getOnlinePlayers()) {
|
||||
p.showPlayer(pl);
|
||||
@@ -80,7 +80,7 @@ public class PerWorldPlayerList extends TabFeature implements Listener {
|
||||
* Player to update
|
||||
*/
|
||||
private void checkPlayer(Player p) {
|
||||
for (Player all : Bukkit.getOnlinePlayers()){
|
||||
for (Player all : Bukkit.getOnlinePlayers()) {
|
||||
if (all == p) continue;
|
||||
if (!shouldSee(p, all) && p.canSee(all)) p.hidePlayer(all);
|
||||
if (shouldSee(p, all) && !p.canSee(all)) p.showPlayer(all);
|
||||
|
||||
@@ -3,7 +3,10 @@ package me.neznamy.tab.platforms.bukkit.features;
|
||||
import me.neznamy.tab.api.TabAPI;
|
||||
import me.neznamy.tab.api.TabFeature;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.NMSStorage;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.PacketPlayOutEntityMetadata;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.PacketPlayOutSpawnEntityLiving;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcherObject;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.nms.NMSStorage;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcher;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcherItem;
|
||||
|
||||
@@ -118,9 +121,9 @@ public class PetFix extends TabFeature {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void onPacketSend(TabPlayer receiver, Object packet) throws ReflectiveOperationException {
|
||||
if (nms.PacketPlayOutEntityMetadata.isInstance(packet)) {
|
||||
if (PacketPlayOutEntityMetadata.CLASS.isInstance(packet)) {
|
||||
Object removedEntry = null;
|
||||
List<Object> items = (List<Object>) nms.PacketPlayOutEntityMetadata_LIST.get(packet);
|
||||
List<Object> items = (List<Object>) PacketPlayOutEntityMetadata.LIST.get(packet);
|
||||
if (items == null) return;
|
||||
try {
|
||||
for (Object item : items) {
|
||||
@@ -128,11 +131,11 @@ public class PetFix extends TabFeature {
|
||||
int slot;
|
||||
Object value;
|
||||
if (nms.is1_19_3Plus()) {
|
||||
slot = nms.DataWatcher$DataValue_POSITION.getInt(item);
|
||||
value = nms.DataWatcher$DataValue_VALUE.get(item);
|
||||
slot = DataWatcher.DataValue_POSITION.getInt(item);
|
||||
value = DataWatcher.DataValue_VALUE.get(item);
|
||||
} else {
|
||||
slot = nms.DataWatcherObject_SLOT.getInt(nms.DataWatcherItem_TYPE.get(item));
|
||||
value = nms.DataWatcherItem_VALUE.get(item);
|
||||
slot = DataWatcherObject.SLOT.getInt(DataWatcherItem.TYPE.get(item));
|
||||
value = DataWatcherItem.VALUE.get(item);
|
||||
}
|
||||
if (slot == petOwnerPosition) {
|
||||
if (value instanceof Optional || value instanceof com.google.common.base.Optional) {
|
||||
@@ -145,13 +148,13 @@ public class PetFix extends TabFeature {
|
||||
onPacketSend(receiver, packet);
|
||||
}
|
||||
if (removedEntry != null) items.remove(removedEntry);
|
||||
} else if (nms.PacketPlayOutSpawnEntityLiving.isInstance(packet) && nms.PacketPlayOutSpawnEntityLiving_DATAWATCHER != null) {
|
||||
} else if (PacketPlayOutSpawnEntityLiving.CLASS.isInstance(packet) && PacketPlayOutSpawnEntityLiving.DATA_WATCHER != null) {
|
||||
//<1.15
|
||||
DataWatcher watcher = DataWatcher.fromNMS(nms.PacketPlayOutSpawnEntityLiving_DATAWATCHER.get(packet));
|
||||
DataWatcher watcher = DataWatcher.fromNMS(PacketPlayOutSpawnEntityLiving.DATA_WATCHER.get(packet));
|
||||
DataWatcherItem petOwner = watcher.getItem(petOwnerPosition);
|
||||
if (petOwner != null && (petOwner.getValue() instanceof Optional || petOwner.getValue() instanceof com.google.common.base.Optional)) {
|
||||
watcher.removeValue(petOwnerPosition);
|
||||
nms.setField(packet, nms.PacketPlayOutSpawnEntityLiving_DATAWATCHER, watcher.toNMS());
|
||||
PacketPlayOutSpawnEntityLiving.DATA_WATCHER.set(packet, watcher.build());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -27,7 +27,7 @@ public class BukkitArmorStand extends BackendArmorStand {
|
||||
private final Player player;
|
||||
|
||||
/** Entity destroy packet */
|
||||
protected TabPacket destroyPacket = new PacketPlayOutEntityDestroy(entityId);
|
||||
protected final TabPacket destroyPacket = new PacketPlayOutEntityDestroy(entityId);
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters.
|
||||
@@ -77,16 +77,16 @@ public class BukkitArmorStand extends BackendArmorStand {
|
||||
//1.14+ server sided bug
|
||||
Entity vehicle = player.getVehicle();
|
||||
if (vehicle != null) {
|
||||
if (vehicle.getType().toString().contains("HORSE")) { //covering all 3 horse types
|
||||
if (vehicle.getType().toString().contains("horse")) { //covering all 3 horse types
|
||||
y = vehicle.getLocation().getY() + 0.85;
|
||||
}
|
||||
if (vehicle.getType().toString().equals("DONKEY")) { //1.11+
|
||||
if (vehicle.getType().toString().equals("donkey")) { //1.11+
|
||||
y = vehicle.getLocation().getY() + 0.525;
|
||||
}
|
||||
if (vehicle.getType() == EntityType.PIG) {
|
||||
y = vehicle.getLocation().getY() + 0.325;
|
||||
}
|
||||
if (vehicle.getType().toString().equals("STRIDER")) { //1.16+
|
||||
if (vehicle.getType().toString().equals("strider")) { //1.16+
|
||||
y = vehicle.getLocation().getY() + 1.15;
|
||||
}
|
||||
} else {
|
||||
|
||||
+10
-8
@@ -3,7 +3,9 @@ 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.platforms.bukkit.nms.storage.NMSStorage;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.PacketPlayOutEntityDestroy;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.PacketPlayOutEntityTeleport;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.nms.NMSStorage;
|
||||
import me.neznamy.tab.shared.backend.features.unlimitedtags.BackendArmorStand;
|
||||
import me.neznamy.tab.shared.backend.features.unlimitedtags.BackendArmorStandManager;
|
||||
import me.neznamy.tab.shared.backend.features.unlimitedtags.BackendNameTagX;
|
||||
@@ -52,7 +54,7 @@ public class BukkitNameTagX extends BackendNameTagX {
|
||||
}
|
||||
}
|
||||
if (attacked != null && attacked != sender) {
|
||||
nms.setField(packet, nms.PacketPlayInUseEntity_ENTITY, getEntityId(attacked));
|
||||
nms.PacketPlayInUseEntity_ENTITY.set(packet, getEntityId(attacked));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@@ -65,13 +67,13 @@ public class BukkitNameTagX extends BackendNameTagX {
|
||||
if (!receiver.isLoaded() || isDisabledPlayer(receiver) || getDisabledUnlimitedPlayers().contains(receiver)) return;
|
||||
if (nms.PacketPlayOutEntity.isInstance(packet) && !nms.PacketPlayOutEntityLook.isInstance(packet)) { //ignoring head rotation only packets
|
||||
packetListener.onEntityMove(receiver, nms.PacketPlayOutEntity_ENTITYID.getInt(packet));
|
||||
} else if (nms.PacketPlayOutEntityTeleport.isInstance(packet)) {
|
||||
packetListener.onEntityMove(receiver, nms.PacketPlayOutEntityTeleport_ENTITYID.getInt(packet));
|
||||
} else if (PacketPlayOutEntityTeleport.CLASS.isInstance(packet)) {
|
||||
packetListener.onEntityMove(receiver, PacketPlayOutEntityTeleport.ENTITY_ID.getInt(packet));
|
||||
} else if (nms.PacketPlayOutNamedEntitySpawn.isInstance(packet)) {
|
||||
packetListener.onEntitySpawn(receiver, nms.PacketPlayOutNamedEntitySpawn_ENTITYID.getInt(packet));
|
||||
} else if (nms.PacketPlayOutEntityDestroy.isInstance(packet)) {
|
||||
} else if (PacketPlayOutEntityDestroy.CLASS.isInstance(packet)) {
|
||||
if (nms.getMinorVersion() >= 17) {
|
||||
Object entities = nms.PacketPlayOutEntityDestroy_ENTITIES.get(packet);
|
||||
Object entities = PacketPlayOutEntityDestroy.ENTITIES.get(packet);
|
||||
if (entities instanceof List) {
|
||||
packetListener.onEntityDestroy(receiver, (List<Integer>) entities);
|
||||
} else {
|
||||
@@ -79,7 +81,7 @@ public class BukkitNameTagX extends BackendNameTagX {
|
||||
packetListener.onEntityDestroy(receiver, (int) entities);
|
||||
}
|
||||
} else {
|
||||
packetListener.onEntityDestroy(receiver, (int[]) nms.PacketPlayOutEntityDestroy_ENTITIES.get(packet));
|
||||
packetListener.onEntityDestroy(receiver, (int[]) PacketPlayOutEntityDestroy.ENTITIES.get(packet));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -142,7 +144,7 @@ public class BukkitNameTagX extends BackendNameTagX {
|
||||
|
||||
@Override
|
||||
public String getEntityType(Object entity) {
|
||||
return ((Entity)entity).getType().toString();
|
||||
return ((Entity) entity).getType().toString().toLowerCase();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+44
-1
@@ -2,6 +2,10 @@ package me.neznamy.tab.platforms.bukkit.nms;
|
||||
|
||||
import lombok.Data;
|
||||
import me.neznamy.tab.api.protocol.TabPacket;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.nms.NMSStorage;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* Custom class for holding data used in PacketPlayOutEntityDestroy minecraft packet.
|
||||
@@ -9,9 +13,32 @@ import me.neznamy.tab.api.protocol.TabPacket;
|
||||
@Data
|
||||
public class PacketPlayOutEntityDestroy implements TabPacket {
|
||||
|
||||
/** Destroyed entities */
|
||||
/** NMS Fields */
|
||||
public static Class<?> CLASS;
|
||||
public static Constructor<?> CONSTRUCTOR;
|
||||
public static Field ENTITIES;
|
||||
|
||||
/** Packet's instance fields */
|
||||
private final int[] entities;
|
||||
|
||||
/**
|
||||
* Loads all required Fields and throws Exception if something went wrong
|
||||
*
|
||||
* @param nms
|
||||
* NMS storage reference
|
||||
* @throws NoSuchMethodException
|
||||
* If something fails
|
||||
*/
|
||||
public static void load(NMSStorage nms) throws NoSuchMethodException {
|
||||
(ENTITIES = CLASS.getDeclaredFields()[0]).setAccessible(true);
|
||||
try {
|
||||
CONSTRUCTOR = CLASS.getConstructor(int[].class);
|
||||
} catch (NoSuchMethodException e) {
|
||||
//1.17.0
|
||||
CONSTRUCTOR = CLASS.getConstructor(int.class);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameter
|
||||
*
|
||||
@@ -21,4 +48,20 @@ public class PacketPlayOutEntityDestroy implements TabPacket {
|
||||
public PacketPlayOutEntityDestroy(int... entities) {
|
||||
this.entities = entities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this class into NMS packet
|
||||
*
|
||||
* @return NMS packet
|
||||
* @throws ReflectiveOperationException
|
||||
* If something went wrong
|
||||
*/
|
||||
public Object build() throws ReflectiveOperationException {
|
||||
if (CONSTRUCTOR.getParameterTypes()[0] != int.class) {
|
||||
return CONSTRUCTOR.newInstance(new Object[]{entities});
|
||||
} else {
|
||||
//1.17.0
|
||||
return CONSTRUCTOR.newInstance(entities[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
+47
-5
@@ -1,19 +1,61 @@
|
||||
package me.neznamy.tab.platforms.bukkit.nms;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
import lombok.ToString;
|
||||
import me.neznamy.tab.api.protocol.TabPacket;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcher;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.nms.NMSStorage;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Custom class for holding data used in PacketPlayOutEntityMetadata minecraft packet.
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor @ToString
|
||||
public class PacketPlayOutEntityMetadata implements TabPacket {
|
||||
|
||||
/** Entity's id */
|
||||
private final int entityId;
|
||||
/** NMS Fields */
|
||||
public static Class<?> CLASS;
|
||||
public static Constructor<?> CONSTRUCTOR;
|
||||
public static Field LIST;
|
||||
|
||||
/** Entity's data that changed */
|
||||
/** Packet's instance fields */
|
||||
private final int entityId;
|
||||
@NonNull private final DataWatcher dataWatcher;
|
||||
|
||||
/**
|
||||
* Loads all required Fields and throws Exception if something went wrong
|
||||
*
|
||||
* @param nms
|
||||
* NMS storage reference
|
||||
* @throws NoSuchMethodException
|
||||
* If something fails
|
||||
*/
|
||||
public static void load(NMSStorage nms) throws NoSuchMethodException {
|
||||
if (nms.is1_19_3Plus()) {
|
||||
CONSTRUCTOR = CLASS.getConstructor(int.class, List.class);
|
||||
} else {
|
||||
CONSTRUCTOR = CLASS.getConstructor(int.class, DataWatcher.CLASS, boolean.class);
|
||||
}
|
||||
LIST = nms.getFields(CLASS, List.class).get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this class into NMS packet
|
||||
*
|
||||
* @return NMS packet
|
||||
* @throws ReflectiveOperationException
|
||||
* If something went wrong
|
||||
*/
|
||||
public Object build() throws ReflectiveOperationException {
|
||||
if (CONSTRUCTOR.getParameterCount() == 2) {
|
||||
//1.19.3+
|
||||
return CONSTRUCTOR.newInstance(entityId, DataWatcher.packDirty.invoke(dataWatcher.build()));
|
||||
} else {
|
||||
return CONSTRUCTOR.newInstance(entityId, dataWatcher.build(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
+81
-5
@@ -1,19 +1,95 @@
|
||||
package me.neznamy.tab.platforms.bukkit.nms;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
import lombok.ToString;
|
||||
import me.neznamy.tab.api.protocol.TabPacket;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.nms.NMSStorage;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* Custom class for holding data used in PacketPlayOutEntityTeleport minecraft packet.
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor @ToString
|
||||
public class PacketPlayOutEntityTeleport implements TabPacket {
|
||||
|
||||
/** Entity's id */
|
||||
private final int entityId;
|
||||
/** NMS Fields */
|
||||
public static Class<?> CLASS;
|
||||
public static Constructor<?> CONSTRUCTOR;
|
||||
public static Field ENTITY_ID;
|
||||
public static Field X;
|
||||
public static Field Y;
|
||||
public static Field Z;
|
||||
public static Field YAW;
|
||||
public static Field PITCH;
|
||||
|
||||
/** Entity's new location */
|
||||
/** Packet's instance fields */
|
||||
private final int entityId;
|
||||
@NonNull private final Location location;
|
||||
|
||||
/**
|
||||
* Loads all required Fields and throws Exception if something went wrong
|
||||
*
|
||||
* @param nms
|
||||
* NMS storage reference
|
||||
* @throws NoSuchMethodException
|
||||
* If something fails
|
||||
*/
|
||||
public static void load(NMSStorage nms) throws NoSuchMethodException {
|
||||
ENTITY_ID = nms.getFields(CLASS, int.class).get(0);
|
||||
YAW = nms.getFields(CLASS, byte.class).get(0);
|
||||
PITCH = nms.getFields(CLASS, byte.class).get(1);
|
||||
if (nms.getMinorVersion() >= 17) {
|
||||
CONSTRUCTOR = CLASS.getConstructor(nms.Entity);
|
||||
} else {
|
||||
CONSTRUCTOR = CLASS.getConstructor();
|
||||
}
|
||||
if (nms.getMinorVersion() >= 9) {
|
||||
X = nms.getFields(CLASS, double.class).get(0);
|
||||
Y = nms.getFields(CLASS, double.class).get(1);
|
||||
Z = nms.getFields(CLASS, double.class).get(2);
|
||||
} else {
|
||||
X = nms.getFields(CLASS, int.class).get(1);
|
||||
Y = nms.getFields(CLASS, int.class).get(2);
|
||||
Z = nms.getFields(CLASS, int.class).get(3);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this class into NMS packet
|
||||
*
|
||||
* @return NMS packet
|
||||
* @throws ReflectiveOperationException
|
||||
* If something went wrong
|
||||
*/
|
||||
public Object build() throws ReflectiveOperationException {
|
||||
NMSStorage nms = NMSStorage.getInstance();
|
||||
Object nmsPacket;
|
||||
if (nms.getMinorVersion() >= 17) {
|
||||
nmsPacket = CONSTRUCTOR.newInstance(nms.dummyEntity);
|
||||
} else {
|
||||
nmsPacket = CONSTRUCTOR.newInstance();
|
||||
}
|
||||
ENTITY_ID.set(nmsPacket, entityId);
|
||||
if (nms.getMinorVersion() >= 9) {
|
||||
X.set(nmsPacket, location.getX());
|
||||
Y.set(nmsPacket, location.getY());
|
||||
Z.set(nmsPacket, location.getZ());
|
||||
} else {
|
||||
X.set(nmsPacket, floor(location.getX()*32));
|
||||
Y.set(nmsPacket, floor(location.getY()*32));
|
||||
Z.set(nmsPacket, floor(location.getZ()*32));
|
||||
}
|
||||
YAW.set(nmsPacket, (byte) (location.getYaw()/360*256));
|
||||
PITCH.set(nmsPacket, (byte) (location.getPitch()/360*256));
|
||||
return nmsPacket;
|
||||
}
|
||||
|
||||
private int floor(double paramDouble) {
|
||||
int i = (int)paramDouble;
|
||||
return paramDouble < i ? i - 1 : i;
|
||||
}
|
||||
}
|
||||
+127
-11
@@ -1,32 +1,148 @@
|
||||
package me.neznamy.tab.platforms.bukkit.nms;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
import lombok.ToString;
|
||||
import me.neznamy.tab.api.protocol.TabPacket;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcher;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.nms.NMSStorage;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.EntityType;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.EnumMap;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Custom class for holding data used in PacketPlayOutSpawnEntityLiving minecraft packet.
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor @ToString
|
||||
public class PacketPlayOutSpawnEntityLiving implements TabPacket {
|
||||
|
||||
/** Entity's id */
|
||||
/** NMS Fields */
|
||||
public static Class<?> CLASS;
|
||||
public static Class<?> EntityTypes;
|
||||
public static Constructor<?> CONSTRUCTOR;
|
||||
public static Field ENTITY_ID;
|
||||
public static Field ENTITY_TYPE;
|
||||
public static Field YAW;
|
||||
public static Field PITCH;
|
||||
public static Field UUID;
|
||||
public static Field X;
|
||||
public static Field Y;
|
||||
public static Field Z;
|
||||
public static Field DATA_WATCHER;
|
||||
public static Object EntityTypes_ARMOR_STAND;
|
||||
|
||||
/** Entity types */
|
||||
public static final EnumMap<EntityType, Integer> entityIds = new EnumMap<>(EntityType.class);
|
||||
|
||||
/** Packet's instance fields */
|
||||
private final int entityId;
|
||||
|
||||
/** Entity's UUID (for 1.9+ servers) */
|
||||
@NonNull private final UUID uniqueId;
|
||||
|
||||
/** Type of entity */
|
||||
@NonNull private final EntityType entityType;
|
||||
|
||||
/** Entity's spawn location */
|
||||
@NonNull private final Location location;
|
||||
|
||||
/** Entity's data for 1.14- servers */
|
||||
private final DataWatcher dataWatcher;
|
||||
|
||||
/**
|
||||
* Loads all required Fields and throws Exception if something went wrong
|
||||
*
|
||||
* @param nms
|
||||
* NMS storage reference
|
||||
* @throws NoSuchMethodException
|
||||
* If something fails
|
||||
*/
|
||||
public static void load(NMSStorage nms) throws NoSuchMethodException {
|
||||
if (nms.getMinorVersion() >= 19) {
|
||||
entityIds.put(EntityType.ARMOR_STAND, 2);
|
||||
} else if (nms.getMinorVersion() >= 13) {
|
||||
entityIds.put(EntityType.ARMOR_STAND, 1);
|
||||
} else {
|
||||
entityIds.put(EntityType.WITHER, 64);
|
||||
if (nms.getMinorVersion() >= 8) {
|
||||
entityIds.put(EntityType.ARMOR_STAND, 30);
|
||||
}
|
||||
}
|
||||
|
||||
if (nms.getMinorVersion() >= 17) {
|
||||
if (nms.is1_19_3Plus()) {
|
||||
CONSTRUCTOR = CLASS.getConstructor(nms.Entity);
|
||||
} else {
|
||||
CONSTRUCTOR = CLASS.getConstructor(nms.EntityLiving);
|
||||
}
|
||||
} else {
|
||||
CONSTRUCTOR = CLASS.getConstructor();
|
||||
}
|
||||
ENTITY_ID = nms.getFields(CLASS, int.class).get(0);
|
||||
YAW = nms.getFields(CLASS, byte.class).get(0);
|
||||
PITCH = nms.getFields(CLASS, byte.class).get(1);
|
||||
if (nms.getMinorVersion() >= 9) {
|
||||
UUID = nms.getFields(CLASS, UUID.class).get(0);
|
||||
if (nms.getMinorVersion() >= 19) {
|
||||
X = nms.getFields(CLASS, double.class).get(2);
|
||||
Y = nms.getFields(CLASS, double.class).get(3);
|
||||
Z = nms.getFields(CLASS, double.class).get(4);
|
||||
} else {
|
||||
X = nms.getFields(CLASS, double.class).get(0);
|
||||
Y = nms.getFields(CLASS, double.class).get(1);
|
||||
Z = nms.getFields(CLASS, double.class).get(2);
|
||||
}
|
||||
} else {
|
||||
X = nms.getFields(CLASS, int.class).get(2);
|
||||
Y = nms.getFields(CLASS, int.class).get(3);
|
||||
Z = nms.getFields(CLASS, int.class).get(4);
|
||||
}
|
||||
if (nms.getMinorVersion() < 19) {
|
||||
ENTITY_TYPE = nms.getFields(CLASS, int.class).get(1);
|
||||
}
|
||||
if (nms.getMinorVersion() <= 14) {
|
||||
DATA_WATCHER = nms.getFields(CLASS, DataWatcher.CLASS).get(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this class into NMS packet
|
||||
*
|
||||
* @return NMS packet
|
||||
* @throws ReflectiveOperationException
|
||||
* If something went wrong
|
||||
*/
|
||||
public Object build() throws ReflectiveOperationException {
|
||||
NMSStorage nms = NMSStorage.getInstance();
|
||||
Object nmsPacket;
|
||||
if (nms.getMinorVersion() >= 17) {
|
||||
nmsPacket = CONSTRUCTOR.newInstance(nms.dummyEntity);
|
||||
} else {
|
||||
nmsPacket = CONSTRUCTOR.newInstance();
|
||||
}
|
||||
ENTITY_ID.set(nmsPacket, entityId);
|
||||
YAW.set(nmsPacket, (byte)(location.getYaw() * 256.0f / 360.0f));
|
||||
PITCH.set(nmsPacket, (byte)(location.getPitch() * 256.0f / 360.0f));
|
||||
if (nms.getMinorVersion() <= 14) {
|
||||
DATA_WATCHER.set(nmsPacket, dataWatcher.build());
|
||||
}
|
||||
if (nms.getMinorVersion() >= 9) {
|
||||
UUID.set(nmsPacket, uniqueId);
|
||||
X.set(nmsPacket, location.getX());
|
||||
Y.set(nmsPacket, location.getY());
|
||||
Z.set(nmsPacket, location.getZ());
|
||||
} else {
|
||||
X.set(nmsPacket, floor(location.getX()*32));
|
||||
Y.set(nmsPacket, floor(location.getY()*32));
|
||||
Z.set(nmsPacket, floor(location.getZ()*32));
|
||||
}
|
||||
int id = entityIds.get(entityType);
|
||||
if (nms.getMinorVersion() >= 19) {
|
||||
ENTITY_TYPE.set(nmsPacket, EntityTypes_ARMOR_STAND); // :(
|
||||
} else {
|
||||
ENTITY_TYPE.set(nmsPacket, id);
|
||||
}
|
||||
return nmsPacket;
|
||||
}
|
||||
|
||||
private int floor(double paramDouble) {
|
||||
int i = (int)paramDouble;
|
||||
return paramDouble < i ? i - 1 : i;
|
||||
}
|
||||
}
|
||||
+38
-14
@@ -3,8 +3,11 @@ package me.neznamy.tab.platforms.bukkit.nms.datawatcher;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.ToString;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.NMSStorage;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.nms.NMSStorage;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -15,12 +18,38 @@ import java.util.Map;
|
||||
@ToString
|
||||
public class DataWatcher {
|
||||
|
||||
/** NMS Fields */
|
||||
public static Class<?> CLASS;
|
||||
public static Constructor<?> CONSTRUCTOR;
|
||||
public static Method REGISTER;
|
||||
public static Method markDirty;
|
||||
public static Method packDirty;
|
||||
|
||||
public static Class<?> DataValue;
|
||||
public static Field DataValue_POSITION;
|
||||
public static Field DataValue_VALUE;
|
||||
|
||||
/** Watched data */
|
||||
private final Map<Integer, DataWatcherItem> dataValues = new HashMap<>();
|
||||
|
||||
/** Helper for easier data write */
|
||||
@Getter private final DataWatcherHelper helper = new DataWatcherHelper(this);
|
||||
|
||||
/**
|
||||
* Loads all required Fields and throws Exception if something went wrong
|
||||
*
|
||||
* @param nms
|
||||
* NMS storage reference
|
||||
*/
|
||||
public static void load(NMSStorage nms) {
|
||||
CONSTRUCTOR = CLASS.getConstructors()[0];
|
||||
if (nms.is1_19_3Plus()) {
|
||||
markDirty = nms.getMethods(CLASS, void.class, DataWatcherObject.CLASS).get(0);
|
||||
DataValue_POSITION = nms.getFields(DataValue, int.class).get(0);
|
||||
DataValue_VALUE = nms.getFields(DataValue, Object.class).get(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets value into data values
|
||||
*
|
||||
@@ -29,7 +58,7 @@ public class DataWatcher {
|
||||
* @param value
|
||||
* value
|
||||
*/
|
||||
public void setValue(@NonNull DataWatcherObject type, @NonNull Object value){
|
||||
public void setValue(@NonNull DataWatcherObject type, @NonNull Object value) {
|
||||
dataValues.put(type.getPosition(), new DataWatcherItem(type, value));
|
||||
}
|
||||
|
||||
@@ -61,23 +90,18 @@ public class DataWatcher {
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public Object toNMS() throws ReflectiveOperationException {
|
||||
public Object build() throws ReflectiveOperationException {
|
||||
NMSStorage nms = NMSStorage.getInstance();
|
||||
Object nmsWatcher;
|
||||
if (nms.newDataWatcher.getParameterCount() == 1) { //1.7+
|
||||
nmsWatcher = nms.newDataWatcher.newInstance(new Object[] {null});
|
||||
if (CONSTRUCTOR.getParameterCount() == 1) { //1.7+
|
||||
nmsWatcher = CONSTRUCTOR.newInstance(new Object[] {null});
|
||||
} else {
|
||||
nmsWatcher = nms.newDataWatcher.newInstance();
|
||||
nmsWatcher = CONSTRUCTOR.newInstance();
|
||||
}
|
||||
for (DataWatcherItem item : dataValues.values()) {
|
||||
Object position;
|
||||
if (nms.getMinorVersion() >= 9) {
|
||||
position = nms.newDataWatcherObject.newInstance(item.getType().getPosition(), item.getType().getSerializer());
|
||||
} else {
|
||||
position = item.getType().getPosition();
|
||||
}
|
||||
nms.DataWatcher_REGISTER.invoke(nmsWatcher, position, item.getValue());
|
||||
if (nms.is1_19_3Plus()) nms.DataWatcher_markDirty.invoke(nmsWatcher, position);
|
||||
Object nmsObject = item.getType().build();
|
||||
REGISTER.invoke(nmsWatcher, nmsObject, item.getValue());
|
||||
if (nms.is1_19_3Plus()) markDirty.invoke(nmsWatcher, nmsObject);
|
||||
}
|
||||
return nmsWatcher;
|
||||
}
|
||||
|
||||
+23
-32
@@ -1,10 +1,10 @@
|
||||
package me.neznamy.tab.platforms.bukkit.nms.datawatcher;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
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.storage.NMSStorage;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.nms.NMSStorage;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
|
||||
import java.util.Optional;
|
||||
@@ -12,28 +12,22 @@ import java.util.Optional;
|
||||
/**
|
||||
* A class to help to assign DataWatcher items as positions often change per-version
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
public class DataWatcherHelper {
|
||||
|
||||
/** Position of armor stand flags */
|
||||
/** NMS Fields */
|
||||
public static Class<?> DataWatcherRegistry;
|
||||
public static Class<?> DataWatcherSerializer;
|
||||
public static Object DataWatcherSerializer_BYTE;
|
||||
public static Object DataWatcherSerializer_FLOAT;
|
||||
public static Object DataWatcherSerializer_STRING;
|
||||
public static Object DataWatcherSerializer_OPTIONAL_COMPONENT;
|
||||
public static Object DataWatcherSerializer_BOOLEAN;
|
||||
|
||||
/** Instance fields */
|
||||
private final int armorStandFlagsPosition = getArmorStandFlagsPosition();
|
||||
|
||||
/** DataWatcher to write to */
|
||||
private final DataWatcher data;
|
||||
|
||||
/** Data Watcher registry reference */
|
||||
private final DataWatcherRegistry registry;
|
||||
|
||||
/**
|
||||
* Constructs new instance of this class with given parent
|
||||
*
|
||||
* @param data
|
||||
* data to write to
|
||||
*/
|
||||
public DataWatcherHelper(DataWatcher data) {
|
||||
this.data = data;
|
||||
this.registry = NMSStorage.getInstance().getDataWatcherRegistry();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns armor stand flags position based on server version
|
||||
*
|
||||
@@ -53,7 +47,7 @@ public class DataWatcherHelper {
|
||||
//1.10.x - 1.13.x
|
||||
return 11;
|
||||
} else {
|
||||
//1.8.1 - 1.9.x
|
||||
//1.8.x - 1.9.x
|
||||
return 10;
|
||||
}
|
||||
}
|
||||
@@ -65,7 +59,7 @@ public class DataWatcherHelper {
|
||||
* flags to write
|
||||
*/
|
||||
public void setEntityFlags(byte flags) {
|
||||
data.setValue(new DataWatcherObject(0, registry.getTypeByte()), flags);
|
||||
data.setValue(new DataWatcherObject(0, DataWatcherSerializer_BYTE), flags);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,17 +72,14 @@ public class DataWatcherHelper {
|
||||
*/
|
||||
public void setCustomName(String customName, ProtocolVersion clientVersion) {
|
||||
if (TabAPI.getInstance().getServerVersion().getMinorVersion() >= 13) {
|
||||
try {
|
||||
data.setValue(new DataWatcherObject(2, registry.getTypeOptionalComponent()), 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 (TabAPI.getInstance().getServerVersion().getMinorVersion() >= 8){
|
||||
data.setValue(new DataWatcherObject(2, registry.getTypeString()), customName);
|
||||
data.setValue(new DataWatcherObject(2, DataWatcherSerializer_OPTIONAL_COMPONENT),
|
||||
Optional.ofNullable(NMSStorage.getInstance().toNMSComponent(IChatBaseComponent.optimizedComponent(customName), clientVersion)));
|
||||
} else if (TabAPI.getInstance().getServerVersion().getMinorVersion() >= 8) {
|
||||
data.setValue(new DataWatcherObject(2, DataWatcherSerializer_STRING), customName);
|
||||
} else {
|
||||
//name length is limited to 64 characters on <1.8
|
||||
String cutName = (customName.length() > 64 ? customName.substring(0, 64) : customName);
|
||||
if (TabAPI.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);
|
||||
@@ -104,7 +95,7 @@ public class DataWatcherHelper {
|
||||
*/
|
||||
public void setCustomNameVisible(boolean visible) {
|
||||
if (TabAPI.getInstance().getServerVersion().getMinorVersion() >= 9) {
|
||||
data.setValue(new DataWatcherObject(3, registry.getTypeBoolean()), visible);
|
||||
data.setValue(new DataWatcherObject(3, DataWatcherSerializer_BOOLEAN), visible);
|
||||
} else {
|
||||
data.setValue(new DataWatcherObject(3, null), (byte)(visible?1:0));
|
||||
}
|
||||
@@ -118,7 +109,7 @@ public class DataWatcherHelper {
|
||||
*/
|
||||
public void setHealth(float health) {
|
||||
if (TabAPI.getInstance().getServerVersion().getMinorVersion() >= 6) {
|
||||
data.setValue(new DataWatcherObject(6, registry.getTypeFloat()), health);
|
||||
data.setValue(new DataWatcherObject(6, DataWatcherSerializer_FLOAT), health);
|
||||
} else {
|
||||
data.setValue(new DataWatcherObject(16, null), (int)health);
|
||||
}
|
||||
@@ -131,7 +122,7 @@ public class DataWatcherHelper {
|
||||
* flags to write
|
||||
*/
|
||||
public void setArmorStandFlags(byte flags) {
|
||||
data.setValue(new DataWatcherObject(armorStandFlagsPosition, registry.getTypeByte()), flags);
|
||||
data.setValue(new DataWatcherObject(armorStandFlagsPosition, DataWatcherSerializer_BYTE), flags);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+29
-9
@@ -2,20 +2,40 @@ package me.neznamy.tab.platforms.bukkit.nms.datawatcher;
|
||||
|
||||
import lombok.Data;
|
||||
import me.neznamy.tab.api.TabAPI;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.NMSStorage;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.nms.NMSStorage;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* Class representing NMS Data Watcher Item
|
||||
*/
|
||||
@Data
|
||||
public class DataWatcherItem {
|
||||
|
||||
/** Value type */
|
||||
|
||||
/** NMS Fields */
|
||||
public static Class<?> CLASS;
|
||||
public static Field TYPE;
|
||||
public static Field VALUE;
|
||||
|
||||
/** Instance fields */
|
||||
private final DataWatcherObject type;
|
||||
|
||||
/** Data value */
|
||||
private final Object value;
|
||||
|
||||
/**
|
||||
* Loads all required Fields
|
||||
*
|
||||
* @param nms
|
||||
* NMS storage reference
|
||||
*/
|
||||
public static void load(NMSStorage nms) {
|
||||
VALUE = nms.getFields(CLASS, Object.class).get(0);
|
||||
if (nms.getMinorVersion() >= 9) {
|
||||
TYPE = nms.getFields(CLASS, DataWatcherObject.CLASS).get(0);
|
||||
} else {
|
||||
TYPE = nms.getFields(CLASS, int.class).get(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns and instance of this class from given NMS item
|
||||
*
|
||||
@@ -27,13 +47,13 @@ public class DataWatcherItem {
|
||||
*/
|
||||
public static DataWatcherItem fromNMS(Object nmsItem) throws ReflectiveOperationException {
|
||||
NMSStorage nms = NMSStorage.getInstance();
|
||||
Object value = nms.DataWatcherItem_VALUE.get(nmsItem);
|
||||
Object value = VALUE.get(nmsItem);
|
||||
DataWatcherObject object;
|
||||
if (TabAPI.getInstance().getServerVersion().getMinorVersion() >= 9) {
|
||||
Object nmsObject = nms.DataWatcherItem_TYPE.get(nmsItem);
|
||||
object = new DataWatcherObject(nms.DataWatcherObject_SLOT.getInt(nmsObject), nms.DataWatcherObject_SERIALIZER.get(nmsObject));
|
||||
Object nmsObject = TYPE.get(nmsItem);
|
||||
object = new DataWatcherObject(DataWatcherObject.SLOT.getInt(nmsObject), DataWatcherObject.SERIALIZER.get(nmsObject));
|
||||
} else {
|
||||
object = new DataWatcherObject(nms.DataWatcherItem_TYPE.getInt(nmsItem), null);
|
||||
object = new DataWatcherObject(TYPE.getInt(nmsItem), null);
|
||||
}
|
||||
return new DataWatcherItem(object, value);
|
||||
}
|
||||
|
||||
+41
-3
@@ -2,6 +2,10 @@ package me.neznamy.tab.platforms.bukkit.nms.datawatcher;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.nms.NMSStorage;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* A class representing the n.m.s.DataWatcherObject class to make work with it much easier
|
||||
@@ -9,9 +13,43 @@ import lombok.Data;
|
||||
@Data @AllArgsConstructor
|
||||
public class DataWatcherObject {
|
||||
|
||||
/** Object's position in DataWatcher */
|
||||
private final int position;
|
||||
/** NMS Fields */
|
||||
public static Class<?> CLASS;
|
||||
public static Constructor<?> CONSTRUCTOR;
|
||||
public static Field SLOT;
|
||||
public static Field SERIALIZER;
|
||||
|
||||
/** Value encoder for 1.9+ */
|
||||
/** Instance fields */
|
||||
private final int position;
|
||||
private final Object serializer;
|
||||
|
||||
/**
|
||||
* Loads all required Fields and throws Exception if something went wrong
|
||||
*
|
||||
* @param nms
|
||||
* NMS storage reference
|
||||
* @throws NoSuchMethodException
|
||||
* If something fails
|
||||
*/
|
||||
public static void load(NMSStorage nms) throws NoSuchMethodException {
|
||||
if (nms.getMinorVersion() < 9) return;
|
||||
CONSTRUCTOR = CLASS.getConstructor(int.class, DataWatcherHelper.DataWatcherSerializer);
|
||||
SLOT = nms.getFields(CLASS, int.class).get(0);
|
||||
SERIALIZER = nms.getFields(CLASS, DataWatcherHelper.DataWatcherSerializer).get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the object into NMS object
|
||||
*
|
||||
* @return NMS object
|
||||
* @throws ReflectiveOperationException
|
||||
* If thrown by reflective operation
|
||||
*/
|
||||
public Object build() throws ReflectiveOperationException {
|
||||
if (NMSStorage.getInstance().getMinorVersion() >= 9) {
|
||||
return DataWatcherObject.CONSTRUCTOR.newInstance(position, serializer);
|
||||
} else {
|
||||
return position;
|
||||
}
|
||||
}
|
||||
}
|
||||
-60
@@ -1,60 +0,0 @@
|
||||
package me.neznamy.tab.platforms.bukkit.nms.datawatcher;
|
||||
|
||||
import lombok.Getter;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.NMSStorage;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A class representing the n.m.s.DataWatcherRegistry class to make work with it much easier
|
||||
*/
|
||||
public class DataWatcherRegistry {
|
||||
|
||||
/** Byte encoder */
|
||||
@Getter private Object typeByte;
|
||||
|
||||
/** Float encoder */
|
||||
@Getter private Object typeFloat;
|
||||
|
||||
/** String encoder */
|
||||
@Getter private Object typeString;
|
||||
|
||||
/** Encoder for optional component */
|
||||
@Getter private Object typeOptionalComponent;
|
||||
|
||||
/** Boolean encoder */
|
||||
@Getter private Object typeBoolean;
|
||||
|
||||
/**
|
||||
* Initializes required NMS classes and fields
|
||||
*/
|
||||
public DataWatcherRegistry(NMSStorage nms) {
|
||||
if (nms.getMinorVersion() >= 9) {
|
||||
Map<String, Object> fields = nms.getStaticFields(nms.DataWatcherRegistry);
|
||||
if (fields.containsKey("a")) {
|
||||
// Bukkit mapping
|
||||
typeByte = fields.get("a");
|
||||
typeFloat = fields.get("c");
|
||||
typeString = fields.get("d");
|
||||
if (nms.getMinorVersion() >= 13) {
|
||||
if (nms.is1_19_3Plus()) {
|
||||
typeOptionalComponent = fields.get("g");
|
||||
typeBoolean = fields.get("j");
|
||||
} else {
|
||||
typeOptionalComponent = fields.get("f");
|
||||
typeBoolean = fields.get("i");
|
||||
}
|
||||
} else {
|
||||
typeBoolean = fields.get("h");
|
||||
}
|
||||
} else {
|
||||
// Mojang mapping
|
||||
typeByte = fields.get("BYTE");
|
||||
typeFloat = fields.get("FLOAT");
|
||||
typeString = fields.get("STRING");
|
||||
typeOptionalComponent = fields.get("OPTIONAL_COMPONENT");
|
||||
typeBoolean = fields.get("BOOLEAN");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-152
@@ -1,152 +0,0 @@
|
||||
package me.neznamy.tab.platforms.bukkit.nms.storage;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* NMS loader for Minecraft 1.5.2 - 1.16.5 using Bukkit mapping.
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public class BukkitLegacyNMSStorage extends NMSStorage {
|
||||
|
||||
/**
|
||||
* Creates new instance, initializes required NMS classes and fields
|
||||
*
|
||||
* @throws ReflectiveOperationException
|
||||
* If any class, field or method fails to load
|
||||
*/
|
||||
public BukkitLegacyNMSStorage() 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
|
||||
*/
|
||||
public Class<?> getLegacyClass(String name) throws ClassNotFoundException {
|
||||
return Class.forName("net.minecraft.server." + serverPackage + "." + name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadNamedFieldsAndMethods() throws ReflectiveOperationException {
|
||||
PING = getField(EntityPlayer, "ping");
|
||||
ScoreboardScore_setScore = getMethod(ScoreboardScore, new String[] {"setScore", "c"}, int.class); // 1.5.1+, 1.5
|
||||
ScoreboardTeam_setAllowFriendlyFire = getMethod(ScoreboardTeam, new String[] {"setAllowFriendlyFire", "a"}, boolean.class); // 1.5.1+, 1.5
|
||||
ScoreboardTeam_setCanSeeFriendlyInvisibles = getMethod(ScoreboardTeam, new String[] {"setCanSeeFriendlyInvisibles", "b"}, boolean.class); // 1.5.1+, 1.5
|
||||
if (minorVersion >= 7) {
|
||||
ChatSerializer_DESERIALIZE = ChatSerializer.getMethod("a", String.class);
|
||||
}
|
||||
if (minorVersion >= 8) {
|
||||
ScoreboardTeam_setNameTagVisibility = getMethod(ScoreboardTeam, new String[] {"setNameTagVisibility", "a"}, EnumNameTagVisibility); // {1.8.1+, 1.8}
|
||||
}
|
||||
if (minorVersion >= 9) {
|
||||
DataWatcher_REGISTER = DataWatcher.getMethod("register", DataWatcherObject, Object.class);
|
||||
} else {
|
||||
DataWatcher_REGISTER = DataWatcher.getMethod("a", int.class, Object.class);
|
||||
}
|
||||
if (minorVersion >= 13) {
|
||||
ScoreboardTeam_setPrefix = ScoreboardTeam.getMethod("setPrefix", IChatBaseComponent);
|
||||
ScoreboardTeam_setSuffix = ScoreboardTeam.getMethod("setSuffix", IChatBaseComponent);
|
||||
} else {
|
||||
ScoreboardTeam_setPrefix = getMethod(ScoreboardTeam, new String[] {"setPrefix", "b"}, String.class); // 1.5.1+, 1.5
|
||||
ScoreboardTeam_setSuffix = getMethod(ScoreboardTeam, new String[] {"setSuffix", "c"}, String.class); // 1.5.1+, 1.5
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadClasses() throws ClassNotFoundException {
|
||||
EntityHuman = getLegacyClass("EntityHuman");
|
||||
World = getLegacyClass("World");
|
||||
Packet = getLegacyClass("Packet");
|
||||
EnumChatFormat = (Class<Enum>) 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 = (Class<Enum>) 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 = (Class<Enum>) getLegacyClass("PacketPlayInUseEntity$EnumEntityUseAction", "EnumEntityUseAction");
|
||||
}
|
||||
|
||||
// Player Info
|
||||
if (minorVersion >= 8) {
|
||||
PacketPlayOutPlayerInfo = getLegacyClass("PacketPlayOutPlayerInfo");
|
||||
EnumPlayerInfoAction = (Class<Enum>) getLegacyClass("PacketPlayOutPlayerInfo$EnumPlayerInfoAction", "EnumPlayerInfoAction");
|
||||
PlayerInfoData = getLegacyClass("PacketPlayOutPlayerInfo$PlayerInfoData", "PlayerInfoData");
|
||||
EnumGamemode = (Class<Enum>) 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", "IObjective"); // 1.5.1+, 1.5
|
||||
ScoreboardTeam = getLegacyClass("ScoreboardTeam");
|
||||
if (minorVersion >= 8) {
|
||||
EnumScoreboardHealthDisplay = (Class<Enum>) getLegacyClass("IScoreboardCriteria$EnumScoreboardHealthDisplay", "EnumScoreboardHealthDisplay");
|
||||
EnumScoreboardAction = (Class<Enum>) getLegacyClass("ScoreboardServer$Action", "PacketPlayOutScoreboardScore$EnumScoreboardAction", "EnumScoreboardAction");
|
||||
EnumNameTagVisibility = (Class<Enum>) getLegacyClass("ScoreboardTeamBase$EnumNameTagVisibility", "EnumNameTagVisibility");
|
||||
}
|
||||
if (minorVersion >= 9) {
|
||||
EnumTeamPush = (Class<Enum>) getLegacyClass("ScoreboardTeamBase$EnumTeamPush");
|
||||
}
|
||||
}
|
||||
}
|
||||
-124
@@ -1,124 +0,0 @@
|
||||
package me.neznamy.tab.platforms.bukkit.nms.storage;
|
||||
|
||||
/**
|
||||
* NMS loader for minecraft 1.17+ using Mojang packaging and bukkit names.
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public class BukkitModernNMSStorage extends NMSStorage {
|
||||
|
||||
/**
|
||||
* 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 = ChatSerializer.getMethod("a", String.class);
|
||||
DataWatcher_REGISTER = getMethod(DataWatcher, new String[]{"register", "a"}, DataWatcherObject, Object.class); // {Bukkit, Bukkit 1.18+}
|
||||
ScoreboardScore_setScore = getMethod(ScoreboardScore, new String[]{"setScore", "b"}, int.class); // {Bukkit, Bukkit 1.18+}
|
||||
ScoreboardTeam_setAllowFriendlyFire = getMethod(ScoreboardTeam, new String[]{"setAllowFriendlyFire", "a"}, boolean.class); // {Bukkit, Bukkit 1.18+}
|
||||
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) {
|
||||
EntityTypes_ARMOR_STAND = EntityTypes.getDeclaredField("d").get(null);
|
||||
PacketPlayOutSpawnEntityLiving_ENTITYTYPE = getField(PacketPlayOutSpawnEntityLiving, "e");
|
||||
DataWatcher_b = DataWatcher.getMethod("b");
|
||||
}
|
||||
}
|
||||
|
||||
@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<Enum>) 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");
|
||||
if (minorVersion >= 19) {
|
||||
PacketPlayOutChat = Class.forName("net.minecraft.network.protocol.game.ClientboundSystemChatPacket");
|
||||
} else {
|
||||
PacketPlayOutChat = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutChat");
|
||||
ChatMessageType = (Class<Enum>) Class.forName("net.minecraft.network.chat.ChatMessageType");
|
||||
}
|
||||
|
||||
// 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");
|
||||
if (is1_19_3Plus()) {
|
||||
DataWatcher$DataValue = Class.forName("net.minecraft.network.syncher.DataWatcher$b");
|
||||
}
|
||||
|
||||
// Entities
|
||||
if (minorVersion >= 19) {
|
||||
PacketPlayOutSpawnEntityLiving = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutSpawnEntity");
|
||||
} else {
|
||||
PacketPlayOutSpawnEntityLiving = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutSpawnEntityLiving");
|
||||
}
|
||||
PacketPlayOutEntityTeleport = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutEntityTeleport");
|
||||
PacketPlayInUseEntity = Class.forName("net.minecraft.network.protocol.game.PacketPlayInUseEntity");
|
||||
PacketPlayInUseEntity$d = Class.forName("net.minecraft.network.protocol.game.PacketPlayInUseEntity$d");
|
||||
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<Enum>) Class.forName("net.minecraft.network.protocol.game.PacketPlayInUseEntity$EnumEntityUseAction");
|
||||
if (minorVersion >= 19) {
|
||||
EntityTypes = Class.forName("net.minecraft.world.entity.EntityTypes");
|
||||
}
|
||||
|
||||
// Player Info
|
||||
if (minorVersion >= 19) {
|
||||
ProfilePublicKey = Class.forName("net.minecraft.world.entity.player.ProfilePublicKey");
|
||||
ProfilePublicKey$a = Class.forName("net.minecraft.world.entity.player.ProfilePublicKey$a");
|
||||
}
|
||||
if (is1_19_3Plus()) {
|
||||
//1.19.3+
|
||||
ClientboundPlayerInfoRemovePacket = Class.forName("net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket");
|
||||
PacketPlayOutPlayerInfo = Class.forName("net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket");
|
||||
EnumPlayerInfoAction = (Class<Enum>) Class.forName("net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket$a");
|
||||
PlayerInfoData = Class.forName("net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket$b");
|
||||
RemoteChatSession = Class.forName("net.minecraft.network.chat.RemoteChatSession");
|
||||
RemoteChatSession$Data = Class.forName("net.minecraft.network.chat.RemoteChatSession$a");
|
||||
} else {
|
||||
PacketPlayOutPlayerInfo = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo");
|
||||
EnumPlayerInfoAction = (Class<Enum>) Class.forName("net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo$EnumPlayerInfoAction");
|
||||
PlayerInfoData = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo$PlayerInfoData");
|
||||
}
|
||||
EnumGamemode = (Class<Enum>) 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<Enum>) Class.forName("net.minecraft.world.scores.criteria.IScoreboardCriteria$EnumScoreboardHealthDisplay");
|
||||
EnumScoreboardAction = (Class<Enum>) 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<Enum>) Class.forName("net.minecraft.world.scores.ScoreboardTeamBase$EnumNameTagVisibility");
|
||||
EnumTeamPush = (Class<Enum>) Class.forName("net.minecraft.world.scores.ScoreboardTeamBase$EnumTeamPush");
|
||||
PacketPlayOutScoreboardTeam_PlayerAction = (Class<Enum>) Class.forName("net.minecraft.network.protocol.game.PacketPlayOutScoreboardTeam$a");
|
||||
}
|
||||
}
|
||||
-122
@@ -1,122 +0,0 @@
|
||||
package me.neznamy.tab.platforms.bukkit.nms.storage;
|
||||
|
||||
/**
|
||||
* NMS loader for minecraft 1.17+ using Mojang packaging and names.
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public class MojangModernNMSStorage extends NMSStorage {
|
||||
|
||||
/**
|
||||
* 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 = ChatSerializer.getMethod("fromJson", String.class);
|
||||
DataWatcher_REGISTER = DataWatcher.getMethod("define", DataWatcherObject, Object.class);
|
||||
ScoreboardScore_setScore = ScoreboardScore.getMethod("setScore", int.class);
|
||||
ScoreboardTeam_setAllowFriendlyFire = ScoreboardTeam.getMethod("setAllowFriendlyFire", boolean.class);
|
||||
ScoreboardTeam_setCanSeeFriendlyInvisibles = ScoreboardTeam.getMethod("setSeeFriendlyInvisibles", boolean.class);
|
||||
ScoreboardTeam_setPrefix = ScoreboardTeam.getMethod("setPlayerPrefix", IChatBaseComponent);
|
||||
ScoreboardTeam_setSuffix = ScoreboardTeam.getMethod("setPlayerSuffix", IChatBaseComponent);
|
||||
ScoreboardTeam_setNameTagVisibility = ScoreboardTeam.getMethod("setNameTagVisibility", EnumNameTagVisibility);
|
||||
if (minorVersion >= 19) {
|
||||
EntityTypes_ARMOR_STAND = EntityTypes.getDeclaredField("ARMOR_STAND").get(null);
|
||||
PacketPlayOutSpawnEntityLiving_ENTITYTYPE = getField(PacketPlayOutSpawnEntityLiving, "type");
|
||||
DataWatcher_b = DataWatcher.getMethod("packDirty");
|
||||
}
|
||||
}
|
||||
|
||||
@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<Enum>) 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");
|
||||
if (minorVersion >= 19) {
|
||||
PacketPlayOutChat = Class.forName("net.minecraft.network.protocol.game.ClientboundSystemChatPacket");
|
||||
} else {
|
||||
PacketPlayOutChat = Class.forName("net.minecraft.network.protocol.game.ClientboundChatPacket");
|
||||
ChatMessageType = (Class<Enum>) Class.forName("net.minecraft.network.chat.ChatType");
|
||||
}
|
||||
|
||||
// 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");
|
||||
if (is1_19_3Plus()) {
|
||||
DataWatcher$DataValue = Class.forName("net.minecraft.network.syncher.SynchedEntityData$DataValue");
|
||||
}
|
||||
|
||||
// Entities
|
||||
if (minorVersion >= 19) {
|
||||
PacketPlayOutSpawnEntityLiving = Class.forName("net.minecraft.network.protocol.game.ClientboundAddEntityPacket");
|
||||
} else {
|
||||
PacketPlayOutSpawnEntityLiving = Class.forName("net.minecraft.network.protocol.game.ClientboundAddMobPacket");
|
||||
}
|
||||
PacketPlayOutEntityTeleport = Class.forName("net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket");
|
||||
PacketPlayInUseEntity = Class.forName("net.minecraft.network.protocol.game.ServerboundInteractPacket");
|
||||
PacketPlayInUseEntity$d = Class.forName("net.minecraft.network.protocol.game.ServerboundInteractPacket$InteractionAction");
|
||||
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<Enum>) Class.forName("net.minecraft.network.protocol.game.ServerboundInteractPacket$Action");
|
||||
if (minorVersion >= 19) {
|
||||
EntityTypes = Class.forName("net.minecraft.world.entity.EntityType");
|
||||
}
|
||||
|
||||
// Player Info
|
||||
if (minorVersion >= 19) {
|
||||
ProfilePublicKey = Class.forName("net.minecraft.world.entity.player.ProfilePublicKey");
|
||||
ProfilePublicKey$a = Class.forName("net.minecraft.world.entity.player.ProfilePublicKey$Data");
|
||||
}
|
||||
if (is1_19_3Plus()) {
|
||||
ClientboundPlayerInfoRemovePacket = Class.forName("net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket");
|
||||
PacketPlayOutPlayerInfo = Class.forName("net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket");
|
||||
EnumPlayerInfoAction = (Class<Enum>) Class.forName("net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket$Action");
|
||||
PlayerInfoData = Class.forName("net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket$Entry");
|
||||
RemoteChatSession = Class.forName("net.minecraft.network.chat.RemoteChatSession");
|
||||
RemoteChatSession$Data = Class.forName("net.minecraft.network.chat.RemoteChatSession$Data");
|
||||
} else {
|
||||
PacketPlayOutPlayerInfo = Class.forName("net.minecraft.network.protocol.game.ClientboundPlayerInfoPacket");
|
||||
EnumPlayerInfoAction = (Class<Enum>) Class.forName("net.minecraft.network.protocol.game.ClientboundPlayerInfoPacket$Action");
|
||||
PlayerInfoData = Class.forName("net.minecraft.network.protocol.game.ClientboundPlayerInfoPacket$PlayerUpdate");
|
||||
}
|
||||
EnumGamemode = (Class<Enum>) 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<Enum>) Class.forName("net.minecraft.world.scores.criteria.ObjectiveCriteria$RenderType");
|
||||
EnumScoreboardAction = (Class<Enum>) 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<Enum>) Class.forName("net.minecraft.world.scores.Team$Visibility");
|
||||
EnumTeamPush = (Class<Enum>) Class.forName("net.minecraft.world.scores.Team$CollisionRule");
|
||||
PacketPlayOutScoreboardTeam_PlayerAction = (Class<Enum>) Class.forName("net.minecraft.network.protocol.game.ClientboundSetPlayerTeamPacket$Action");
|
||||
}
|
||||
}
|
||||
@@ -1,707 +0,0 @@
|
||||
package me.neznamy.tab.platforms.bukkit.nms.storage;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import me.neznamy.tab.api.ProtocolVersion;
|
||||
import me.neznamy.tab.api.util.ReflectionUtils;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcherRegistry;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Class holding all NMS classes, methods, fields and constructors used by TAB.
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public abstract class NMSStorage {
|
||||
|
||||
/** Instance of this class */
|
||||
@Getter @Setter private static NMSStorage instance;
|
||||
|
||||
/** Server's NMS/CraftBukkit package */
|
||||
protected final String serverPackage = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
|
||||
|
||||
/** Server's minor version */
|
||||
@Getter protected final int minorVersion = Integer.parseInt(serverPackage.split("_")[1]);
|
||||
|
||||
/** Flag determining whether the server version is at least 1.19.3 or not */
|
||||
@Getter private final boolean is1_19_3Plus = ReflectionUtils.classExists("net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket");
|
||||
|
||||
/** Basic universal values */
|
||||
protected Class<?> Packet;
|
||||
protected Class<?> NetworkManager;
|
||||
protected Class<?> EntityArmorStand;
|
||||
protected Class<?> World;
|
||||
public Class<Enum> 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 Method getHandle;
|
||||
public Method sendPacket;
|
||||
public Method getProfile;
|
||||
|
||||
/** Chat components */
|
||||
protected Class<?> IChatBaseComponent;
|
||||
protected Class<?> ChatSerializer;
|
||||
public Method ChatSerializer_DESERIALIZE;
|
||||
|
||||
/** PacketPlayOutChat */
|
||||
protected Class<?> PacketPlayOutChat;
|
||||
public Class<Enum> ChatMessageType;
|
||||
public Constructor<?> newPacketPlayOutChat;
|
||||
|
||||
/** DataWatcher */
|
||||
protected Class<?> DataWatcher;
|
||||
protected Class<?> DataWatcherItem;
|
||||
protected Class<?> DataWatcherObject;
|
||||
protected Class<?> DataWatcherSerializer;
|
||||
public Class<?> DataWatcherRegistry;
|
||||
public Constructor<?> newDataWatcher;
|
||||
public Constructor<?> newDataWatcherObject;
|
||||
public Field DataWatcherItem_TYPE;
|
||||
public Field DataWatcherItem_VALUE;
|
||||
public Field DataWatcherObject_SLOT;
|
||||
public Field DataWatcherObject_SERIALIZER;
|
||||
public Method DataWatcher_REGISTER;
|
||||
@Getter private final DataWatcherRegistry dataWatcherRegistry;
|
||||
//1.19.3+
|
||||
protected Class<?> DataWatcher$DataValue;
|
||||
public Field DataWatcher$DataValue_POSITION;
|
||||
public Field DataWatcher$DataValue_VALUE;
|
||||
public Method DataWatcher_markDirty;
|
||||
public Method DataWatcher_b;
|
||||
|
||||
/** PacketPlayOutSpawnEntityLiving */
|
||||
public Class<?> PacketPlayOutSpawnEntityLiving;
|
||||
public Class<?> EntityTypes;
|
||||
public Constructor<?> newPacketPlayOutSpawnEntityLiving;
|
||||
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 Object EntityTypes_ARMOR_STAND;
|
||||
|
||||
/** PacketPlayOutEntityTeleport */
|
||||
public Class<?> PacketPlayOutEntityTeleport;
|
||||
public Constructor<?> newPacketPlayOutEntityTeleport;
|
||||
public Field PacketPlayOutEntityTeleport_ENTITYID;
|
||||
public Field PacketPlayOutEntityTeleport_X;
|
||||
public Field PacketPlayOutEntityTeleport_Y;
|
||||
public Field PacketPlayOutEntityTeleport_Z;
|
||||
public Field PacketPlayOutEntityTeleport_YAW;
|
||||
public Field PacketPlayOutEntityTeleport_PITCH;
|
||||
|
||||
/** PacketPlayOutPlayerListHeaderFooter */
|
||||
protected Class<?> PacketPlayOutPlayerListHeaderFooter;
|
||||
public Constructor<?> newPacketPlayOutPlayerListHeaderFooter;
|
||||
public Field PacketPlayOutPlayerListHeaderFooter_HEADER;
|
||||
public Field PacketPlayOutPlayerListHeaderFooter_FOOTER;
|
||||
|
||||
/** Other entity packets */
|
||||
public Class<?> PacketPlayInUseEntity;
|
||||
public Class<?> PacketPlayInUseEntity$d;
|
||||
protected Class<Enum> EnumEntityUseAction;
|
||||
public Field PacketPlayInUseEntity_ENTITY;
|
||||
public Field PacketPlayInUseEntity_ACTION;
|
||||
|
||||
public Class<?> PacketPlayOutEntity;
|
||||
public Field PacketPlayOutEntity_ENTITYID;
|
||||
|
||||
public Class<?> PacketPlayOutEntityDestroy;
|
||||
public Constructor<?> newPacketPlayOutEntityDestroy;
|
||||
public Field PacketPlayOutEntityDestroy_ENTITIES;
|
||||
|
||||
public Class<?> PacketPlayOutEntityLook;
|
||||
|
||||
public Class<?> PacketPlayOutEntityMetadata;
|
||||
public Constructor<?> newPacketPlayOutEntityMetadata;
|
||||
public Field PacketPlayOutEntityMetadata_LIST;
|
||||
|
||||
public Class<?> PacketPlayOutNamedEntitySpawn;
|
||||
public Field PacketPlayOutNamedEntitySpawn_ENTITYID;
|
||||
|
||||
/** PacketPlayOutPlayerInfo */
|
||||
public Class<?> PacketPlayOutPlayerInfo;
|
||||
public Class<Enum> EnumPlayerInfoAction;
|
||||
protected Class<?> PlayerInfoData;
|
||||
public Class<Enum> EnumGamemode;
|
||||
protected Class<?> ProfilePublicKey;
|
||||
protected Class<?> ProfilePublicKey$a;
|
||||
public Constructor<?> newPacketPlayOutPlayerInfo;
|
||||
public Constructor<?> newPlayerInfoData;
|
||||
public Field PacketPlayOutPlayerInfo_ACTION;
|
||||
public Field PacketPlayOutPlayerInfo_PLAYERS;
|
||||
public Method PlayerInfoData_getProfile;
|
||||
public Method PlayerInfoData_isListed;
|
||||
public Method PlayerInfoData_getLatency;
|
||||
public Method PlayerInfoData_getGamemode;
|
||||
public Method PlayerInfoData_getDisplayName;
|
||||
public Method PlayerInfoData_getProfilePublicKeyRecord;
|
||||
//1.19.3+
|
||||
public Class<?> ClientboundPlayerInfoRemovePacket;
|
||||
public Class<?> RemoteChatSession;
|
||||
public Class<?> RemoteChatSession$Data;
|
||||
public Constructor<?> newClientboundPlayerInfoRemovePacket;
|
||||
public Constructor<?> newRemoteChatSession$Data;
|
||||
public Method ClientboundPlayerInfoRemovePacket_getEntries;
|
||||
public Method RemoteChatSession$Data_getSessionId;
|
||||
public Method RemoteChatSession$Data_getProfilePublicKey;
|
||||
|
||||
|
||||
/** Scoreboard objectives */
|
||||
public Class<?> PacketPlayOutScoreboardDisplayObjective;
|
||||
public Class<?> PacketPlayOutScoreboardObjective;
|
||||
protected Class<?> Scoreboard;
|
||||
protected Class<?> PacketPlayOutScoreboardScore;
|
||||
protected Class<?> ScoreboardObjective;
|
||||
protected Class<?> ScoreboardScore;
|
||||
protected Class<?> IScoreboardCriteria;
|
||||
public Class<Enum> EnumScoreboardHealthDisplay;
|
||||
public Class<Enum> 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 Field PacketPlayOutScoreboardDisplayObjective_POSITION;
|
||||
public Field PacketPlayOutScoreboardDisplayObjective_OBJECTIVENAME;
|
||||
public Field PacketPlayOutScoreboardObjective_OBJECTIVENAME;
|
||||
public Field PacketPlayOutScoreboardObjective_METHOD;
|
||||
public Field IScoreboardCriteria_self;
|
||||
public Field PacketPlayOutScoreboardObjective_RENDERTYPE;
|
||||
public Field PacketPlayOutScoreboardObjective_DISPLAYNAME;
|
||||
public Method ScoreboardScore_setScore;
|
||||
|
||||
/** PacketPlayOutScoreboardTeam */
|
||||
public Class<?> PacketPlayOutScoreboardTeam;
|
||||
protected Class<?> ScoreboardTeam;
|
||||
public Class<Enum> EnumNameTagVisibility;
|
||||
public Class<Enum> EnumTeamPush;
|
||||
public Class<Enum> PacketPlayOutScoreboardTeam_PlayerAction;
|
||||
public Constructor<?> newScoreboardTeam;
|
||||
public Constructor<?> newPacketPlayOutScoreboardTeam;
|
||||
public Field PacketPlayOutScoreboardTeam_NAME;
|
||||
public Field PacketPlayOutScoreboardTeam_ACTION;
|
||||
public Field PacketPlayOutScoreboardTeam_PLAYERS;
|
||||
public Method ScoreboardTeam_getPlayerNameSet;
|
||||
public Method ScoreboardTeam_setNameTagVisibility;
|
||||
public Method ScoreboardTeam_setCollisionRule;
|
||||
public Method ScoreboardTeam_setPrefix;
|
||||
public Method ScoreboardTeam_setSuffix;
|
||||
public Method ScoreboardTeam_setColor;
|
||||
public Method ScoreboardTeam_setAllowFriendlyFire;
|
||||
public Method ScoreboardTeam_setCanSeeFriendlyInvisibles;
|
||||
public Method PacketPlayOutScoreboardTeam_of;
|
||||
public Method PacketPlayOutScoreboardTeam_ofBoolean;
|
||||
public Method PacketPlayOutScoreboardTeam_ofString;
|
||||
|
||||
/** Other */
|
||||
public Object emptyScoreboard;
|
||||
public Object dummyEntity;
|
||||
|
||||
/**
|
||||
* Constructs new instance and attempts to load all fields, methods and constructors.
|
||||
*
|
||||
* @throws ReflectiveOperationException
|
||||
* If some field, constructor or method was not found
|
||||
*/
|
||||
public NMSStorage() throws ReflectiveOperationException {
|
||||
ProtocolVersion.UNKNOWN_SERVER_VERSION.setMinorVersion(minorVersion); //fixing compatibility with forks that set version field value to "Unknown"
|
||||
loadClasses();
|
||||
if (minorVersion >= 7) {
|
||||
NETWORK_MANAGER = getFields(PlayerConnection, NetworkManager).get(0);
|
||||
}
|
||||
if (minorVersion >= 8) {
|
||||
CHANNEL = getFields(NetworkManager, Channel.class).get(0);
|
||||
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);
|
||||
}
|
||||
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);
|
||||
dataWatcherRegistry = new DataWatcherRegistry(this);
|
||||
dataWatcher();
|
||||
entityTeleport();
|
||||
spawnEntityLiving();
|
||||
chat();
|
||||
playerListHeaderFooter();
|
||||
playerInfo();
|
||||
otherEntity();
|
||||
scoreboard();
|
||||
scoreboardTeam();
|
||||
loadNamedFieldsAndMethods();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads PacketPlayOutChat's methods, fields and constructors
|
||||
*
|
||||
* @throws ReflectiveOperationException
|
||||
* If some method, field or constructor was not found
|
||||
*/
|
||||
protected void chat() throws ReflectiveOperationException {
|
||||
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);
|
||||
} else if (minorVersion >= 8) {
|
||||
newPacketPlayOutChat = PacketPlayOutChat.getConstructor(IChatBaseComponent, byte.class);
|
||||
} else if (minorVersion >= 7){
|
||||
newPacketPlayOutChat = PacketPlayOutChat.getConstructor(IChatBaseComponent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads PacketPlayOutPlayerInfo's methods, fields and constructors
|
||||
*
|
||||
* @throws ReflectiveOperationException
|
||||
* If some method, field or constructor was not found
|
||||
*/
|
||||
protected void playerInfo() throws ReflectiveOperationException {
|
||||
if (minorVersion < 8) return;
|
||||
if (is1_19_3Plus()) {
|
||||
newClientboundPlayerInfoRemovePacket = ClientboundPlayerInfoRemovePacket.getConstructor(List.class);
|
||||
newPacketPlayOutPlayerInfo = PacketPlayOutPlayerInfo.getConstructor(EnumSet.class, Collection.class);
|
||||
ClientboundPlayerInfoRemovePacket_getEntries = getMethods(ClientboundPlayerInfoRemovePacket, List.class).get(0);
|
||||
PacketPlayOutPlayerInfo_ACTION = getFields(PacketPlayOutPlayerInfo, EnumSet.class).get(0);
|
||||
newRemoteChatSession$Data = RemoteChatSession$Data.getConstructor(UUID.class, ProfilePublicKey$a);
|
||||
RemoteChatSession$Data_getSessionId = getMethods(RemoteChatSession$Data, UUID.class).get(0);
|
||||
RemoteChatSession$Data_getProfilePublicKey = getMethods(RemoteChatSession$Data, ProfilePublicKey$a).get(0);
|
||||
PlayerInfoData_getProfilePublicKeyRecord = getMethods(PlayerInfoData, RemoteChatSession$Data).get(0);
|
||||
PlayerInfoData_isListed = getMethods(PlayerInfoData, boolean.class).get(0);
|
||||
} else {
|
||||
newPacketPlayOutPlayerInfo = PacketPlayOutPlayerInfo.getConstructor(EnumPlayerInfoAction, Array.newInstance(EntityPlayer, 0).getClass());
|
||||
PacketPlayOutPlayerInfo_ACTION = getFields(PacketPlayOutPlayerInfo, EnumPlayerInfoAction).get(0);
|
||||
if (minorVersion >= 19) {
|
||||
PlayerInfoData_getProfilePublicKeyRecord = getMethods(PlayerInfoData, ProfilePublicKey$a).get(0);
|
||||
}
|
||||
}
|
||||
newPlayerInfoData = PlayerInfoData.getConstructors()[0];
|
||||
PacketPlayOutPlayerInfo_PLAYERS = getFields(PacketPlayOutPlayerInfo, List.class).get(0);
|
||||
PlayerInfoData_getProfile = getMethods(PlayerInfoData, GameProfile.class).get(0);
|
||||
for (Method m: getMethods(PlayerInfoData, int.class)) {
|
||||
// do not take .hashCode(), which is final
|
||||
if (!Modifier.isFinal(m.getModifiers())) PlayerInfoData_getLatency = m;
|
||||
}
|
||||
PlayerInfoData_getGamemode = getMethods(PlayerInfoData, EnumGamemode).get(0);
|
||||
PlayerInfoData_getDisplayName = getMethods(PlayerInfoData, IChatBaseComponent).get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads PacketPlayOutSpawnEntityLiving's methods, fields and constructors
|
||||
*
|
||||
* @throws ReflectiveOperationException
|
||||
* If some method, field or constructor was not found
|
||||
*/
|
||||
protected void spawnEntityLiving() throws ReflectiveOperationException {
|
||||
if (minorVersion >= 17) {
|
||||
if (is1_19_3Plus()) {
|
||||
newPacketPlayOutSpawnEntityLiving = PacketPlayOutSpawnEntityLiving.getConstructor(Entity);
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads PacketPlayOutEntityTeleport's methods, fields and constructors
|
||||
*
|
||||
* @throws ReflectiveOperationException
|
||||
* If some method, field or constructor was not found
|
||||
*/
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads PacketPlayOutPlayerListHeaderFooter's methods, fields and constructors
|
||||
*
|
||||
* @throws ReflectiveOperationException
|
||||
* If some method, field or constructor was not found
|
||||
*/
|
||||
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) {
|
||||
newPacketPlayOutPlayerListHeaderFooter = PacketPlayOutPlayerListHeaderFooter.getConstructor(IChatBaseComponent, IChatBaseComponent);
|
||||
} else {
|
||||
newPacketPlayOutPlayerListHeaderFooter = PacketPlayOutPlayerListHeaderFooter.getConstructor();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads methods, fields and constructors for other entity packets
|
||||
*
|
||||
* @throws ReflectiveOperationException
|
||||
* If some method, field or constructor was not found
|
||||
*/
|
||||
protected void otherEntity() throws ReflectiveOperationException {
|
||||
PacketPlayOutEntity_ENTITYID = getFields(PacketPlayOutEntity, int.class).get(0);
|
||||
PacketPlayOutEntityDestroy_ENTITIES = setAccessible(PacketPlayOutEntityDestroy.getDeclaredFields()[0]);
|
||||
if (is1_19_3Plus()) {
|
||||
newPacketPlayOutEntityMetadata = PacketPlayOutEntityMetadata.getConstructor(int.class, List.class);
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads DataWatcher's methods, fields and constructors
|
||||
*
|
||||
* @throws ReflectiveOperationException
|
||||
* If some method, field or constructor was not found
|
||||
*/
|
||||
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);
|
||||
if (is1_19_3Plus()) {
|
||||
DataWatcher$DataValue_POSITION = getFields(DataWatcher$DataValue, int.class).get(0);
|
||||
DataWatcher$DataValue_VALUE = getFields(DataWatcher$DataValue, Object.class).get(0);
|
||||
DataWatcher_markDirty = getMethods(DataWatcher, void.class, DataWatcherObject).get(0);
|
||||
}
|
||||
} else {
|
||||
DataWatcherItem_TYPE = getFields(DataWatcherItem, int.class).get(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads Scoreboard methods, fields and constructors
|
||||
*
|
||||
* @throws ReflectiveOperationException
|
||||
* If some method, field or constructor was not found
|
||||
*/
|
||||
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);
|
||||
if (minorVersion >= 8) {
|
||||
PacketPlayOutScoreboardObjective_RENDERTYPE = getFields(PacketPlayOutScoreboardObjective, EnumScoreboardHealthDisplay).get(0);
|
||||
}
|
||||
if (minorVersion >= 13) {
|
||||
newPacketPlayOutScoreboardObjective = PacketPlayOutScoreboardObjective.getConstructor(ScoreboardObjective, int.class);
|
||||
newPacketPlayOutScoreboardScore_1_13 = PacketPlayOutScoreboardScore.getConstructor(EnumScoreboardAction, String.class, String.class, int.class);
|
||||
PacketPlayOutScoreboardObjective_DISPLAYNAME = getFields(PacketPlayOutScoreboardObjective, IChatBaseComponent).get(0);
|
||||
} else {
|
||||
newPacketPlayOutScoreboardObjective = PacketPlayOutScoreboardObjective.getConstructor();
|
||||
newPacketPlayOutScoreboardScore_String = PacketPlayOutScoreboardScore.getConstructor(String.class);
|
||||
PacketPlayOutScoreboardObjective_DISPLAYNAME = getFields(PacketPlayOutScoreboardObjective, String.class).get(1);
|
||||
if (minorVersion >= 8) {
|
||||
newPacketPlayOutScoreboardScore = PacketPlayOutScoreboardScore.getConstructor(ScoreboardScore);
|
||||
} else {
|
||||
newPacketPlayOutScoreboardScore = PacketPlayOutScoreboardScore.getConstructor(ScoreboardScore, int.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads PacketPlayOutScoreboardTeam's methods, fields and constructors
|
||||
*
|
||||
* @throws ReflectiveOperationException
|
||||
* If some method, field or constructor was not found
|
||||
*/
|
||||
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);
|
||||
if (minorVersion >= 9) {
|
||||
ScoreboardTeam_setCollisionRule = getMethods(ScoreboardTeam, void.class, EnumTeamPush).get(0);
|
||||
}
|
||||
if (minorVersion >= 13) {
|
||||
ScoreboardTeam_setColor = getMethods(ScoreboardTeam, void.class, EnumChatFormat).get(0);
|
||||
}
|
||||
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);
|
||||
} else {
|
||||
newPacketPlayOutScoreboardTeam = PacketPlayOutScoreboardTeam.getConstructor(ScoreboardTeam, int.class);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all classes used by the plugin
|
||||
*
|
||||
* @throws ClassNotFoundException
|
||||
* If a class was not found
|
||||
*/
|
||||
public abstract void loadClasses() throws ClassNotFoundException;
|
||||
|
||||
/**
|
||||
* Loads all fields and methods which must be loaded by their name due to
|
||||
* lack of other methods of reliably retrieving them.
|
||||
*
|
||||
* @throws ReflectiveOperationException
|
||||
* If a field or method was not found
|
||||
*/
|
||||
public abstract void loadNamedFieldsAndMethods() throws ReflectiveOperationException;
|
||||
|
||||
/**
|
||||
* Returns method with specified possible names and parameters. Throws exception if no such method was found
|
||||
*
|
||||
* @param clazz
|
||||
* lass to get method from
|
||||
* @param names
|
||||
* possible method names
|
||||
* @param parameterTypes
|
||||
* parameter types of the method
|
||||
* @return method with specified name and parameters
|
||||
* @throws NoSuchMethodException
|
||||
* if no such method exists
|
||||
*/
|
||||
protected Method getMethod(Class<?> clazz, String[] names, Class<?>... parameterTypes) throws NoSuchMethodException {
|
||||
for (String name : names) {
|
||||
try {
|
||||
return clazz.getMethod(name, parameterTypes);
|
||||
} catch (NoSuchMethodException e) {
|
||||
//not the first method in array
|
||||
}
|
||||
}
|
||||
List<String> list = new ArrayList<>();
|
||||
for (Method m : clazz.getMethods()) {
|
||||
if (m.getParameterCount() != parameterTypes.length) continue;
|
||||
Class<?>[] types = m.getParameterTypes();
|
||||
boolean valid = true;
|
||||
for (int i=0; i<types.length; i++) {
|
||||
if (types[i] != parameterTypes[i]) {
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (valid) list.add(m.getName());
|
||||
}
|
||||
throw new NoSuchMethodException("No method found with possible names " + Arrays.toString(names) + " with parameters " +
|
||||
Arrays.toString(parameterTypes) + " in class " + clazz.getName() + ". Methods with matching parameters: " + list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all methods from class which return specified class type and have specified parameter types.
|
||||
*
|
||||
* @param clazz
|
||||
* Class to get methods from
|
||||
* @param returnType
|
||||
* Return type of methods
|
||||
* @param parameterTypes
|
||||
* Parameter types of methods
|
||||
* @return List of found methods matching requirements. If nothing is found, empty list is returned.
|
||||
*/
|
||||
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;
|
||||
Class<?>[] types = m.getParameterTypes();
|
||||
boolean valid = true;
|
||||
for (int i=0; i<types.length; i++) {
|
||||
if (types[i] != parameterTypes[i]) {
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (valid) list.add(m);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all fields of class with defined class type
|
||||
*
|
||||
* @param clazz
|
||||
* class to check fields of
|
||||
* @param type
|
||||
* field type to check for
|
||||
* @return list of all fields with specified class type
|
||||
*/
|
||||
protected List<Field> getFields(Class<?> clazz, Class<?> type) {
|
||||
List<Field> list = new ArrayList<>();
|
||||
for (Field field : clazz.getDeclaredFields()) {
|
||||
if (field.getType() == type) {
|
||||
list.add(setAccessible(field));
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all instance fields of class with defined class type
|
||||
*
|
||||
* @param clazz
|
||||
* class to check fields of
|
||||
* @param type
|
||||
* field type to check for
|
||||
* @return list of all fields with specified class type
|
||||
*/
|
||||
public List<Field> getInstanceFields(Class<?> clazz, Class<?> type) {
|
||||
List<Field> list = new ArrayList<>();
|
||||
for (Field field : clazz.getDeclaredFields()) {
|
||||
if (field.getType() == type && !Modifier.isStatic(field.getModifiers())) {
|
||||
list.add(setAccessible(field));
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns field with specified name and makes it accessible
|
||||
*
|
||||
* @param clazz
|
||||
* class to get field from
|
||||
* @param name
|
||||
* field name
|
||||
* @return accessible field with defined name
|
||||
* @throws NoSuchFieldException
|
||||
* if field was not found
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
throw new NoSuchFieldException("Field \"" + name + "\" was not found in class " + clazz.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets value of a field in object
|
||||
*
|
||||
* @param obj
|
||||
* Instance of object where field should be set
|
||||
* @param field
|
||||
* Field to set value of
|
||||
* @param value
|
||||
* Value to set field to
|
||||
* @throws IllegalAccessException
|
||||
* If thrown by reflective operation
|
||||
*/
|
||||
public void setField(Object obj, Field field, Object value) throws IllegalAccessException {
|
||||
field.set(obj, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes object accessible and returns it for chaining.
|
||||
*
|
||||
* @param o
|
||||
* Object to make accessible
|
||||
* @return Entered object, for chaining
|
||||
*/
|
||||
public <T extends AccessibleObject> T setAccessible(T o) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
-49
@@ -1,49 +0,0 @@
|
||||
package me.neznamy.tab.platforms.bukkit.nms.storage;
|
||||
|
||||
import me.neznamy.tab.platforms.bukkit.Main;
|
||||
|
||||
/**
|
||||
* NMS loader for Thermos 1.7.10.
|
||||
*/
|
||||
public class ThermosNMSStorage extends BukkitLegacyNMSStorage {
|
||||
|
||||
/**
|
||||
* Creates new instance, initializes required NMS classes and fields
|
||||
*
|
||||
* @throws ReflectiveOperationException
|
||||
* If any class, field or method fails to load
|
||||
*/
|
||||
public ThermosNMSStorage() throws ReflectiveOperationException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns class from given name
|
||||
*
|
||||
* @param name
|
||||
* class name
|
||||
* @return class from given name
|
||||
* @throws ClassNotFoundException
|
||||
* if class was not found
|
||||
*/
|
||||
@Override
|
||||
public Class<?> getLegacyClass(String name) throws ClassNotFoundException {
|
||||
try {
|
||||
return Main.class.getClassLoader().loadClass("net.minecraft.server." + serverPackage + "." + name);
|
||||
} catch (NullPointerException e) {
|
||||
// nested class not found
|
||||
throw new ClassNotFoundException(name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadNamedFieldsAndMethods() throws ReflectiveOperationException {
|
||||
PING = getField(EntityPlayer, "field_71138_i");
|
||||
ScoreboardScore_setScore = ScoreboardScore.getMethod("func_96647_c", int.class);
|
||||
ScoreboardTeam_setAllowFriendlyFire = ScoreboardTeam.getMethod("func_96660_a", boolean.class);
|
||||
ScoreboardTeam_setCanSeeFriendlyInvisibles = ScoreboardTeam.getMethod("func_98300_b", boolean.class);
|
||||
ChatSerializer_DESERIALIZE = ChatSerializer.getMethod("func_150699_a", String.class);
|
||||
DataWatcher_REGISTER = DataWatcher.getMethod("func_75682_a", int.class, Object.class);
|
||||
ScoreboardTeam_setPrefix = ScoreboardTeam.getMethod("func_96666_b", String.class);
|
||||
ScoreboardTeam_setSuffix = ScoreboardTeam.getMethod("func_96662_c", String.class);
|
||||
}
|
||||
}
|
||||
+164
@@ -0,0 +1,164 @@
|
||||
package me.neznamy.tab.platforms.bukkit.nms.storage.nms;
|
||||
|
||||
import me.neznamy.tab.platforms.bukkit.nms.PacketPlayOutEntityDestroy;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.PacketPlayOutEntityMetadata;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.PacketPlayOutEntityTeleport;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.PacketPlayOutSpawnEntityLiving;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcher;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcherHelper;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcherItem;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcherObject;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.packet.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* NMS loader for Minecraft 1.5.2 - 1.16.5 using Bukkit mapping.
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public class BukkitLegacyNMSStorage extends NMSStorage {
|
||||
|
||||
public BukkitLegacyNMSStorage() 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
|
||||
*/
|
||||
public Class<?> getLegacyClass(String name) throws ClassNotFoundException {
|
||||
return Class.forName("net.minecraft.server." + serverPackage + "." + name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadNamedFieldsAndMethods() throws ReflectiveOperationException {
|
||||
(PING = EntityPlayer.getDeclaredField("ping")).setAccessible(true);
|
||||
PacketPlayOutScoreboardScoreStorage.ScoreboardScore_setScore = getMethod(PacketPlayOutScoreboardScoreStorage.ScoreboardScore, new String[] {"setScore", "c"}, int.class); // 1.5.1+, 1.5
|
||||
PacketPlayOutScoreboardTeamStorage.ScoreboardTeam_setAllowFriendlyFire = getMethod(PacketPlayOutScoreboardTeamStorage.ScoreboardTeam, new String[] {"setAllowFriendlyFire", "a"}, boolean.class); // 1.5.1+, 1.5
|
||||
PacketPlayOutScoreboardTeamStorage.ScoreboardTeam_setCanSeeFriendlyInvisibles = getMethod(PacketPlayOutScoreboardTeamStorage.ScoreboardTeam, new String[] {"setCanSeeFriendlyInvisibles", "b"}, boolean.class); // 1.5.1+, 1.5
|
||||
if (minorVersion >= 7) {
|
||||
ChatSerializer_DESERIALIZE = ChatSerializer.getMethod("a", String.class);
|
||||
}
|
||||
if (minorVersion >= 8) {
|
||||
PacketPlayOutScoreboardTeamStorage.ScoreboardTeam_setNameTagVisibility = getMethod(PacketPlayOutScoreboardTeamStorage.ScoreboardTeam, new String[] {"setNameTagVisibility", "a"}, PacketPlayOutScoreboardTeamStorage.EnumNameTagVisibility); // {1.8.1+, 1.8}
|
||||
}
|
||||
if (minorVersion >= 9) {
|
||||
DataWatcher.REGISTER = DataWatcher.CLASS.getMethod("register", DataWatcherObject.CLASS, Object.class);
|
||||
DataWatcherHelper.DataWatcherSerializer_BYTE = DataWatcherHelper.DataWatcherRegistry.getDeclaredField("a").get(null);
|
||||
DataWatcherHelper.DataWatcherSerializer_FLOAT = DataWatcherHelper.DataWatcherRegistry.getDeclaredField("c").get(null);
|
||||
DataWatcherHelper.DataWatcherSerializer_STRING = DataWatcherHelper.DataWatcherRegistry.getDeclaredField("d").get(null);
|
||||
if (getMinorVersion() >= 13) {
|
||||
DataWatcherHelper.DataWatcherSerializer_OPTIONAL_COMPONENT = DataWatcherHelper.DataWatcherRegistry.getDeclaredField("f").get(null);
|
||||
DataWatcherHelper.DataWatcherSerializer_BOOLEAN = DataWatcherHelper.DataWatcherRegistry.getDeclaredField("i").get(null);
|
||||
} else {
|
||||
DataWatcherHelper.DataWatcherSerializer_BOOLEAN = DataWatcherHelper.DataWatcherRegistry.getDeclaredField("h").get(null);
|
||||
}
|
||||
} else {
|
||||
DataWatcher.REGISTER = DataWatcher.CLASS.getMethod("a", int.class, Object.class);
|
||||
}
|
||||
if (minorVersion >= 13) {
|
||||
PacketPlayOutScoreboardTeamStorage.ScoreboardTeam_setPrefix = PacketPlayOutScoreboardTeamStorage.ScoreboardTeam.getMethod("setPrefix", IChatBaseComponent);
|
||||
PacketPlayOutScoreboardTeamStorage.ScoreboardTeam_setSuffix = PacketPlayOutScoreboardTeamStorage.ScoreboardTeam.getMethod("setSuffix", IChatBaseComponent);
|
||||
} else {
|
||||
PacketPlayOutScoreboardTeamStorage.ScoreboardTeam_setPrefix = getMethod(PacketPlayOutScoreboardTeamStorage.ScoreboardTeam, new String[] {"setPrefix", "b"}, String.class); // 1.5.1+, 1.5
|
||||
PacketPlayOutScoreboardTeamStorage.ScoreboardTeam_setSuffix = getMethod(PacketPlayOutScoreboardTeamStorage.ScoreboardTeam, new String[] {"setSuffix", "c"}, String.class); // 1.5.1+, 1.5
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadClasses() throws ClassNotFoundException {
|
||||
EntityHuman = getLegacyClass("EntityHuman");
|
||||
World = getLegacyClass("World");
|
||||
Packet = getLegacyClass("Packet");
|
||||
EnumChatFormat = (Class<Enum>) getLegacyClass("EnumChatFormat");
|
||||
EntityPlayer = getLegacyClass("EntityPlayer");
|
||||
Entity = getLegacyClass("Entity");
|
||||
EntityLiving = getLegacyClass("EntityLiving");
|
||||
PlayerConnection = getLegacyClass("PlayerConnection");
|
||||
PacketPlayOutChatStorage.CLASS = getLegacyClass("PacketPlayOutChat", "Packet3Chat");
|
||||
NetworkManager = getLegacyClass("NetworkManager");
|
||||
if (minorVersion >= 7) {
|
||||
IChatBaseComponent = getLegacyClass("IChatBaseComponent");
|
||||
ChatSerializer = getLegacyClass("IChatBaseComponent$ChatSerializer", "ChatSerializer");
|
||||
}
|
||||
if (minorVersion >= 8) {
|
||||
PacketPlayOutPlayerListHeaderFooterStorage.CLASS = getLegacyClass("PacketPlayOutPlayerListHeaderFooter");
|
||||
EntityArmorStand = getLegacyClass("EntityArmorStand");
|
||||
}
|
||||
if (minorVersion >= 12) {
|
||||
PacketPlayOutChatStorage.ChatMessageTypeClass = (Class<Enum>) getLegacyClass("ChatMessageType");
|
||||
}
|
||||
|
||||
// DataWatcher
|
||||
DataWatcher.CLASS = getLegacyClass("DataWatcher");
|
||||
DataWatcherItem.CLASS = getLegacyClass("DataWatcher$Item", "DataWatcher$WatchableObject", "WatchableObject");
|
||||
if (minorVersion >= 9) {
|
||||
DataWatcherObject.CLASS = getLegacyClass("DataWatcherObject");
|
||||
DataWatcherHelper.DataWatcherRegistry = getLegacyClass("DataWatcherRegistry");
|
||||
DataWatcherHelper.DataWatcherSerializer = getLegacyClass("DataWatcherSerializer");
|
||||
}
|
||||
|
||||
// Entities
|
||||
PacketPlayOutSpawnEntityLiving.CLASS = getLegacyClass("PacketPlayOutSpawnEntityLiving", "Packet24MobSpawn");
|
||||
PacketPlayOutEntityTeleport.CLASS = getLegacyClass("PacketPlayOutEntityTeleport", "Packet34EntityTeleport");
|
||||
PacketPlayInUseEntity = getLegacyClass("PacketPlayInUseEntity", "Packet7UseEntity");
|
||||
PacketPlayOutEntity = getLegacyClass("PacketPlayOutEntity", "Packet30Entity");
|
||||
PacketPlayOutEntityDestroy.CLASS = getLegacyClass("PacketPlayOutEntityDestroy", "Packet29DestroyEntity");
|
||||
PacketPlayOutEntityLook = getLegacyClass("PacketPlayOutEntity$PacketPlayOutEntityLook", "PacketPlayOutEntityLook", "Packet32EntityLook");
|
||||
PacketPlayOutEntityMetadata.CLASS = getLegacyClass("PacketPlayOutEntityMetadata", "Packet40EntityMetadata");
|
||||
PacketPlayOutNamedEntitySpawn = getLegacyClass("PacketPlayOutNamedEntitySpawn", "Packet20NamedEntitySpawn");
|
||||
if (minorVersion >= 7) {
|
||||
EnumEntityUseAction = (Class<Enum>) getLegacyClass("PacketPlayInUseEntity$EnumEntityUseAction", "EnumEntityUseAction");
|
||||
}
|
||||
|
||||
// Player Info
|
||||
if (minorVersion >= 8) {
|
||||
PacketPlayOutPlayerInfoStorage.CLASS = getLegacyClass("PacketPlayOutPlayerInfo");
|
||||
PacketPlayOutPlayerInfoStorage.EnumPlayerInfoActionClass = (Class<Enum>) getLegacyClass("PacketPlayOutPlayerInfo$EnumPlayerInfoAction", "EnumPlayerInfoAction");
|
||||
PacketPlayOutPlayerInfoStorage.PlayerInfoDataStorage.CLASS = getLegacyClass("PacketPlayOutPlayerInfo$PlayerInfoData", "PlayerInfoData");
|
||||
PacketPlayOutPlayerInfoStorage.EnumGamemodeClass = (Class<Enum>) getLegacyClass("EnumGamemode", "WorldSettings$EnumGamemode");
|
||||
}
|
||||
|
||||
// Scoreboard
|
||||
PacketPlayOutScoreboardDisplayObjectiveStorage.CLASS = getLegacyClass("PacketPlayOutScoreboardDisplayObjective", "Packet208SetScoreboardDisplayObjective");
|
||||
PacketPlayOutScoreboardObjectiveStorage.CLASS = getLegacyClass("PacketPlayOutScoreboardObjective", "Packet206SetScoreboardObjective");
|
||||
PacketPlayOutScoreboardTeamStorage.CLASS = getLegacyClass("PacketPlayOutScoreboardTeam", "Packet209SetScoreboardTeam");
|
||||
PacketPlayOutScoreboardScoreStorage.CLASS = getLegacyClass("PacketPlayOutScoreboardScore", "Packet207SetScoreboardScore");
|
||||
Scoreboard = getLegacyClass("Scoreboard");
|
||||
PacketPlayOutScoreboardObjectiveStorage.ScoreboardObjective = getLegacyClass("ScoreboardObjective");
|
||||
PacketPlayOutScoreboardScoreStorage.ScoreboardScore = getLegacyClass("ScoreboardScore");
|
||||
IScoreboardCriteria = getLegacyClass("IScoreboardCriteria", "IObjective"); // 1.5.1+, 1.5
|
||||
PacketPlayOutScoreboardTeamStorage.ScoreboardTeam = getLegacyClass("ScoreboardTeam");
|
||||
if (minorVersion >= 8) {
|
||||
PacketPlayOutScoreboardObjectiveStorage.EnumScoreboardHealthDisplay = (Class<Enum>) getLegacyClass("IScoreboardCriteria$EnumScoreboardHealthDisplay", "EnumScoreboardHealthDisplay");
|
||||
PacketPlayOutScoreboardScoreStorage.EnumScoreboardAction = (Class<Enum>) getLegacyClass("ScoreboardServer$Action", "PacketPlayOutScoreboardScore$EnumScoreboardAction", "EnumScoreboardAction");
|
||||
PacketPlayOutScoreboardTeamStorage.EnumNameTagVisibility = (Class<Enum>) getLegacyClass("ScoreboardTeamBase$EnumNameTagVisibility", "EnumNameTagVisibility");
|
||||
}
|
||||
if (minorVersion >= 9) {
|
||||
PacketPlayOutScoreboardTeamStorage.EnumTeamPush = (Class<Enum>) getLegacyClass("ScoreboardTeamBase$EnumTeamPush");
|
||||
}
|
||||
}
|
||||
}
|
||||
+136
@@ -0,0 +1,136 @@
|
||||
package me.neznamy.tab.platforms.bukkit.nms.storage.nms;
|
||||
|
||||
import me.neznamy.tab.platforms.bukkit.nms.PacketPlayOutEntityDestroy;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.PacketPlayOutEntityMetadata;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.PacketPlayOutEntityTeleport;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.PacketPlayOutSpawnEntityLiving;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcher;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcherHelper;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcherItem;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcherObject;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.packet.*;
|
||||
|
||||
/**
|
||||
* NMS loader for minecraft 1.17+ using Mojang packaging and bukkit names.
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public class BukkitModernNMSStorage extends NMSStorage {
|
||||
|
||||
public BukkitModernNMSStorage() throws ReflectiveOperationException {}
|
||||
|
||||
@Override
|
||||
public void loadNamedFieldsAndMethods() throws ReflectiveOperationException {
|
||||
(PING = EntityPlayer.getDeclaredField("e")).setAccessible(true);
|
||||
ChatSerializer_DESERIALIZE = ChatSerializer.getMethod("a", String.class);
|
||||
DataWatcher.REGISTER = getMethod(DataWatcher.CLASS, new String[]{"register", "a"}, DataWatcherObject.CLASS, Object.class); // {Bukkit, Bukkit 1.18+}
|
||||
PacketPlayOutScoreboardScoreStorage.ScoreboardScore_setScore = getMethod(PacketPlayOutScoreboardScoreStorage.ScoreboardScore, new String[]{"setScore", "b"}, int.class); // {Bukkit, Bukkit 1.18+}
|
||||
PacketPlayOutScoreboardTeamStorage.ScoreboardTeam_setAllowFriendlyFire = getMethod(PacketPlayOutScoreboardTeamStorage.ScoreboardTeam, new String[]{"setAllowFriendlyFire", "a"}, boolean.class); // {Bukkit, Bukkit 1.18+}
|
||||
PacketPlayOutScoreboardTeamStorage.ScoreboardTeam_setCanSeeFriendlyInvisibles = getMethod(PacketPlayOutScoreboardTeamStorage.ScoreboardTeam, new String[]{"setCanSeeFriendlyInvisibles", "b"}, boolean.class); // {Bukkit, Bukkit 1.18+}
|
||||
PacketPlayOutScoreboardTeamStorage.ScoreboardTeam_setPrefix = getMethod(PacketPlayOutScoreboardTeamStorage.ScoreboardTeam, new String[]{"setPrefix", "b"}, IChatBaseComponent); // {Bukkit, Bukkit 1.18+}
|
||||
PacketPlayOutScoreboardTeamStorage.ScoreboardTeam_setSuffix = getMethod(PacketPlayOutScoreboardTeamStorage.ScoreboardTeam, new String[]{"setSuffix", "c"}, IChatBaseComponent); // {Bukkit, Bukkit 1.18+}
|
||||
PacketPlayOutScoreboardTeamStorage.ScoreboardTeam_setNameTagVisibility = getMethod(PacketPlayOutScoreboardTeamStorage.ScoreboardTeam, new String[]{"setNameTagVisibility", "a"}, PacketPlayOutScoreboardTeamStorage.EnumNameTagVisibility); // {Bukkit, Bukkit 1.18+}
|
||||
DataWatcherHelper.DataWatcherSerializer_BYTE = DataWatcherHelper.DataWatcherRegistry.getDeclaredField("a").get(null);
|
||||
DataWatcherHelper.DataWatcherSerializer_FLOAT = DataWatcherHelper.DataWatcherRegistry.getDeclaredField("c").get(null);
|
||||
DataWatcherHelper.DataWatcherSerializer_STRING = DataWatcherHelper.DataWatcherRegistry.getDeclaredField("d").get(null);
|
||||
if (is1_19_3Plus()) {
|
||||
DataWatcherHelper.DataWatcherSerializer_OPTIONAL_COMPONENT = DataWatcherHelper.DataWatcherRegistry.getDeclaredField("g").get(null);
|
||||
DataWatcherHelper.DataWatcherSerializer_BOOLEAN = DataWatcherHelper.DataWatcherRegistry.getDeclaredField("j").get(null);
|
||||
} else {
|
||||
DataWatcherHelper.DataWatcherSerializer_OPTIONAL_COMPONENT = DataWatcherHelper.DataWatcherRegistry.getDeclaredField("f").get(null);
|
||||
DataWatcherHelper.DataWatcherSerializer_BOOLEAN = DataWatcherHelper.DataWatcherRegistry.getDeclaredField("i").get(null);
|
||||
}
|
||||
if (minorVersion >= 19) {
|
||||
PacketPlayOutSpawnEntityLiving.EntityTypes_ARMOR_STAND = PacketPlayOutSpawnEntityLiving.EntityTypes.getDeclaredField("d").get(null);
|
||||
(PacketPlayOutSpawnEntityLiving.ENTITY_TYPE = PacketPlayOutSpawnEntityLiving.CLASS.getDeclaredField("e")).setAccessible(true);
|
||||
DataWatcher.packDirty = DataWatcher.CLASS.getMethod("b");
|
||||
}
|
||||
}
|
||||
|
||||
@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<Enum>) 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");
|
||||
|
||||
PacketPlayOutPlayerListHeaderFooterStorage.CLASS = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutPlayerListHeaderFooter");
|
||||
if (minorVersion >= 19) {
|
||||
PacketPlayOutChatStorage.CLASS = Class.forName("net.minecraft.network.protocol.game.ClientboundSystemChatPacket");
|
||||
} else {
|
||||
PacketPlayOutChatStorage.CLASS = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutChat");
|
||||
PacketPlayOutChatStorage.ChatMessageTypeClass = (Class<Enum>) Class.forName("net.minecraft.network.chat.ChatMessageType");
|
||||
}
|
||||
|
||||
// DataWatcher
|
||||
DataWatcher.CLASS = Class.forName("net.minecraft.network.syncher.DataWatcher");
|
||||
DataWatcherItem.CLASS = Class.forName("net.minecraft.network.syncher.DataWatcher$Item");
|
||||
DataWatcherObject.CLASS = Class.forName("net.minecraft.network.syncher.DataWatcherObject");
|
||||
DataWatcherHelper.DataWatcherRegistry = Class.forName("net.minecraft.network.syncher.DataWatcherRegistry");
|
||||
DataWatcherHelper.DataWatcherSerializer = Class.forName("net.minecraft.network.syncher.DataWatcherSerializer");
|
||||
if (is1_19_3Plus()) {
|
||||
DataWatcher.DataValue = Class.forName("net.minecraft.network.syncher.DataWatcher$b");
|
||||
}
|
||||
|
||||
// Entities
|
||||
if (minorVersion >= 19) {
|
||||
PacketPlayOutSpawnEntityLiving.CLASS = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutSpawnEntity");
|
||||
} else {
|
||||
PacketPlayOutSpawnEntityLiving.CLASS = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutSpawnEntityLiving");
|
||||
}
|
||||
PacketPlayOutEntityTeleport.CLASS = 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 = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutEntityDestroy");
|
||||
PacketPlayOutEntityLook = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutEntity$PacketPlayOutEntityLook");
|
||||
PacketPlayOutEntityMetadata.CLASS = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutEntityMetadata");
|
||||
PacketPlayOutNamedEntitySpawn = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutNamedEntitySpawn");
|
||||
EnumEntityUseAction = (Class<Enum>) Class.forName("net.minecraft.network.protocol.game.PacketPlayInUseEntity$EnumEntityUseAction");
|
||||
if (minorVersion >= 19) {
|
||||
PacketPlayOutSpawnEntityLiving.EntityTypes = Class.forName("net.minecraft.world.entity.EntityTypes");
|
||||
}
|
||||
|
||||
// Player Info
|
||||
if (minorVersion >= 19) {
|
||||
PacketPlayOutPlayerInfoStorage.ProfilePublicKey = Class.forName("net.minecraft.world.entity.player.ProfilePublicKey");
|
||||
PacketPlayOutPlayerInfoStorage.ProfilePublicKey$a = Class.forName("net.minecraft.world.entity.player.ProfilePublicKey$a");
|
||||
}
|
||||
if (is1_19_3Plus()) {
|
||||
PacketPlayOutPlayerInfoStorage.ClientboundPlayerInfoRemovePacket = Class.forName("net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket");
|
||||
PacketPlayOutPlayerInfoStorage.CLASS = Class.forName("net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket");
|
||||
PacketPlayOutPlayerInfoStorage.EnumPlayerInfoActionClass = (Class<Enum>) Class.forName("net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket$a");
|
||||
PacketPlayOutPlayerInfoStorage.PlayerInfoDataStorage.CLASS = Class.forName("net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket$b");
|
||||
PacketPlayOutPlayerInfoStorage.RemoteChatSession = Class.forName("net.minecraft.network.chat.RemoteChatSession");
|
||||
PacketPlayOutPlayerInfoStorage.RemoteChatSession$Data = Class.forName("net.minecraft.network.chat.RemoteChatSession$a");
|
||||
} else {
|
||||
PacketPlayOutPlayerInfoStorage.CLASS = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo");
|
||||
PacketPlayOutPlayerInfoStorage.EnumPlayerInfoActionClass = (Class<Enum>) Class.forName("net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo$EnumPlayerInfoAction");
|
||||
PacketPlayOutPlayerInfoStorage.PlayerInfoDataStorage.CLASS = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo$PlayerInfoData");
|
||||
}
|
||||
PacketPlayOutPlayerInfoStorage.EnumGamemodeClass = (Class<Enum>) Class.forName("net.minecraft.world.level.EnumGamemode");
|
||||
|
||||
// Scoreboard
|
||||
PacketPlayOutScoreboardDisplayObjectiveStorage.CLASS = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutScoreboardDisplayObjective");
|
||||
PacketPlayOutScoreboardObjectiveStorage.CLASS = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutScoreboardObjective");
|
||||
Scoreboard = Class.forName("net.minecraft.world.scores.Scoreboard");
|
||||
PacketPlayOutScoreboardScoreStorage.CLASS = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutScoreboardScore");
|
||||
PacketPlayOutScoreboardObjectiveStorage.ScoreboardObjective = Class.forName("net.minecraft.world.scores.ScoreboardObjective");
|
||||
PacketPlayOutScoreboardScoreStorage.ScoreboardScore = Class.forName("net.minecraft.world.scores.ScoreboardScore");
|
||||
IScoreboardCriteria = Class.forName("net.minecraft.world.scores.criteria.IScoreboardCriteria");
|
||||
PacketPlayOutScoreboardObjectiveStorage.EnumScoreboardHealthDisplay = (Class<Enum>) Class.forName("net.minecraft.world.scores.criteria.IScoreboardCriteria$EnumScoreboardHealthDisplay");
|
||||
PacketPlayOutScoreboardScoreStorage.EnumScoreboardAction = (Class<Enum>) Class.forName("net.minecraft.server.ScoreboardServer$Action");
|
||||
PacketPlayOutScoreboardTeamStorage.CLASS = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutScoreboardTeam");
|
||||
PacketPlayOutScoreboardTeamStorage.ScoreboardTeam = Class.forName("net.minecraft.world.scores.ScoreboardTeam");
|
||||
PacketPlayOutScoreboardTeamStorage.EnumNameTagVisibility = (Class<Enum>) Class.forName("net.minecraft.world.scores.ScoreboardTeamBase$EnumNameTagVisibility");
|
||||
PacketPlayOutScoreboardTeamStorage.EnumTeamPush = (Class<Enum>) Class.forName("net.minecraft.world.scores.ScoreboardTeamBase$EnumTeamPush");
|
||||
PacketPlayOutScoreboardTeamStorage.PlayerAction = (Class<Enum>) Class.forName("net.minecraft.network.protocol.game.PacketPlayOutScoreboardTeam$a");
|
||||
}
|
||||
}
|
||||
+130
@@ -0,0 +1,130 @@
|
||||
package me.neznamy.tab.platforms.bukkit.nms.storage.nms;
|
||||
|
||||
import me.neznamy.tab.platforms.bukkit.nms.PacketPlayOutEntityDestroy;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.PacketPlayOutEntityMetadata;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.PacketPlayOutEntityTeleport;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.PacketPlayOutSpawnEntityLiving;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcher;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcherHelper;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcherItem;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcherObject;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.packet.*;
|
||||
|
||||
/**
|
||||
* NMS loader for minecraft 1.17+ using Mojang packaging and names.
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public class MojangModernNMSStorage extends NMSStorage {
|
||||
|
||||
public MojangModernNMSStorage() throws ReflectiveOperationException {}
|
||||
|
||||
@Override
|
||||
public void loadNamedFieldsAndMethods() throws ReflectiveOperationException {
|
||||
(PING = EntityPlayer.getDeclaredField("latency")).setAccessible(true);
|
||||
ChatSerializer_DESERIALIZE = ChatSerializer.getMethod("fromJson", String.class);
|
||||
DataWatcher.REGISTER = DataWatcher.CLASS.getMethod("define", DataWatcherObject.CLASS, Object.class);
|
||||
PacketPlayOutScoreboardScoreStorage.ScoreboardScore_setScore = PacketPlayOutScoreboardScoreStorage.ScoreboardScore.getMethod("setScore", int.class);
|
||||
PacketPlayOutScoreboardTeamStorage.ScoreboardTeam_setAllowFriendlyFire = PacketPlayOutScoreboardTeamStorage.ScoreboardTeam.getMethod("setAllowFriendlyFire", boolean.class);
|
||||
PacketPlayOutScoreboardTeamStorage.ScoreboardTeam_setCanSeeFriendlyInvisibles = PacketPlayOutScoreboardTeamStorage.ScoreboardTeam.getMethod("setSeeFriendlyInvisibles", boolean.class);
|
||||
PacketPlayOutScoreboardTeamStorage.ScoreboardTeam_setPrefix = PacketPlayOutScoreboardTeamStorage.ScoreboardTeam.getMethod("setPlayerPrefix", IChatBaseComponent);
|
||||
PacketPlayOutScoreboardTeamStorage.ScoreboardTeam_setSuffix = PacketPlayOutScoreboardTeamStorage.ScoreboardTeam.getMethod("setPlayerSuffix", IChatBaseComponent);
|
||||
PacketPlayOutScoreboardTeamStorage.ScoreboardTeam_setNameTagVisibility = PacketPlayOutScoreboardTeamStorage.ScoreboardTeam.getMethod("setNameTagVisibility", PacketPlayOutScoreboardTeamStorage.EnumNameTagVisibility);
|
||||
DataWatcherHelper.DataWatcherSerializer_BYTE = DataWatcherHelper.DataWatcherRegistry.getDeclaredField("BYTE").get(null);
|
||||
DataWatcherHelper.DataWatcherSerializer_FLOAT = DataWatcherHelper.DataWatcherRegistry.getDeclaredField("FLOAT").get(null);
|
||||
DataWatcherHelper.DataWatcherSerializer_STRING = DataWatcherHelper.DataWatcherRegistry.getDeclaredField("STRING").get(null);
|
||||
DataWatcherHelper.DataWatcherSerializer_OPTIONAL_COMPONENT = DataWatcherHelper.DataWatcherRegistry.getDeclaredField("OPTIONAL_COMPONENT").get(null);
|
||||
DataWatcherHelper.DataWatcherSerializer_BOOLEAN = DataWatcherHelper.DataWatcherRegistry.getDeclaredField("BOOLEAN").get(null);
|
||||
if (minorVersion >= 19) {
|
||||
PacketPlayOutSpawnEntityLiving.EntityTypes_ARMOR_STAND = PacketPlayOutSpawnEntityLiving.EntityTypes.getDeclaredField("ARMOR_STAND").get(null);
|
||||
(PacketPlayOutSpawnEntityLiving.ENTITY_TYPE = PacketPlayOutSpawnEntityLiving.CLASS.getDeclaredField("type")).setAccessible(true);
|
||||
DataWatcher.packDirty = DataWatcher.CLASS.getMethod("packDirty");
|
||||
}
|
||||
}
|
||||
|
||||
@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<Enum>) 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");
|
||||
PacketPlayOutPlayerListHeaderFooterStorage.CLASS = Class.forName("net.minecraft.network.protocol.game.ClientboundTabListPacket");
|
||||
if (minorVersion >= 19) {
|
||||
PacketPlayOutChatStorage.CLASS = Class.forName("net.minecraft.network.protocol.game.ClientboundSystemChatPacket");
|
||||
} else {
|
||||
PacketPlayOutChatStorage.CLASS = Class.forName("net.minecraft.network.protocol.game.ClientboundChatPacket");
|
||||
PacketPlayOutChatStorage.ChatMessageTypeClass = (Class<Enum>) Class.forName("net.minecraft.network.chat.ChatType");
|
||||
}
|
||||
|
||||
// DataWatcher
|
||||
DataWatcher.CLASS = Class.forName("net.minecraft.network.syncher.SynchedEntityData");
|
||||
DataWatcherItem.CLASS = Class.forName("net.minecraft.network.syncher.SynchedEntityData$DataItem");
|
||||
DataWatcherObject.CLASS = Class.forName("net.minecraft.network.syncher.EntityDataAccessor");
|
||||
DataWatcherHelper.DataWatcherRegistry = Class.forName("net.minecraft.network.syncher.EntityDataSerializers");
|
||||
DataWatcherHelper.DataWatcherSerializer = Class.forName("net.minecraft.network.syncher.EntityDataSerializer");
|
||||
if (is1_19_3Plus()) {
|
||||
DataWatcher.DataValue = Class.forName("net.minecraft.network.syncher.SynchedEntityData$DataValue");
|
||||
}
|
||||
|
||||
// Entities
|
||||
if (minorVersion >= 19) {
|
||||
PacketPlayOutSpawnEntityLiving.CLASS = Class.forName("net.minecraft.network.protocol.game.ClientboundAddEntityPacket");
|
||||
} else {
|
||||
PacketPlayOutSpawnEntityLiving.CLASS = Class.forName("net.minecraft.network.protocol.game.ClientboundAddMobPacket");
|
||||
}
|
||||
PacketPlayOutEntityTeleport.CLASS = 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 = Class.forName("net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket");
|
||||
PacketPlayOutEntityLook = Class.forName("net.minecraft.network.protocol.game.ClientboundMoveEntityPacket$Rot");
|
||||
PacketPlayOutEntityMetadata.CLASS = Class.forName("net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket");
|
||||
PacketPlayOutNamedEntitySpawn = Class.forName("net.minecraft.network.protocol.game.ClientboundAddPlayerPacket");
|
||||
EnumEntityUseAction = (Class<Enum>) Class.forName("net.minecraft.network.protocol.game.ServerboundInteractPacket$Action");
|
||||
if (minorVersion >= 19) {
|
||||
PacketPlayOutSpawnEntityLiving.EntityTypes = Class.forName("net.minecraft.world.entity.EntityType");
|
||||
}
|
||||
|
||||
// Player Info
|
||||
if (minorVersion >= 19) {
|
||||
PacketPlayOutPlayerInfoStorage.ProfilePublicKey = Class.forName("net.minecraft.world.entity.player.ProfilePublicKey");
|
||||
PacketPlayOutPlayerInfoStorage.ProfilePublicKey$a = Class.forName("net.minecraft.world.entity.player.ProfilePublicKey$Data");
|
||||
}
|
||||
if (is1_19_3Plus()) {
|
||||
PacketPlayOutPlayerInfoStorage.ClientboundPlayerInfoRemovePacket = Class.forName("net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket");
|
||||
PacketPlayOutPlayerInfoStorage.CLASS = Class.forName("net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket");
|
||||
PacketPlayOutPlayerInfoStorage.EnumPlayerInfoActionClass = (Class<Enum>) Class.forName("net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket$Action");
|
||||
PacketPlayOutPlayerInfoStorage.PlayerInfoDataStorage.CLASS = Class.forName("net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket$Entry");
|
||||
PacketPlayOutPlayerInfoStorage.RemoteChatSession = Class.forName("net.minecraft.network.chat.RemoteChatSession");
|
||||
PacketPlayOutPlayerInfoStorage.RemoteChatSession$Data = Class.forName("net.minecraft.network.chat.RemoteChatSession$Data");
|
||||
} else {
|
||||
PacketPlayOutPlayerInfoStorage.CLASS = Class.forName("net.minecraft.network.protocol.game.ClientboundPlayerInfoPacket");
|
||||
PacketPlayOutPlayerInfoStorage.EnumPlayerInfoActionClass = (Class<Enum>) Class.forName("net.minecraft.network.protocol.game.ClientboundPlayerInfoPacket$Action");
|
||||
PacketPlayOutPlayerInfoStorage.PlayerInfoDataStorage.CLASS = Class.forName("net.minecraft.network.protocol.game.ClientboundPlayerInfoPacket$PlayerUpdate");
|
||||
}
|
||||
PacketPlayOutPlayerInfoStorage.EnumGamemodeClass = (Class<Enum>) Class.forName("net.minecraft.world.level.GameType");
|
||||
|
||||
// Scoreboard
|
||||
PacketPlayOutScoreboardDisplayObjectiveStorage.CLASS = Class.forName("net.minecraft.network.protocol.game.ClientboundSetDisplayObjectivePacket");
|
||||
PacketPlayOutScoreboardObjectiveStorage.CLASS = Class.forName("net.minecraft.network.protocol.game.ClientboundSetObjectivePacket");
|
||||
Scoreboard = Class.forName("net.minecraft.world.scores.Scoreboard");
|
||||
PacketPlayOutScoreboardScoreStorage.CLASS = Class.forName("net.minecraft.network.protocol.game.ClientboundSetScorePacket");
|
||||
PacketPlayOutScoreboardObjectiveStorage.ScoreboardObjective = Class.forName("net.minecraft.world.scores.Objective");
|
||||
PacketPlayOutScoreboardScoreStorage.ScoreboardScore = Class.forName("net.minecraft.world.scores.Score");
|
||||
IScoreboardCriteria = Class.forName("net.minecraft.world.scores.criteria.ObjectiveCriteria");
|
||||
PacketPlayOutScoreboardObjectiveStorage.EnumScoreboardHealthDisplay = (Class<Enum>) Class.forName("net.minecraft.world.scores.criteria.ObjectiveCriteria$RenderType");
|
||||
PacketPlayOutScoreboardScoreStorage.EnumScoreboardAction = (Class<Enum>) Class.forName("net.minecraft.server.ServerScoreboard$Method");
|
||||
PacketPlayOutScoreboardTeamStorage.CLASS = Class.forName("net.minecraft.network.protocol.game.ClientboundSetPlayerTeamPacket");
|
||||
PacketPlayOutScoreboardTeamStorage.ScoreboardTeam = Class.forName("net.minecraft.world.scores.PlayerTeam");
|
||||
PacketPlayOutScoreboardTeamStorage.EnumNameTagVisibility = (Class<Enum>) Class.forName("net.minecraft.world.scores.Team$Visibility");
|
||||
PacketPlayOutScoreboardTeamStorage.EnumTeamPush = (Class<Enum>) Class.forName("net.minecraft.world.scores.Team$CollisionRule");
|
||||
PacketPlayOutScoreboardTeamStorage.PlayerAction = (Class<Enum>) Class.forName("net.minecraft.network.protocol.game.ClientboundSetPlayerTeamPacket$Action");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,290 @@
|
||||
package me.neznamy.tab.platforms.bukkit.nms.storage.nms;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import me.neznamy.tab.api.ProtocolVersion;
|
||||
import me.neznamy.tab.api.TabAPI;
|
||||
import me.neznamy.tab.api.chat.IChatBaseComponent;
|
||||
import me.neznamy.tab.api.chat.WrappedChatComponent;
|
||||
import me.neznamy.tab.api.util.ComponentCache;
|
||||
import me.neznamy.tab.api.util.ReflectionUtils;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.PacketPlayOutEntityDestroy;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.PacketPlayOutEntityMetadata;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.PacketPlayOutEntityTeleport;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.PacketPlayOutSpawnEntityLiving;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcher;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcherItem;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcherObject;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.packet.*;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
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.List;
|
||||
|
||||
/**
|
||||
* Class holding all NMS classes, methods, fields and constructors used by TAB.
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public abstract class NMSStorage {
|
||||
|
||||
/** Instance of this class */
|
||||
@Getter @Setter private static NMSStorage instance;
|
||||
|
||||
/** Server's NMS/CraftBukkit package */
|
||||
protected final String serverPackage = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
|
||||
|
||||
/** Server's minor version */
|
||||
@Getter protected final int minorVersion = Integer.parseInt(serverPackage.split("_")[1]);
|
||||
|
||||
/** Flag determining whether the server version is at least 1.19.3 or not */
|
||||
@Getter private final boolean is1_19_3Plus = ReflectionUtils.classExists("net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket");
|
||||
|
||||
/** Basic universal values */
|
||||
protected Class<?> Packet;
|
||||
protected Class<?> NetworkManager;
|
||||
protected Class<?> EntityArmorStand;
|
||||
protected Class<?> World;
|
||||
public Class<Enum> EnumChatFormat;
|
||||
public Class<?> EntityPlayer;
|
||||
protected Class<?> EntityHuman;
|
||||
public Class<?> Entity;
|
||||
public Class<?> EntityLiving;
|
||||
protected Class<?> PlayerConnection;
|
||||
public Field PING;
|
||||
public Field PLAYER_CONNECTION;
|
||||
public Field NETWORK_MANAGER;
|
||||
public Field CHANNEL;
|
||||
public Method getHandle;
|
||||
public Method sendPacket;
|
||||
public Method getProfile;
|
||||
|
||||
/** Chat components */
|
||||
public Class<?> IChatBaseComponent;
|
||||
protected Class<?> ChatSerializer;
|
||||
public Method ChatSerializer_DESERIALIZE;
|
||||
|
||||
/** Other entity packets */
|
||||
public Class<?> PacketPlayInUseEntity;
|
||||
public Class<?> PacketPlayInUseEntity$d;
|
||||
protected Class<Enum> EnumEntityUseAction;
|
||||
public Field PacketPlayInUseEntity_ENTITY;
|
||||
public Field PacketPlayInUseEntity_ACTION;
|
||||
|
||||
public Class<?> PacketPlayOutEntity;
|
||||
public Field PacketPlayOutEntity_ENTITYID;
|
||||
|
||||
public Class<?> PacketPlayOutEntityLook;
|
||||
|
||||
public Class<?> PacketPlayOutNamedEntitySpawn;
|
||||
public Field PacketPlayOutNamedEntitySpawn_ENTITYID;
|
||||
|
||||
/** Scoreboard objectives */
|
||||
public Class<?> Scoreboard;
|
||||
protected Constructor<?> newScoreboard;
|
||||
protected Class<?> IScoreboardCriteria;
|
||||
public Field IScoreboardCriteria_self;
|
||||
public Object emptyScoreboard;
|
||||
|
||||
public Object dummyEntity;
|
||||
|
||||
private final ComponentCache<IChatBaseComponent, Object> componentCache = new ComponentCache<>(10000,
|
||||
(component, clientVersion) -> ChatSerializer_DESERIALIZE.invoke(null, component.toString(clientVersion)));
|
||||
|
||||
/**
|
||||
* Constructs new instance and attempts to load all fields, methods and constructors.
|
||||
*
|
||||
* @throws ReflectiveOperationException
|
||||
* If some field, constructor or method was not found
|
||||
*/
|
||||
public NMSStorage() throws ReflectiveOperationException {
|
||||
ProtocolVersion.UNKNOWN_SERVER_VERSION.setMinorVersion(minorVersion); //fixing compatibility with forks that set version field value to "Unknown"
|
||||
loadClasses();
|
||||
if (minorVersion >= 7) {
|
||||
NETWORK_MANAGER = getFields(PlayerConnection, NetworkManager).get(0);
|
||||
}
|
||||
if (minorVersion >= 8) {
|
||||
CHANNEL = getFields(NetworkManager, Channel.class).get(0);
|
||||
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);
|
||||
}
|
||||
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);
|
||||
newScoreboard = Scoreboard.getConstructor();
|
||||
emptyScoreboard = newScoreboard.newInstance();
|
||||
DataWatcher.load(this);
|
||||
DataWatcherItem.load(this);
|
||||
DataWatcherObject.load(this);
|
||||
PacketPlayOutEntityDestroy.load(this);
|
||||
PacketPlayOutEntityMetadata.load(this);
|
||||
PacketPlayOutEntityTeleport.load(this);
|
||||
PacketPlayOutSpawnEntityLiving.load(this);
|
||||
PacketPlayOutChatStorage.load(this);
|
||||
PacketPlayOutPlayerListHeaderFooterStorage.load(this);
|
||||
PacketPlayOutPlayerInfoStorage.load(this);
|
||||
PacketPlayOutScoreboardObjectiveStorage.load(this);
|
||||
PacketPlayOutScoreboardDisplayObjectiveStorage.load(this);
|
||||
otherEntity();
|
||||
PacketPlayOutScoreboardTeamStorage.load(this);
|
||||
PacketPlayOutScoreboardScoreStorage.load(this);
|
||||
IScoreboardCriteria_self = getFields(IScoreboardCriteria, IScoreboardCriteria).get(0);
|
||||
loadNamedFieldsAndMethods();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads fields for other entity packets
|
||||
*
|
||||
*/
|
||||
protected void otherEntity() {
|
||||
PacketPlayOutEntity_ENTITYID = getFields(PacketPlayOutEntity, int.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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all classes used by the plugin
|
||||
*
|
||||
* @throws ClassNotFoundException
|
||||
* If a class was not found
|
||||
*/
|
||||
public abstract void loadClasses() throws ClassNotFoundException;
|
||||
|
||||
/**
|
||||
* Loads all fields and methods which must be loaded by their name due to
|
||||
* lack of other methods of reliably retrieving them.
|
||||
*
|
||||
* @throws ReflectiveOperationException
|
||||
* If a field or method was not found
|
||||
*/
|
||||
public abstract void loadNamedFieldsAndMethods() throws ReflectiveOperationException;
|
||||
|
||||
/**
|
||||
* Returns method with specified possible names and parameters. Throws exception if no such method was found
|
||||
*
|
||||
* @param clazz
|
||||
* lass to get method from
|
||||
* @param names
|
||||
* possible method names
|
||||
* @param parameterTypes
|
||||
* parameter types of the method
|
||||
* @return method with specified name and parameters
|
||||
* @throws NoSuchMethodException
|
||||
* if no such method exists
|
||||
*/
|
||||
protected Method getMethod(Class<?> clazz, String[] names, Class<?>... parameterTypes) throws NoSuchMethodException {
|
||||
for (String name : names) {
|
||||
try {
|
||||
return clazz.getMethod(name, parameterTypes);
|
||||
} catch (NoSuchMethodException e) {
|
||||
//not the first method in array
|
||||
}
|
||||
}
|
||||
List<String> list = new ArrayList<>();
|
||||
for (Method m : clazz.getMethods()) {
|
||||
if (m.getParameterCount() != parameterTypes.length) continue;
|
||||
Class<?>[] types = m.getParameterTypes();
|
||||
boolean valid = true;
|
||||
for (int i=0; i<types.length; i++) {
|
||||
if (types[i] != parameterTypes[i]) {
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (valid) list.add(m.getName());
|
||||
}
|
||||
throw new NoSuchMethodException("No method found with possible names " + Arrays.toString(names) + " with parameters " +
|
||||
Arrays.toString(parameterTypes) + " in class " + clazz.getName() + ". Methods with matching parameters: " + list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all methods from class which return specified class type and have specified parameter types.
|
||||
*
|
||||
* @param clazz
|
||||
* Class to get methods from
|
||||
* @param returnType
|
||||
* Return type of methods
|
||||
* @param parameterTypes
|
||||
* Parameter types of methods
|
||||
* @return List of found methods matching requirements. If nothing is found, empty list is returned.
|
||||
*/
|
||||
public 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;
|
||||
Class<?>[] types = m.getParameterTypes();
|
||||
boolean valid = true;
|
||||
for (int i=0; i<types.length; i++) {
|
||||
if (types[i] != parameterTypes[i]) {
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (valid) list.add(m);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all fields of class with defined class type
|
||||
*
|
||||
* @param clazz
|
||||
* class to check fields of
|
||||
* @param type
|
||||
* field type to check for
|
||||
* @return list of all fields with specified class type
|
||||
*/
|
||||
public List<Field> getFields(Class<?> clazz, Class<?> type) {
|
||||
List<Field> list = new ArrayList<>();
|
||||
for (Field field : clazz.getDeclaredFields()) {
|
||||
if (field.getType() == type) {
|
||||
field.setAccessible(true);
|
||||
list.add(field);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts TAB's IChatBaseComponent into minecraft's component using String deserialization.
|
||||
* If the requested component is found in cache, it is returned. If not, it is created, added into cache and returned.
|
||||
* If {@code component} is {@code null}, returns {@code null}
|
||||
*
|
||||
* @param component
|
||||
* component to convert
|
||||
* @param clientVersion
|
||||
* client version used to decide RGB conversion
|
||||
* @return converted component or {@code null} if {@code component} is {@code null}
|
||||
*/
|
||||
public Object toNMSComponent(IChatBaseComponent component, ProtocolVersion clientVersion) {
|
||||
if (component instanceof WrappedChatComponent) return ((WrappedChatComponent) component).getOriginalComponent();
|
||||
return componentCache.get(component, clientVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Scoreboard Objective with given name.
|
||||
*
|
||||
* @param objectiveName
|
||||
* Objective name
|
||||
* @return NMS Objective
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public Object newScoreboardObjective(String objectiveName) throws ReflectiveOperationException {
|
||||
if (minorVersion >= 13) {
|
||||
return PacketPlayOutScoreboardObjectiveStorage.newScoreboardObjective.newInstance(null, objectiveName, null, toNMSComponent(new IChatBaseComponent(""), TabAPI.getInstance().getServerVersion()), null);
|
||||
}
|
||||
return PacketPlayOutScoreboardObjectiveStorage.newScoreboardObjective.newInstance(null, objectiveName, IScoreboardCriteria_self.get(null));
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package me.neznamy.tab.platforms.bukkit.nms.storage.nms;
|
||||
|
||||
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcher;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.packet.PacketPlayOutScoreboardScoreStorage;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.packet.PacketPlayOutScoreboardTeamStorage;
|
||||
|
||||
/**
|
||||
* NMS loader for Thermos 1.7.10.
|
||||
*/
|
||||
public class ThermosNMSStorage extends BukkitLegacyNMSStorage {
|
||||
|
||||
public ThermosNMSStorage() throws ReflectiveOperationException {}
|
||||
|
||||
@Override
|
||||
public Class<?> getLegacyClass(String name) throws ClassNotFoundException {
|
||||
try {
|
||||
return getClass().getClassLoader().loadClass("net.minecraft.server." + serverPackage + "." + name);
|
||||
} catch (NullPointerException e) {
|
||||
// nested class not found
|
||||
throw new ClassNotFoundException(name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadNamedFieldsAndMethods() throws ReflectiveOperationException {
|
||||
(PING = EntityPlayer.getDeclaredField("field_71138_i")).setAccessible(true);
|
||||
PacketPlayOutScoreboardScoreStorage.ScoreboardScore_setScore = PacketPlayOutScoreboardScoreStorage.ScoreboardScore.getMethod("func_96647_c", int.class);
|
||||
PacketPlayOutScoreboardTeamStorage.ScoreboardTeam_setAllowFriendlyFire = PacketPlayOutScoreboardTeamStorage.ScoreboardTeam.getMethod("func_96660_a", boolean.class);
|
||||
PacketPlayOutScoreboardTeamStorage.ScoreboardTeam_setCanSeeFriendlyInvisibles = PacketPlayOutScoreboardTeamStorage.ScoreboardTeam.getMethod("func_98300_b", boolean.class);
|
||||
ChatSerializer_DESERIALIZE = ChatSerializer.getMethod("func_150699_a", String.class);
|
||||
DataWatcher.REGISTER = DataWatcher.CLASS.getMethod("func_75682_a", int.class, Object.class);
|
||||
PacketPlayOutScoreboardTeamStorage.ScoreboardTeam_setPrefix = PacketPlayOutScoreboardTeamStorage.ScoreboardTeam.getMethod("func_96666_b", String.class);
|
||||
PacketPlayOutScoreboardTeamStorage.ScoreboardTeam_setSuffix = PacketPlayOutScoreboardTeamStorage.ScoreboardTeam.getMethod("func_96662_c", String.class);
|
||||
}
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
package me.neznamy.tab.platforms.bukkit.nms.storage.packet;
|
||||
|
||||
import me.neznamy.tab.api.ProtocolVersion;
|
||||
import me.neznamy.tab.api.protocol.PacketPlayOutChat;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.nms.NMSStorage;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.UUID;
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public class PacketPlayOutChatStorage {
|
||||
|
||||
public static Class<?> CLASS;
|
||||
public static Class<Enum> ChatMessageTypeClass;
|
||||
public static Constructor<?> CONSTRUCTOR;
|
||||
|
||||
public static void load(NMSStorage nms) throws NoSuchMethodException {
|
||||
if (nms.getMinorVersion() >= 19) {
|
||||
try {
|
||||
CONSTRUCTOR = CLASS.getConstructor(nms.IChatBaseComponent, boolean.class);
|
||||
} catch (NoSuchMethodException e) {
|
||||
//1.19.0
|
||||
CONSTRUCTOR = CLASS.getConstructor(nms.IChatBaseComponent, int.class);
|
||||
}
|
||||
} else if (nms.getMinorVersion() >= 16) {
|
||||
CONSTRUCTOR = CLASS.getConstructor(nms.IChatBaseComponent, ChatMessageTypeClass, UUID.class);
|
||||
} else if (nms.getMinorVersion() >= 12) {
|
||||
CONSTRUCTOR = CLASS.getConstructor(nms.IChatBaseComponent, ChatMessageTypeClass);
|
||||
} else if (nms.getMinorVersion() >= 8) {
|
||||
CONSTRUCTOR = CLASS.getConstructor(nms.IChatBaseComponent, byte.class);
|
||||
} else if (nms.getMinorVersion() >= 7) {
|
||||
CONSTRUCTOR = CLASS.getConstructor(nms.IChatBaseComponent);
|
||||
}
|
||||
}
|
||||
|
||||
public static Object build(PacketPlayOutChat packet, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
NMSStorage nms = NMSStorage.getInstance();
|
||||
Object component = nms.toNMSComponent(packet.getMessage(), clientVersion);
|
||||
if (nms.getMinorVersion() >= 19)
|
||||
try {
|
||||
return CONSTRUCTOR.newInstance(component, packet.getType() == PacketPlayOutChat.ChatMessageType.GAME_INFO);
|
||||
} catch (Exception e) {
|
||||
//1.19.0
|
||||
return CONSTRUCTOR.newInstance(component, packet.getType().ordinal());
|
||||
}
|
||||
if (nms.getMinorVersion() >= 16)
|
||||
return CONSTRUCTOR.newInstance(component, Enum.valueOf(ChatMessageTypeClass, packet.getType().toString()), UUID.randomUUID());
|
||||
if (nms.getMinorVersion() >= 12)
|
||||
return CONSTRUCTOR.newInstance(component, Enum.valueOf(ChatMessageTypeClass, packet.getType().toString()));
|
||||
if (nms.getMinorVersion() >= 8)
|
||||
return CONSTRUCTOR.newInstance(component, (byte) packet.getType().ordinal());
|
||||
if (nms.getMinorVersion() == 7)
|
||||
return CONSTRUCTOR.newInstance(component);
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
+207
@@ -0,0 +1,207 @@
|
||||
package me.neznamy.tab.platforms.bukkit.nms.storage.packet;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import me.neznamy.tab.api.ProtocolVersion;
|
||||
import me.neznamy.tab.api.chat.WrappedChatComponent;
|
||||
import me.neznamy.tab.api.protocol.PacketPlayOutPlayerInfo;
|
||||
import me.neznamy.tab.api.protocol.Skin;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.nms.NMSStorage;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public class PacketPlayOutPlayerInfoStorage {
|
||||
|
||||
public static Class<?> CLASS;
|
||||
public static Constructor<?> CONSTRUCTOR;
|
||||
public static Field ACTION;
|
||||
public static Field PLAYERS;
|
||||
public static Class<Enum> EnumPlayerInfoActionClass;
|
||||
public static Class<Enum> EnumGamemodeClass;
|
||||
public static Class<?> ProfilePublicKey;
|
||||
public static Class<?> ProfilePublicKey$a;
|
||||
|
||||
//1.19.3+
|
||||
public static Class<?> ClientboundPlayerInfoRemovePacket;
|
||||
public static Class<?> RemoteChatSession;
|
||||
public static Class<?> RemoteChatSession$Data;
|
||||
public static Constructor<?> newClientboundPlayerInfoRemovePacket;
|
||||
public static Constructor<?> newRemoteChatSession$Data;
|
||||
public static Method ClientboundPlayerInfoRemovePacket_getEntries;
|
||||
public static Method RemoteChatSession$Data_getSessionId;
|
||||
public static Method RemoteChatSession$Data_getProfilePublicKey;
|
||||
|
||||
public static void load(NMSStorage nms) throws NoSuchMethodException {
|
||||
if (nms.getMinorVersion() < 8) return;
|
||||
if (nms.is1_19_3Plus()) {
|
||||
newClientboundPlayerInfoRemovePacket = ClientboundPlayerInfoRemovePacket.getConstructor(List.class);
|
||||
CONSTRUCTOR = CLASS.getConstructor(EnumSet.class, Collection.class);
|
||||
ClientboundPlayerInfoRemovePacket_getEntries = nms.getMethods(ClientboundPlayerInfoRemovePacket, List.class).get(0);
|
||||
ACTION = nms.getFields(CLASS, EnumSet.class).get(0);
|
||||
newRemoteChatSession$Data = RemoteChatSession$Data.getConstructor(UUID.class, ProfilePublicKey$a);
|
||||
RemoteChatSession$Data_getSessionId = nms.getMethods(RemoteChatSession$Data, UUID.class).get(0);
|
||||
RemoteChatSession$Data_getProfilePublicKey = nms.getMethods(RemoteChatSession$Data, ProfilePublicKey$a).get(0);
|
||||
} else {
|
||||
CONSTRUCTOR = CLASS.getConstructor(EnumPlayerInfoActionClass, Array.newInstance(nms.EntityPlayer, 0).getClass());
|
||||
ACTION = nms.getFields(CLASS, EnumPlayerInfoActionClass).get(0);
|
||||
}
|
||||
PLAYERS = nms.getFields(CLASS, List.class).get(0);
|
||||
PlayerInfoDataStorage.load(nms);
|
||||
}
|
||||
|
||||
public static Object build(PacketPlayOutPlayerInfo packet, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
NMSStorage nms = NMSStorage.getInstance();
|
||||
if (nms.getMinorVersion() < 8) return null;
|
||||
Object nmsPacket;
|
||||
if (ClientboundPlayerInfoRemovePacket != null) {
|
||||
//1.19.3+
|
||||
if (packet.getActions().contains(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER)) {
|
||||
return newClientboundPlayerInfoRemovePacket.newInstance(
|
||||
packet.getEntries().stream().map(PacketPlayOutPlayerInfo.PlayerInfoData::getUniqueId).collect(Collectors.toList())
|
||||
);
|
||||
}
|
||||
Enum[] array = packet.getActions().stream().map(action -> Enum.valueOf(EnumPlayerInfoActionClass, action.toString())).toArray(Enum[]::new);
|
||||
nmsPacket = CONSTRUCTOR.newInstance(EnumSet.of(array[0], array), Collections.emptyList());
|
||||
} else {
|
||||
//1.19.2-
|
||||
PacketPlayOutPlayerInfo.EnumPlayerInfoAction action = packet.getActions().contains(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER) ?
|
||||
PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER : packet.getActions().iterator().next();
|
||||
nmsPacket = CONSTRUCTOR.newInstance(Enum.valueOf(EnumPlayerInfoActionClass, action.toString()), Array.newInstance(nms.EntityPlayer, 0));
|
||||
}
|
||||
List<Object> items = new ArrayList<>();
|
||||
for (PacketPlayOutPlayerInfo.PlayerInfoData data : packet.getEntries()) {
|
||||
items.add(PlayerInfoDataStorage.build(nmsPacket, data, clientVersion));
|
||||
}
|
||||
PLAYERS.set(nmsPacket, items);
|
||||
return nmsPacket;
|
||||
}
|
||||
|
||||
public static PacketPlayOutPlayerInfo read(Object nmsPacket) throws ReflectiveOperationException {
|
||||
NMSStorage nms = NMSStorage.getInstance();
|
||||
if (nms.getMinorVersion() < 8) return null;
|
||||
if (ClientboundPlayerInfoRemovePacket != null && ClientboundPlayerInfoRemovePacket.isInstance(nmsPacket)) {
|
||||
List<UUID> entries = (List<UUID>) ClientboundPlayerInfoRemovePacket_getEntries.invoke(nmsPacket);
|
||||
return new PacketPlayOutPlayerInfo(
|
||||
PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER,
|
||||
entries.stream().map(PacketPlayOutPlayerInfo.PlayerInfoData::new).collect(Collectors.toList())
|
||||
);
|
||||
}
|
||||
List<PacketPlayOutPlayerInfo.PlayerInfoData> listData = new ArrayList<>();
|
||||
for (Object nmsData : (List<?>) PLAYERS.get(nmsPacket)) {
|
||||
listData.add(PlayerInfoDataStorage.read(nmsData));
|
||||
}
|
||||
if (ClientboundPlayerInfoRemovePacket != null) {
|
||||
//1.19.3+
|
||||
PacketPlayOutPlayerInfo.EnumPlayerInfoAction[] array = ((EnumSet<?>) ACTION.get(nmsPacket)).stream().map(action ->
|
||||
PacketPlayOutPlayerInfo.EnumPlayerInfoAction.valueOf(action.toString())).toArray(
|
||||
PacketPlayOutPlayerInfo.EnumPlayerInfoAction[]::new);
|
||||
return new PacketPlayOutPlayerInfo(EnumSet.of(array[0], array), listData);
|
||||
} else {
|
||||
//1.19.2-
|
||||
return new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.valueOf(ACTION.get(nmsPacket).toString()), listData);
|
||||
}
|
||||
}
|
||||
|
||||
public static class PlayerInfoDataStorage {
|
||||
|
||||
public static Class<?> CLASS;
|
||||
public static Constructor<?> newPlayerInfoData;
|
||||
public static Method PlayerInfoData_getProfile;
|
||||
public static Method PlayerInfoData_isListed;
|
||||
public static Method PlayerInfoData_getLatency;
|
||||
public static Method PlayerInfoData_getGamemode;
|
||||
public static Method PlayerInfoData_getDisplayName;
|
||||
public static Method PlayerInfoData_getProfilePublicKeyRecord;
|
||||
|
||||
public static void load(NMSStorage nms) {
|
||||
if (nms.getMinorVersion() < 8) return;
|
||||
newPlayerInfoData = CLASS.getConstructors()[0];
|
||||
PlayerInfoData_getProfile = nms.getMethods(CLASS, GameProfile.class).get(0);
|
||||
PlayerInfoData_getGamemode = nms.getMethods(CLASS, EnumGamemodeClass).get(0);
|
||||
PlayerInfoData_getDisplayName = nms.getMethods(CLASS, nms.IChatBaseComponent).get(0);
|
||||
for (Method m: nms.getMethods(CLASS, int.class)) {
|
||||
// do not take .hashCode(), which is final
|
||||
if (!Modifier.isFinal(m.getModifiers())) PlayerInfoData_getLatency = m;
|
||||
}
|
||||
if (nms.is1_19_3Plus()) {
|
||||
PlayerInfoData_getProfilePublicKeyRecord = nms.getMethods(CLASS, RemoteChatSession$Data).get(0);
|
||||
PlayerInfoData_isListed = nms.getMethods(CLASS, boolean.class).get(0);
|
||||
} else {
|
||||
if (nms.getMinorVersion() >= 19) {
|
||||
PlayerInfoData_getProfilePublicKeyRecord = nms.getMethods(CLASS, ProfilePublicKey$a).get(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Object build(Object nmsPacket, PacketPlayOutPlayerInfo.PlayerInfoData data, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
NMSStorage nms = NMSStorage.getInstance();
|
||||
if (ClientboundPlayerInfoRemovePacket != null) {
|
||||
//1.19.3+
|
||||
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()));
|
||||
return newPlayerInfoData.newInstance(
|
||||
data.getUniqueId(),
|
||||
profile,
|
||||
data.isListed(),
|
||||
data.getLatency(),
|
||||
data.getGameMode() == null ? null : Enum.valueOf(EnumGamemodeClass, data.getGameMode().toString()),
|
||||
data.getDisplayName() == null ? null : nms.toNMSComponent(data.getDisplayName(), clientVersion),
|
||||
data.getProfilePublicKey() == null ? null : newRemoteChatSession$Data.newInstance(data.getChatSessionId(), data.getProfilePublicKey()));
|
||||
|
||||
} else {
|
||||
//1.19.2-
|
||||
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 (newPlayerInfoData.getParameterTypes()[0] == PacketPlayOutPlayerInfoStorage.CLASS) {
|
||||
parameters.add(nmsPacket);
|
||||
}
|
||||
parameters.add(profile);
|
||||
parameters.add(data.getLatency());
|
||||
parameters.add(data.getGameMode() == null ? null : Enum.valueOf(EnumGamemodeClass, data.getGameMode().toString()));
|
||||
parameters.add(data.getDisplayName() == null ? null : nms.toNMSComponent(data.getDisplayName(), clientVersion));
|
||||
if (nms.getMinorVersion() >= 19) parameters.add(data.getProfilePublicKey());
|
||||
return newPlayerInfoData.newInstance(parameters.toArray());
|
||||
}
|
||||
}
|
||||
|
||||
public static PacketPlayOutPlayerInfo.PlayerInfoData read(Object nmsData) throws ReflectiveOperationException {
|
||||
Object nmsGameMode = PlayerInfoData_getGamemode.invoke(nmsData);
|
||||
PacketPlayOutPlayerInfo.EnumGamemode gameMode = (nmsGameMode == null) ? null : PacketPlayOutPlayerInfo.EnumGamemode.valueOf(nmsGameMode.toString());
|
||||
GameProfile profile = (GameProfile) PlayerInfoData_getProfile.invoke(nmsData);
|
||||
Object nmsComponent = PlayerInfoData_getDisplayName.invoke(nmsData);
|
||||
Skin skin = null;
|
||||
if (!profile.getProperties().get("textures").isEmpty()) {
|
||||
Property pr = profile.getProperties().get("textures").iterator().next();
|
||||
skin = new Skin(pr.getValue(), pr.getSignature());
|
||||
}
|
||||
boolean listed = true;
|
||||
UUID chatSessionId = null;
|
||||
Object profilePublicKey;
|
||||
if (ClientboundPlayerInfoRemovePacket != null) {
|
||||
//1.19.3+
|
||||
listed = (boolean) PlayerInfoData_isListed.invoke(nmsData);
|
||||
Object remoteChatSession = PlayerInfoData_getProfilePublicKeyRecord.invoke(nmsData);
|
||||
chatSessionId = remoteChatSession == null ? null : (UUID) RemoteChatSession$Data_getSessionId.invoke(remoteChatSession);
|
||||
profilePublicKey = remoteChatSession == null ? null : RemoteChatSession$Data_getProfilePublicKey.invoke(remoteChatSession);
|
||||
} else {
|
||||
//1.19.2-
|
||||
profilePublicKey = NMSStorage.getInstance().getMinorVersion() >= 19 ? PlayerInfoData_getProfilePublicKeyRecord.invoke(nmsData) : null;
|
||||
}
|
||||
return new PacketPlayOutPlayerInfo.PlayerInfoData(
|
||||
profile.getName(),
|
||||
profile.getId(),
|
||||
skin,
|
||||
listed,
|
||||
(int) PlayerInfoData_getLatency.invoke(nmsData),
|
||||
gameMode,
|
||||
nmsComponent == null ? null : new WrappedChatComponent(nmsComponent),
|
||||
chatSessionId,
|
||||
profilePublicKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package me.neznamy.tab.platforms.bukkit.nms.storage.packet;
|
||||
|
||||
import me.neznamy.tab.api.ProtocolVersion;
|
||||
import me.neznamy.tab.api.protocol.PacketPlayOutPlayerListHeaderFooter;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.nms.NMSStorage;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public class PacketPlayOutPlayerListHeaderFooterStorage {
|
||||
|
||||
public static Class<?> CLASS;
|
||||
public static Constructor<?> CONSTRUCTOR;
|
||||
public static Field HEADER;
|
||||
public static Field FOOTER;
|
||||
|
||||
public static void load(NMSStorage nms) throws NoSuchMethodException {
|
||||
if (nms.getMinorVersion() < 8) return;
|
||||
HEADER = nms.getFields(CLASS, nms.IChatBaseComponent).get(0);
|
||||
FOOTER = nms.getFields(CLASS, nms.IChatBaseComponent).get(1);
|
||||
if (nms.getMinorVersion() >= 17) {
|
||||
CONSTRUCTOR = CLASS.getConstructor(nms.IChatBaseComponent, nms.IChatBaseComponent);
|
||||
} else {
|
||||
CONSTRUCTOR = CLASS.getConstructor();
|
||||
}
|
||||
}
|
||||
|
||||
public static Object build(PacketPlayOutPlayerListHeaderFooter packet, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
NMSStorage nms = NMSStorage.getInstance();
|
||||
if (nms.getMinorVersion() < 8) return null;
|
||||
if (CONSTRUCTOR.getParameterCount() == 2) {
|
||||
return CONSTRUCTOR.newInstance(nms.toNMSComponent(packet.getHeader(), clientVersion),
|
||||
nms.toNMSComponent(packet.getFooter(), clientVersion));
|
||||
}
|
||||
Object nmsPacket = CONSTRUCTOR.newInstance();
|
||||
HEADER.set(nmsPacket, nms.toNMSComponent(packet.getHeader(), clientVersion));
|
||||
FOOTER.set(nmsPacket, nms.toNMSComponent(packet.getFooter(), clientVersion));
|
||||
return nmsPacket;
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package me.neznamy.tab.platforms.bukkit.nms.storage.packet;
|
||||
|
||||
import me.neznamy.tab.api.ProtocolVersion;
|
||||
import me.neznamy.tab.api.protocol.PacketPlayOutScoreboardDisplayObjective;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.nms.NMSStorage;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public class PacketPlayOutScoreboardDisplayObjectiveStorage {
|
||||
|
||||
public static Class<?> CLASS;
|
||||
public static Constructor<?> CONSTRUCTOR;
|
||||
public static Field POSITION;
|
||||
public static Field OBJECTIVE_NAME;
|
||||
|
||||
public static void load(NMSStorage nms) throws NoSuchMethodException {
|
||||
CONSTRUCTOR = CLASS.getConstructor(int.class, PacketPlayOutScoreboardObjectiveStorage.ScoreboardObjective);
|
||||
POSITION = nms.getFields(CLASS, int.class).get(0);
|
||||
OBJECTIVE_NAME = nms.getFields(CLASS, String.class).get(0);
|
||||
}
|
||||
|
||||
public static Object build(PacketPlayOutScoreboardDisplayObjective packet, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
return CONSTRUCTOR.newInstance(packet.getSlot(), NMSStorage.getInstance().newScoreboardObjective(packet.getObjectiveName()));
|
||||
}
|
||||
|
||||
public static PacketPlayOutScoreboardDisplayObjective read(Object nmsPacket) throws ReflectiveOperationException {
|
||||
return new PacketPlayOutScoreboardDisplayObjective(
|
||||
POSITION.getInt(nmsPacket),
|
||||
(String) OBJECTIVE_NAME.get(nmsPacket)
|
||||
);
|
||||
}
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
package me.neznamy.tab.platforms.bukkit.nms.storage.packet;
|
||||
|
||||
import me.neznamy.tab.api.ProtocolVersion;
|
||||
import me.neznamy.tab.api.chat.IChatBaseComponent;
|
||||
import me.neznamy.tab.api.protocol.PacketPlayOutScoreboardObjective;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.nms.NMSStorage;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public class PacketPlayOutScoreboardObjectiveStorage {
|
||||
|
||||
public static Class<?> CLASS;
|
||||
public static Constructor<?> CONSTRUCTOR;
|
||||
public static Field OBJECTIVE_NAME;
|
||||
public static Field METHOD;
|
||||
public static Field RENDER_TYPE;
|
||||
public static Field DISPLAY_NAME;
|
||||
|
||||
public static Class<Enum> EnumScoreboardHealthDisplay;
|
||||
public static Class<?> ScoreboardObjective;
|
||||
public static Constructor<?> newScoreboardObjective;
|
||||
|
||||
public static void load(NMSStorage nms) throws NoSuchMethodException {
|
||||
newScoreboardObjective = ScoreboardObjective.getConstructors()[0];
|
||||
OBJECTIVE_NAME = nms.getFields(CLASS, String.class).get(0);
|
||||
List<Field> list = nms.getFields(CLASS, int.class);
|
||||
METHOD = list.get(list.size()-1);
|
||||
if (nms.getMinorVersion() >= 8) {
|
||||
RENDER_TYPE = nms.getFields(CLASS, EnumScoreboardHealthDisplay).get(0);
|
||||
}
|
||||
if (nms.getMinorVersion() >= 13) {
|
||||
CONSTRUCTOR = CLASS.getConstructor(ScoreboardObjective, int.class);
|
||||
DISPLAY_NAME = nms.getFields(CLASS, nms.IChatBaseComponent).get(0);
|
||||
} else {
|
||||
CONSTRUCTOR = CLASS.getConstructor();
|
||||
DISPLAY_NAME = nms.getFields(CLASS, String.class).get(1);
|
||||
}
|
||||
}
|
||||
|
||||
public static Object build(PacketPlayOutScoreboardObjective packet, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
NMSStorage nms = NMSStorage.getInstance();
|
||||
String displayName = clientVersion.getMinorVersion() < 13 ? TAB.getInstance().getPlatform().getPacketBuilder().cutTo(packet.getDisplayName(), 32) : packet.getDisplayName();
|
||||
if (nms.getMinorVersion() >= 13) {
|
||||
return CONSTRUCTOR.newInstance(newScoreboardObjective.newInstance(null, packet.getObjectiveName(), null,
|
||||
nms.toNMSComponent(IChatBaseComponent.optimizedComponent(displayName), clientVersion),
|
||||
packet.getRenderType() == null ? null : Enum.valueOf(EnumScoreboardHealthDisplay, packet.getRenderType().toString())),
|
||||
packet.getAction());
|
||||
}
|
||||
|
||||
Object nmsPacket = CONSTRUCTOR.newInstance();
|
||||
OBJECTIVE_NAME.set(nmsPacket, packet.getObjectiveName());
|
||||
DISPLAY_NAME.set(nmsPacket, displayName);
|
||||
if (nms.getMinorVersion() >= 8 && packet.getRenderType() != null) {
|
||||
RENDER_TYPE.set(nmsPacket, Enum.valueOf(EnumScoreboardHealthDisplay, packet.getRenderType().toString()));
|
||||
}
|
||||
METHOD.set(nmsPacket, packet.getAction());
|
||||
return nmsPacket;
|
||||
}
|
||||
|
||||
public static PacketPlayOutScoreboardObjective read(Object nmsPacket) throws ReflectiveOperationException {
|
||||
return new PacketPlayOutScoreboardObjective(METHOD.getInt(nmsPacket),
|
||||
(String) OBJECTIVE_NAME.get(nmsPacket), null,
|
||||
PacketPlayOutScoreboardObjective.EnumScoreboardHealthDisplay.INTEGER
|
||||
);
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
package me.neznamy.tab.platforms.bukkit.nms.storage.packet;
|
||||
|
||||
import me.neznamy.tab.api.ProtocolVersion;
|
||||
import me.neznamy.tab.api.protocol.PacketPlayOutScoreboardScore;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.nms.NMSStorage;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public class PacketPlayOutScoreboardScoreStorage {
|
||||
|
||||
public static Class<?> CLASS;
|
||||
public static Constructor<?> CONSTRUCTOR_1_13;
|
||||
public static Constructor<?> CONSTRUCTOR_String;
|
||||
public static Constructor<?> CONSTRUCTOR;
|
||||
public static Class<?> ScoreboardScore;
|
||||
public static Constructor<?> newScoreboardScore;
|
||||
public static Method ScoreboardScore_setScore;
|
||||
public static Class<Enum> EnumScoreboardAction;
|
||||
|
||||
public static void load(NMSStorage nms) throws NoSuchMethodException {
|
||||
newScoreboardScore = ScoreboardScore.getConstructor(nms.Scoreboard, PacketPlayOutScoreboardObjectiveStorage.ScoreboardObjective, String.class);
|
||||
if (nms.getMinorVersion() >= 13) {
|
||||
CONSTRUCTOR_1_13 = CLASS.getConstructor(EnumScoreboardAction, String.class, String.class, int.class);
|
||||
} else {
|
||||
CONSTRUCTOR_String = CLASS.getConstructor(String.class);
|
||||
if (nms.getMinorVersion() >= 8) {
|
||||
CONSTRUCTOR = CLASS.getConstructor(ScoreboardScore);
|
||||
} else {
|
||||
CONSTRUCTOR = CLASS.getConstructor(ScoreboardScore, int.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Object build(PacketPlayOutScoreboardScore packet, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
NMSStorage nms = NMSStorage.getInstance();
|
||||
if (nms.getMinorVersion() >= 13) {
|
||||
return CONSTRUCTOR_1_13.newInstance(Enum.valueOf(EnumScoreboardAction, packet.getAction().toString()), packet.getObjectiveName(), packet.getPlayer(), packet.getScore());
|
||||
}
|
||||
if (packet.getAction() == PacketPlayOutScoreboardScore.Action.REMOVE) {
|
||||
return CONSTRUCTOR_String.newInstance(packet.getPlayer());
|
||||
}
|
||||
Object score = newScoreboardScore.newInstance(nms.emptyScoreboard, nms.newScoreboardObjective(packet.getObjectiveName()), packet.getPlayer());
|
||||
ScoreboardScore_setScore.invoke(score, packet.getScore());
|
||||
if (nms.getMinorVersion() >= 8) {
|
||||
return CONSTRUCTOR.newInstance(score);
|
||||
}
|
||||
return CONSTRUCTOR.newInstance(score, 0);
|
||||
}
|
||||
}
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
package me.neznamy.tab.platforms.bukkit.nms.storage.packet;
|
||||
|
||||
import me.neznamy.tab.api.ProtocolVersion;
|
||||
import me.neznamy.tab.api.chat.EnumChatFormat;
|
||||
import me.neznamy.tab.api.chat.IChatBaseComponent;
|
||||
import me.neznamy.tab.api.protocol.PacketPlayOutScoreboardTeam;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.storage.nms.NMSStorage;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
|
||||
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.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public class PacketPlayOutScoreboardTeamStorage {
|
||||
|
||||
public static Class<?> CLASS;
|
||||
public static Constructor<?> CONSTRUCTOR;
|
||||
public static Method Constructor_of;
|
||||
public static Method Constructor_ofBoolean;
|
||||
public static Method Constructor_ofString;
|
||||
public static Field NAME;
|
||||
public static Field ACTION;
|
||||
public static Field PLAYERS;
|
||||
public static Class<Enum> PlayerAction;
|
||||
|
||||
public static Class<Enum> EnumNameTagVisibility;
|
||||
public static Class<Enum> EnumTeamPush;
|
||||
|
||||
public static Class<?> ScoreboardTeam;
|
||||
public static Constructor<?> newScoreboardTeam;
|
||||
public static Method ScoreboardTeam_getPlayerNameSet;
|
||||
public static Method ScoreboardTeam_setNameTagVisibility;
|
||||
public static Method ScoreboardTeam_setCollisionRule;
|
||||
public static Method ScoreboardTeam_setPrefix;
|
||||
public static Method ScoreboardTeam_setSuffix;
|
||||
public static Method ScoreboardTeam_setColor;
|
||||
public static Method ScoreboardTeam_setAllowFriendlyFire;
|
||||
public static Method ScoreboardTeam_setCanSeeFriendlyInvisibles;
|
||||
|
||||
public static void load(NMSStorage nms) throws NoSuchMethodException {
|
||||
newScoreboardTeam = ScoreboardTeam.getConstructor(nms.Scoreboard, String.class);
|
||||
NAME = nms.getFields(CLASS, String.class).get(0);
|
||||
ACTION = getInstanceFields(CLASS, int.class).get(0);
|
||||
PLAYERS = nms.getFields(CLASS, Collection.class).get(0);
|
||||
ScoreboardTeam_getPlayerNameSet = nms.getMethods(ScoreboardTeam, Collection.class).get(0);
|
||||
if (nms.getMinorVersion() >= 9) {
|
||||
ScoreboardTeam_setCollisionRule = nms.getMethods(ScoreboardTeam, void.class, EnumTeamPush).get(0);
|
||||
}
|
||||
if (nms.getMinorVersion() >= 13) {
|
||||
ScoreboardTeam_setColor = nms.getMethods(ScoreboardTeam, void.class, nms.EnumChatFormat).get(0);
|
||||
}
|
||||
if (nms.getMinorVersion() >= 17) {
|
||||
Constructor_of = nms.getMethods(CLASS, CLASS, ScoreboardTeam).get(0);
|
||||
Constructor_ofBoolean = nms.getMethods(CLASS, CLASS, ScoreboardTeam, boolean.class).get(0);
|
||||
Constructor_ofString = nms.getMethods(CLASS, CLASS, ScoreboardTeam, String.class, PlayerAction).get(0);
|
||||
} else {
|
||||
CONSTRUCTOR = CLASS.getConstructor(ScoreboardTeam, int.class);
|
||||
}
|
||||
}
|
||||
|
||||
public static Object build(PacketPlayOutScoreboardTeam packet, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
NMSStorage nms = NMSStorage.getInstance();
|
||||
Object team = newScoreboardTeam.newInstance(nms.emptyScoreboard, packet.getName());
|
||||
String prefix = packet.getPlayerPrefix();
|
||||
String suffix = packet.getPlayerSuffix();
|
||||
if (clientVersion.getMinorVersion() < 13) {
|
||||
prefix = TAB.getInstance().getPlatform().getPacketBuilder().cutTo(prefix, 16);
|
||||
suffix = TAB.getInstance().getPlatform().getPacketBuilder().cutTo(suffix, 16);
|
||||
}
|
||||
((Collection<String>)ScoreboardTeam_getPlayerNameSet.invoke(team)).addAll(packet.getPlayers());
|
||||
ScoreboardTeam_setAllowFriendlyFire.invoke(team, (packet.getOptions() & 0x1) > 0);
|
||||
ScoreboardTeam_setCanSeeFriendlyInvisibles.invoke(team, (packet.getOptions() & 0x2) > 0);
|
||||
if (nms.getMinorVersion() >= 13) {
|
||||
createTeamModern(packet, clientVersion, team, prefix, suffix, nms);
|
||||
} else {
|
||||
createTeamLegacy(packet, team, prefix, suffix, nms);
|
||||
}
|
||||
if (nms.getMinorVersion() >= 17) {
|
||||
switch (packet.getAction()) {
|
||||
case 0:
|
||||
return Constructor_ofBoolean.invoke(null, team, true);
|
||||
case 1:
|
||||
return Constructor_of.invoke(null, team);
|
||||
case 2:
|
||||
return Constructor_ofBoolean.invoke(null, team, false);
|
||||
case 3:
|
||||
return Constructor_ofString.invoke(null, team, packet.getPlayers().iterator().next(), Enum.valueOf(PlayerAction, "ADD"));
|
||||
case 4:
|
||||
return Constructor_ofString.invoke(null, team, packet.getPlayers().iterator().next(), Enum.valueOf(PlayerAction, "REMOVE"));
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid action: " + packet.getAction());
|
||||
}
|
||||
}
|
||||
return CONSTRUCTOR.newInstance(team, packet.getAction());
|
||||
}
|
||||
|
||||
private static void createTeamModern(PacketPlayOutScoreboardTeam packet, ProtocolVersion clientVersion, Object team, String prefix, String suffix, NMSStorage nms) throws ReflectiveOperationException {
|
||||
if (prefix != null) ScoreboardTeam_setPrefix.invoke(team, nms.toNMSComponent(IChatBaseComponent.optimizedComponent(prefix), clientVersion));
|
||||
if (suffix != null) ScoreboardTeam_setSuffix.invoke(team, nms.toNMSComponent(IChatBaseComponent.optimizedComponent(suffix), clientVersion));
|
||||
EnumChatFormat format = packet.getColor() != null ? packet.getColor() : EnumChatFormat.lastColorsOf(prefix);
|
||||
ScoreboardTeam_setColor.invoke(team, Enum.valueOf(nms.EnumChatFormat, format.toString()));
|
||||
ScoreboardTeam_setNameTagVisibility.invoke(team, Enum.valueOf(EnumNameTagVisibility, String.valueOf(packet.getNameTagVisibility()).equals("always") ? "ALWAYS" : "NEVER"));
|
||||
ScoreboardTeam_setCollisionRule.invoke(team, Enum.valueOf(EnumTeamPush, String.valueOf(packet.getCollisionRule()).equals("always") ? "ALWAYS" : "NEVER"));
|
||||
}
|
||||
|
||||
private static void createTeamLegacy(PacketPlayOutScoreboardTeam packet, Object team, String prefix, String suffix, NMSStorage nms) throws ReflectiveOperationException {
|
||||
if (prefix != null) ScoreboardTeam_setPrefix.invoke(team, prefix);
|
||||
if (suffix != null) ScoreboardTeam_setSuffix.invoke(team, suffix);
|
||||
if (nms.getMinorVersion() >= 8) ScoreboardTeam_setNameTagVisibility.invoke(team, Enum.valueOf(EnumNameTagVisibility, String.valueOf(packet.getNameTagVisibility()).equals("always") ? "ALWAYS" : "NEVER"));
|
||||
if (nms.getMinorVersion() >= 9) ScoreboardTeam_setCollisionRule.invoke(team, Enum.valueOf(EnumTeamPush, String.valueOf(packet.getCollisionRule()).equals("always") ? "ALWAYS" : "NEVER"));
|
||||
}
|
||||
|
||||
private static List<Field> getInstanceFields(Class<?> clazz, Class<?> type) {
|
||||
List<Field> list = new ArrayList<>();
|
||||
for (Field field : clazz.getDeclaredFields()) {
|
||||
if (field.getType() == type && !Modifier.isStatic(field.getModifiers())) {
|
||||
field.setAccessible(true);
|
||||
list.add(field);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package me.neznamy.tab.platforms.bukkit.permission;
|
||||
|
||||
import lombok.Getter;
|
||||
import me.neznamy.tab.api.TabConstants;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@@ -15,6 +16,8 @@ public class Vault extends PermissionPlugin {
|
||||
/** Permission plugin */
|
||||
private final Permission permission;
|
||||
|
||||
@Getter private final String version = "Vault " + super.getVersion();
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters
|
||||
*
|
||||
@@ -38,9 +41,4 @@ public class Vault extends PermissionPlugin {
|
||||
public String getName() {
|
||||
return permission.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return "Vault " + super.getVersion();
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
name: TAB
|
||||
name: @name@
|
||||
version: @version@
|
||||
author: NEZNAMY
|
||||
main: me.neznamy.tab.platforms.bukkit.Main
|
||||
main: me.neznamy.tab.platforms.bukkit.BukkitTAB
|
||||
api-version: 1.13
|
||||
softdepend: [PlaceholderAPI, Vault, LuckPerms, Essentials, LibsDisguises, ProtocolSupport, ViaVersion, floodgate]
|
||||
website: "https://github.com/NEZNAMY/TAB"
|
||||
website: "@website@"
|
||||
description: @description@
|
||||
commands:
|
||||
tab:
|
||||
|
||||
+6
-9
@@ -1,8 +1,9 @@
|
||||
package me.neznamy.tab.platforms.bungeecord;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import me.neznamy.tab.api.TabAPI;
|
||||
import me.neznamy.tab.api.TabConstants;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.proxy.ProxyPlatform;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.event.ChatEvent;
|
||||
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
|
||||
@@ -14,12 +15,8 @@ import net.md_5.bungee.event.EventHandler;
|
||||
/**
|
||||
* The core for BungeeCord forwarding events into all enabled features
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
public class BungeeEventListener implements Listener {
|
||||
|
||||
/** Reference to BungeeCord platform implementation */
|
||||
private final BungeePlatform platform;
|
||||
|
||||
/**
|
||||
* Disconnect event listener to forward the event to all features
|
||||
*
|
||||
@@ -27,7 +24,7 @@ public class BungeeEventListener implements Listener {
|
||||
* disconnect event
|
||||
*/
|
||||
@EventHandler
|
||||
public void onQuit(PlayerDisconnectEvent e){
|
||||
public void onQuit(PlayerDisconnectEvent e) {
|
||||
if (TabAPI.getInstance().isPluginDisabled()) return;
|
||||
TabAPI.getInstance().getThreadManager().runTask(() ->
|
||||
TabAPI.getInstance().getFeatureManager().onQuit(TabAPI.getInstance().getPlayer(e.getPlayer().getUniqueId())));
|
||||
@@ -40,7 +37,7 @@ public class BungeeEventListener implements Listener {
|
||||
* switch event
|
||||
*/
|
||||
@EventHandler
|
||||
public void onSwitch(ServerSwitchEvent e){
|
||||
public void onSwitch(ServerSwitchEvent e) {
|
||||
if (TabAPI.getInstance().isPluginDisabled()) return;
|
||||
TabAPI.getInstance().getThreadManager().runTask(() -> {
|
||||
if (TabAPI.getInstance().getPlayer(e.getPlayer().getUniqueId()) == null) {
|
||||
@@ -71,11 +68,11 @@ public class BungeeEventListener implements Listener {
|
||||
* plugin message event
|
||||
*/
|
||||
@EventHandler
|
||||
public void on(PluginMessageEvent event){
|
||||
public void on(PluginMessageEvent event) {
|
||||
if (!event.getTag().equals(TabConstants.PLUGIN_MESSAGE_CHANNEL_NAME)) return;
|
||||
if (event.getReceiver() instanceof ProxiedPlayer) {
|
||||
event.setCancelled(true);
|
||||
platform.getPluginMessageHandler().onPluginMessage(
|
||||
((ProxyPlatform)TAB.getInstance().getPlatform()).getPluginMessageHandler().onPluginMessage(
|
||||
((ProxiedPlayer) event.getReceiver()).getUniqueId(), event.getData());
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -165,7 +165,7 @@ public class BungeePacketBuilder extends PacketBuilder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketPlayOutScoreboardDisplayObjective readDisplayObjective(Object bungeePacket){
|
||||
public PacketPlayOutScoreboardDisplayObjective readDisplayObjective(Object bungeePacket) {
|
||||
return new PacketPlayOutScoreboardDisplayObjective(((ScoreboardDisplay) bungeePacket).getPosition(), ((ScoreboardDisplay) bungeePacket).getName());
|
||||
}
|
||||
}
|
||||
+5
-7
@@ -6,6 +6,7 @@ import io.netty.channel.ChannelDuplexHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import me.neznamy.tab.api.TabFeature;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
@@ -35,6 +36,8 @@ public class BungeePipelineInjector extends PipelineInjector {
|
||||
private final Class<? extends DefinedPacket>[] extraPacketClasses = new Class[]{Team.class, ScoreboardDisplay.class, ScoreboardObjective.class};
|
||||
private final Supplier<DefinedPacket>[] extraPacketSuppliers = new Supplier[]{Team::new, ScoreboardDisplay::new, ScoreboardObjective::new};
|
||||
|
||||
@Getter private final Function<TabPlayer, ChannelDuplexHandler> channelFunction = BungeeChannelDuplexHandler::new;
|
||||
|
||||
/**
|
||||
* Constructs new instance of the feature
|
||||
*/
|
||||
@@ -42,11 +45,6 @@ public class BungeePipelineInjector extends PipelineInjector {
|
||||
super("inbound-boss");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function<TabPlayer, ChannelDuplexHandler> getChannelFunction() {
|
||||
return byteBufDeserialization ? DeserializableBungeeChannelDuplexHandler::new : BungeeChannelDuplexHandler::new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom channel duplex handler override
|
||||
*/
|
||||
@@ -86,7 +84,7 @@ public class BungeePipelineInjector extends PipelineInjector {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} catch (Exception | NoSuchMethodError e){
|
||||
} catch (Exception | NoSuchMethodError e) {
|
||||
TAB.getInstance().getErrorManager().printError("An error occurred when analyzing packets for player " + player.getName() + " with client version " + player.getVersion().getFriendlyName(), e);
|
||||
}
|
||||
try {
|
||||
@@ -102,7 +100,7 @@ public class BungeePipelineInjector extends PipelineInjector {
|
||||
* @param packet
|
||||
* packet to modify
|
||||
*/
|
||||
private void modifyPlayers(Team packet){
|
||||
private void modifyPlayers(Team packet) {
|
||||
if (packet.getMode() == 1 || packet.getMode() == 2 || packet.getMode() == 4) return;
|
||||
Collection<String> col = Lists.newArrayList(packet.getPlayers());
|
||||
for (TabPlayer p : TAB.getInstance().getOnlinePlayers()) {
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package me.neznamy.tab.platforms.bungeecord;
|
||||
|
||||
import com.imaginarycode.minecraft.redisbungee.RedisBungeeAPI;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import me.neznamy.tab.api.TabConstants;
|
||||
import me.neznamy.tab.shared.features.PipelineInjector;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.features.redis.RedisSupport;
|
||||
import me.neznamy.tab.shared.proxy.ProxyPlatform;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
@@ -14,25 +15,18 @@ import org.jetbrains.annotations.Nullable;
|
||||
/**
|
||||
* BungeeCord implementation of Platform
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
public class BungeePlatform extends ProxyPlatform {
|
||||
|
||||
/**
|
||||
* Constructs new instance with BungeeCord packet builder
|
||||
*/
|
||||
public BungeePlatform() {
|
||||
super(new BungeePacketBuilder());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable PipelineInjector getPipelineInjector() {
|
||||
return new BungeePipelineInjector();
|
||||
}
|
||||
private final Plugin plugin;
|
||||
@Getter private final BungeePacketBuilder packetBuilder = new BungeePacketBuilder();
|
||||
@Getter private final BungeePipelineInjector pipelineInjector = new BungeePipelineInjector();
|
||||
|
||||
@Override
|
||||
public @Nullable RedisSupport getRedisSupport() {
|
||||
if (ProxyServer.getInstance().getPluginManager().getPlugin(TabConstants.Plugin.REDIS_BUNGEE) != null) {
|
||||
if (RedisBungeeAPI.getRedisBungeeApi() != null) {
|
||||
return new RedisBungeeSupport();
|
||||
return new RedisBungeeSupport(plugin);
|
||||
} else {
|
||||
TAB.getInstance().getErrorManager().criticalError("RedisBungee plugin was detected, but it returned null API instance. Disabling hook.", null);
|
||||
}
|
||||
|
||||
+4
-5
@@ -22,18 +22,17 @@ import net.md_5.bungee.api.plugin.TabExecutor;
|
||||
/**
|
||||
* Main class for BungeeCord platform
|
||||
*/
|
||||
public class Main extends Plugin {
|
||||
public class BungeeTAB extends Plugin {
|
||||
|
||||
@Override
|
||||
public void onEnable(){
|
||||
public void onEnable() {
|
||||
if (!ReflectionUtils.classExists("net.md_5.bungee.protocol.packet.PlayerListItemUpdate")) {
|
||||
getLogger().info(EnumChatFormat.color("&cThe plugin requires BungeeCord build #1671 and up (or an equivalent fork) to work."));
|
||||
return;
|
||||
}
|
||||
BungeePlatform platform = new BungeePlatform();
|
||||
ProxyServer.getInstance().registerChannel(TabConstants.PLUGIN_MESSAGE_CHANNEL_NAME);
|
||||
TAB.setInstance(new TAB(platform, ProtocolVersion.PROXY, getProxy().getVersion(), getDataFolder(), getLogger()));
|
||||
getProxy().getPluginManager().registerListener(this, new BungeeEventListener(platform));
|
||||
TAB.setInstance(new TAB(new BungeePlatform(this), ProtocolVersion.PROXY, getProxy().getVersion(), getDataFolder(), getLogger()));
|
||||
getProxy().getPluginManager().registerListener(this, new BungeeEventListener());
|
||||
getProxy().getPluginManager().registerCommand(this, new BTABCommand());
|
||||
TAB.getInstance().load();
|
||||
Metrics metrics = new Metrics(this, 10535);
|
||||
@@ -150,6 +150,6 @@ public class BungeeTabPlayer extends ProxyTabPlayer {
|
||||
public void sendPluginMessage(byte[] message) {
|
||||
if (getPlayer().getServer() == null) return;
|
||||
getPlayer().getServer().sendData(TabConstants.PLUGIN_MESSAGE_CHANNEL_NAME, message);
|
||||
TAB.getInstance().getCPUManager().packetSent("Plugin Message (" + new String(message) + ")");
|
||||
TAB.getInstance().getCPUManager().packetSent("Plugin Message");
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -6,6 +6,7 @@ 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;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
|
||||
/**
|
||||
@@ -16,8 +17,8 @@ public class RedisBungeeSupport extends RedisSupport implements Listener {
|
||||
/**
|
||||
* Constructs new instance, registers listeners and overrides placeholders
|
||||
*/
|
||||
public RedisBungeeSupport() {
|
||||
ProxyServer.getInstance().getPluginManager().registerListener(ProxyServer.getInstance().getPluginManager().getPlugin("TAB"), this);
|
||||
public RedisBungeeSupport(Plugin plugin) {
|
||||
ProxyServer.getInstance().getPluginManager().registerListener(plugin, this);
|
||||
RedisBungeeAPI.getRedisBungeeApi().registerPubSubChannels(TabConstants.REDIS_CHANNEL_NAME);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: TAB
|
||||
main: me.neznamy.tab.platforms.bungeecord.Main
|
||||
name: @name@
|
||||
main: me.neznamy.tab.platforms.bungeecord.BungeeTAB
|
||||
version: @version@
|
||||
author: NEZNAMY
|
||||
description: @description@
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# Project properties - we put these here so they can be modified without causing a recompile of the build scripts
|
||||
projectVersion=3.2.5
|
||||
|
||||
# Gradle properties
|
||||
org.gradle.daemon=true
|
||||
org.gradle.configureondemand=true
|
||||
|
||||
@@ -7,7 +7,6 @@ netty = "4.1.86.Final"
|
||||
jsonSimple = "1.1.1"
|
||||
snakeyaml = "1.33"
|
||||
yamlAssist = "1.0.5"
|
||||
gson = "2.10"
|
||||
slf4j = "2.0.6"
|
||||
minimessage = "4.12.0"
|
||||
|
||||
@@ -21,9 +20,10 @@ event = "3.0.0"
|
||||
# Platforms
|
||||
bukkit = "1.16.5-R0.1-SNAPSHOT"
|
||||
bungeecord = "1.19-R0.1-SNAPSHOT"
|
||||
krypton = "98fe09edf8" # Krypton uses commit-based versioning
|
||||
krypton = "a81b4baaed" # Krypton uses commit-based versioning
|
||||
velocity = "3.1.2-SNAPSHOT"
|
||||
sponge = "8.1.0"
|
||||
sponge7 = "7.4.0"
|
||||
sponge8 = "8.1.0"
|
||||
|
||||
# Platform extras
|
||||
placeholderapi = "2.11.2"
|
||||
@@ -32,6 +32,7 @@ via = "4.5.1"
|
||||
authlib = "1.5.25"
|
||||
bstats = "3.0.0"
|
||||
redisBungee = "0.10.1"
|
||||
spark = "0.1-SNAPSHOT"
|
||||
|
||||
# Plugins
|
||||
shadow = "7.1.2"
|
||||
@@ -44,7 +45,6 @@ netty = { group = "io.netty", name = "netty-all", version.ref = "netty" }
|
||||
jsonSimple = { group = "com.googlecode.json-simple", name = "json-simple", version.ref = "jsonSimple" }
|
||||
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" }
|
||||
@@ -64,7 +64,8 @@ krypton-api = { group = "org.kryptonmc", name = "krypton-api", version.ref = "kr
|
||||
krypton-server = { group = "org.kryptonmc", name = "krypton-server", version.ref = "krypton" }
|
||||
krypton-annotationProcessor = { group = "org.kryptonmc", name = "krypton-annotation-processor", version.ref = "krypton" }
|
||||
velocity = { group = "com.velocitypowered", name = "velocity-api", version.ref = "velocity" }
|
||||
sponge = { group = "org.spongepowered", name = "spongeapi", version.ref = "sponge" }
|
||||
sponge7 = { group = "org.spongepowered", name = "spongeapi", version.ref = "sponge7" }
|
||||
sponge8 = { group = "org.spongepowered", name = "spongeapi", version.ref = "sponge8" }
|
||||
|
||||
# Platform extras
|
||||
placeholderapi = { group = "me.clip", name = "placeholderapi", version.ref = "placeholderapi" }
|
||||
@@ -72,11 +73,13 @@ 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" }
|
||||
redisBungee = { group = "com.github.limework.redisbungee", name = "RedisBungee-Bungee", version.ref = "redisBungee" }
|
||||
spark = { group = "me.lucko", name = "spark-api", version.ref = "spark" }
|
||||
|
||||
# Metrics
|
||||
bstats-bukkit = { group = "org.bstats", name = "bstats-bukkit", version.ref = "bstats" }
|
||||
bstats-bungeecord = { group = "org.bstats", name = "bstats-bungeecord", version.ref = "bstats" }
|
||||
bstats-velocity = { group = "org.bstats", name = "bstats-velocity", version.ref = "bstats" }
|
||||
bstats-sponge = { group = "org.bstats", name = "bstats-sponge", version.ref = "bstats" }
|
||||
|
||||
# Plugins
|
||||
plugin-shadow = { group = "gradle.plugin.com.github.johnrengelman", name = "shadow", version.ref = "shadow" }
|
||||
|
||||
@@ -9,7 +9,8 @@ val platforms = setOf(
|
||||
rootProject.projects.bungeecord,
|
||||
rootProject.projects.krypton,
|
||||
rootProject.projects.velocity,
|
||||
//rootProject.projects.sponge
|
||||
rootProject.projects.sponge7,
|
||||
rootProject.projects.sponge8
|
||||
).map { it.dependencyProject }
|
||||
|
||||
tasks {
|
||||
@@ -17,7 +18,7 @@ tasks {
|
||||
archiveFileName.set("TAB-${project.version}.jar")
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
platforms.forEach {
|
||||
val shadowJarTask = it.tasks.named<ShadowJar>("shadowJar").forUseAtConfigurationTime().get()
|
||||
val shadowJarTask = it.tasks.named<ShadowJar>("shadowJar").get()
|
||||
dependsOn(shadowJarTask)
|
||||
dependsOn(it.tasks.withType<Jar>())
|
||||
from(zipTree(shadowJarTask.archiveFile))
|
||||
|
||||
@@ -17,12 +17,12 @@ dependencies {
|
||||
exclude("org.kryptonmc", "serialization-nbt")
|
||||
}
|
||||
compileOnly(libs.kotlin.stdlib)
|
||||
compileOnly(libs.via)
|
||||
compileOnly(libs.spark)
|
||||
kapt(libs.krypton.annotationProcessor)
|
||||
}
|
||||
|
||||
tasks {
|
||||
compileKotlin {
|
||||
compilerOptions.jvmTarget.set(JvmTarget.JVM_17)
|
||||
compilerOptions.jvmTarget.set(JvmTarget.JVM_1_8)
|
||||
}
|
||||
}
|
||||
@@ -4,20 +4,20 @@ import me.neznamy.tab.shared.TAB
|
||||
import org.kryptonmc.api.entity.player.Player
|
||||
import org.kryptonmc.api.event.Listener
|
||||
import org.kryptonmc.api.event.command.CommandExecuteEvent
|
||||
import org.kryptonmc.api.event.player.JoinEvent
|
||||
import org.kryptonmc.api.event.player.QuitEvent
|
||||
import org.kryptonmc.api.event.player.PlayerJoinEvent
|
||||
import org.kryptonmc.api.event.player.PlayerQuitEvent
|
||||
|
||||
class KryptonEventListener(private val plugin: Main) {
|
||||
|
||||
@Listener
|
||||
fun onJoin(event: JoinEvent) {
|
||||
fun onJoin(event: PlayerJoinEvent) {
|
||||
TAB.getInstance().cpuManager.runTask {
|
||||
TAB.getInstance().featureManager.onJoin(KryptonTabPlayer(event.player, plugin.getProtocolVersion(event.player)))
|
||||
}
|
||||
}
|
||||
|
||||
@Listener
|
||||
fun onQuit(event: QuitEvent) {
|
||||
fun onQuit(event: PlayerQuitEvent) {
|
||||
TAB.getInstance().cpuManager.runTask {
|
||||
TAB.getInstance().featureManager.onQuit(TAB.getInstance().getPlayer(event.player.uuid))
|
||||
}
|
||||
|
||||
+48
-50
@@ -1,69 +1,67 @@
|
||||
package me.neznamy.tab.platforms.krypton
|
||||
|
||||
import me.lucko.spark.api.Spark
|
||||
import me.lucko.spark.api.statistic.StatisticWindow.*
|
||||
import me.neznamy.tab.api.placeholder.PlaceholderManager
|
||||
import me.neznamy.tab.shared.placeholders.PlaceholderRegistry
|
||||
import me.neznamy.tab.shared.placeholders.UniversalPlaceholderRegistry
|
||||
import org.kryptonmc.api.entity.player.Player
|
||||
import java.math.RoundingMode
|
||||
import java.text.NumberFormat
|
||||
import kotlin.math.ceil
|
||||
|
||||
class KryptonPlaceholderRegistry(private val plugin: Main) : PlaceholderRegistry {
|
||||
class KryptonPlaceholderRegistry(private val plugin: Main) : UniversalPlaceholderRegistry() {
|
||||
|
||||
override fun registerPlaceholders(manager: PlaceholderManager) {
|
||||
// Built-in stuff
|
||||
manager.registerPlayerPlaceholder("%displayname%", 500) { (it.player as Player).displayName }
|
||||
manager.registerPlayerPlaceholder("%health%", 100) { ceil((it.player as Player).health) }
|
||||
|
||||
// // TPS
|
||||
// val tps = plugin.server.spark.tps()!!
|
||||
// manager.registerServerPlaceholder("%tps_5s%", 1000) { format(tps.poll(TicksPerSecond.SECONDS_5)) }
|
||||
// manager.registerServerPlaceholder("%tps_10s%", 1000) { format(tps.poll(TicksPerSecond.SECONDS_10)) }
|
||||
// manager.registerServerPlaceholder("%tps_1m%", 1000) { format(tps.poll(TicksPerSecond.MINUTES_1)) }
|
||||
// manager.registerServerPlaceholder("%tps_5m%", 1000) { format(tps.poll(TicksPerSecond.MINUTES_5)) }
|
||||
// manager.registerServerPlaceholder("%tps_15m%", 1000) { format(tps.poll(TicksPerSecond.MINUTES_15)) }
|
||||
//
|
||||
// // MSPT
|
||||
// val mspt = plugin.server.spark.mspt()!!
|
||||
// manager.registerServerPlaceholder("%mspt_min_10s%", 1000) { formatMSPT(mspt.poll(MillisPerTick.SECONDS_10).min()) }
|
||||
// manager.registerServerPlaceholder("%mspt_max_10s%", 1000) { formatMSPT(mspt.poll(MillisPerTick.SECONDS_10).max()) }
|
||||
// manager.registerServerPlaceholder("%mspt_mean_10s%", 1000) { formatMSPT(mspt.poll(MillisPerTick.SECONDS_10).mean()) }
|
||||
// manager.registerServerPlaceholder("%mspt_median_10s%", 1000) { formatMSPT(mspt.poll(MillisPerTick.SECONDS_10).median()) }
|
||||
// manager.registerServerPlaceholder("%mspt_percentile95_10s%", 1000) {
|
||||
// formatMSPT(mspt.poll(MillisPerTick.SECONDS_10).percentile95th())
|
||||
// }
|
||||
// manager.registerServerPlaceholder("%mspt_min_1m%", 1000) { formatMSPT(mspt.poll(MillisPerTick.MINUTES_1).min()) }
|
||||
// manager.registerServerPlaceholder("%mspt_max_1m%", 1000) { formatMSPT(mspt.poll(MillisPerTick.MINUTES_1).max()) }
|
||||
// manager.registerServerPlaceholder("%mspt_mean_1m%", 1000) { formatMSPT(mspt.poll(MillisPerTick.MINUTES_1).mean()) }
|
||||
// manager.registerServerPlaceholder("%mspt_median_1m%", 1000) { formatMSPT(mspt.poll(MillisPerTick.MINUTES_1).median()) }
|
||||
// manager.registerServerPlaceholder("%mspt_percentile95_1m%", 1000) {
|
||||
// formatMSPT(mspt.poll(MillisPerTick.SECONDS_10).percentile95th())
|
||||
// }
|
||||
//
|
||||
// // CPU process
|
||||
// val process = plugin.server.spark.cpuProcess()
|
||||
// manager.registerServerPlaceholder("%cpu_process_10s%", 1000) { format(process.poll(CpuUsage.SECONDS_10)) }
|
||||
// manager.registerServerPlaceholder("%cpu_process_1m%", 1000) { format(process.poll(CpuUsage.MINUTES_1)) }
|
||||
// manager.registerServerPlaceholder("%cpu_process_15m%", 1000) { format(process.poll(CpuUsage.MINUTES_15)) }
|
||||
//
|
||||
// // CPU system
|
||||
// val system = plugin.server.spark.cpuSystem()
|
||||
// manager.registerServerPlaceholder("%cpu_system_10s%", 1000) { format(system.poll(CpuUsage.SECONDS_10)) }
|
||||
// manager.registerServerPlaceholder("%cpu_system_1m%", 1000) { format(system.poll(CpuUsage.MINUTES_1)) }
|
||||
// manager.registerServerPlaceholder("%cpu_system_15m%", 1000) { format(system.poll(CpuUsage.MINUTES_15)) }
|
||||
// Spark placeholders, registered if Spark is present
|
||||
registerSparkPlaceholders(manager)
|
||||
super.registerPlaceholders(manager)
|
||||
}
|
||||
|
||||
private fun format(value: Double): String = TWO_DECIMAL_PLACES.format(value)
|
||||
private fun registerSparkPlaceholders(manager: PlaceholderManager) {
|
||||
val spark = plugin.server.servicesManager.provide(Spark::class.java) ?: return
|
||||
|
||||
private fun formatMSPT(value: Double): String = TWO_DECIMAL_PLACES_ROUNDING_DOWN.format(value)
|
||||
|
||||
companion object {
|
||||
|
||||
private val TWO_DECIMAL_PLACES = NumberFormat.getInstance().apply {
|
||||
maximumFractionDigits = 2
|
||||
// TPS
|
||||
val tps = spark.tps()
|
||||
if (tps != null) {
|
||||
manager.registerServerPlaceholder("%tps_5s%", 1000) { format(tps.poll(TicksPerSecond.SECONDS_5)) }
|
||||
manager.registerServerPlaceholder("%tps_10s%", 1000) { format(tps.poll(TicksPerSecond.SECONDS_10)) }
|
||||
manager.registerServerPlaceholder("%tps_1m%", 1000) { format(tps.poll(TicksPerSecond.MINUTES_1)) }
|
||||
manager.registerServerPlaceholder("%tps_5m%", 1000) { format(tps.poll(TicksPerSecond.MINUTES_5)) }
|
||||
manager.registerServerPlaceholder("%tps_15m%", 1000) { format(tps.poll(TicksPerSecond.MINUTES_15)) }
|
||||
}
|
||||
private val TWO_DECIMAL_PLACES_ROUNDING_DOWN = NumberFormat.getInstance().apply {
|
||||
roundingMode = RoundingMode.DOWN
|
||||
maximumFractionDigits = 2
|
||||
|
||||
// MSPT
|
||||
val mspt = spark.mspt()
|
||||
if (mspt != null) {
|
||||
manager.registerServerPlaceholder("%mspt_min_10s%", 1000) { format(mspt.poll(MillisPerTick.SECONDS_10).min()) }
|
||||
manager.registerServerPlaceholder("%mspt_max_10s%", 1000) { format(mspt.poll(MillisPerTick.SECONDS_10).max()) }
|
||||
manager.registerServerPlaceholder("%mspt_mean_10s%", 1000) { format(mspt.poll(MillisPerTick.SECONDS_10).mean()) }
|
||||
manager.registerServerPlaceholder("%mspt_median_10s%", 1000) { format(mspt.poll(MillisPerTick.SECONDS_10).median()) }
|
||||
manager.registerServerPlaceholder("%mspt_percentile95_10s%", 1000) {
|
||||
format(mspt.poll(MillisPerTick.SECONDS_10).percentile95th())
|
||||
}
|
||||
|
||||
manager.registerServerPlaceholder("%mspt_min_1m%", 1000) { format(mspt.poll(MillisPerTick.MINUTES_1).min()) }
|
||||
manager.registerServerPlaceholder("%mspt_max_1m%", 1000) { format(mspt.poll(MillisPerTick.MINUTES_1).max()) }
|
||||
manager.registerServerPlaceholder("%mspt_mean_1m%", 1000) { format(mspt.poll(MillisPerTick.MINUTES_1).mean()) }
|
||||
manager.registerServerPlaceholder("%mspt_median_1m%", 1000) { format(mspt.poll(MillisPerTick.MINUTES_1).median()) }
|
||||
manager.registerServerPlaceholder("%mspt_percentile95_1m%", 1000) {
|
||||
format(mspt.poll(MillisPerTick.SECONDS_10).percentile95th())
|
||||
}
|
||||
}
|
||||
|
||||
// CPU process
|
||||
val process = spark.cpuProcess()
|
||||
manager.registerServerPlaceholder("%cpu_process_10s%", 1000) { format(process.poll(CpuUsage.SECONDS_10)) }
|
||||
manager.registerServerPlaceholder("%cpu_process_1m%", 1000) { format(process.poll(CpuUsage.MINUTES_1)) }
|
||||
manager.registerServerPlaceholder("%cpu_process_15m%", 1000) { format(process.poll(CpuUsage.MINUTES_15)) }
|
||||
|
||||
// CPU system
|
||||
val system = spark.cpuSystem()
|
||||
manager.registerServerPlaceholder("%cpu_system_10s%", 1000) { format(system.poll(CpuUsage.SECONDS_10)) }
|
||||
manager.registerServerPlaceholder("%cpu_system_1m%", 1000) { format(system.poll(CpuUsage.MINUTES_1)) }
|
||||
manager.registerServerPlaceholder("%cpu_system_15m%", 1000) { format(system.poll(CpuUsage.MINUTES_15)) }
|
||||
}
|
||||
}
|
||||
@@ -1,54 +1,32 @@
|
||||
package me.neznamy.tab.platforms.krypton
|
||||
|
||||
import me.neznamy.tab.api.TabFeature
|
||||
import me.neznamy.tab.api.protocol.PacketBuilder
|
||||
import me.neznamy.tab.platforms.krypton.features.unlimitedtags.KryptonNameTagX
|
||||
import me.neznamy.tab.shared.TAB
|
||||
import me.neznamy.tab.shared.backend.BackendPlatform
|
||||
import me.neznamy.tab.shared.features.PipelineInjector
|
||||
import me.neznamy.tab.shared.features.TabExpansion
|
||||
import me.neznamy.tab.shared.features.nametags.NameTag
|
||||
import me.neznamy.tab.shared.permission.LuckPerms
|
||||
import me.neznamy.tab.shared.permission.None
|
||||
import me.neznamy.tab.shared.permission.PermissionPlugin
|
||||
import me.neznamy.tab.shared.placeholders.UniversalPlaceholderRegistry
|
||||
import net.kyori.adventure.text.Component
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer
|
||||
|
||||
class KryptonPlatform(private val plugin: Main) : BackendPlatform(KryptonPacketBuilder) {
|
||||
class KryptonPlatform(private val plugin: Main) : BackendPlatform() {
|
||||
|
||||
private val server = plugin.server
|
||||
|
||||
override fun detectPermissionPlugin(): PermissionPlugin {
|
||||
if (server.pluginManager.isLoaded("luckperms")) return LuckPerms(getPluginVersion("luckperms"))
|
||||
return None()
|
||||
}
|
||||
private val packetBuilder = KryptonPacketBuilder
|
||||
|
||||
override fun sendConsoleMessage(message: String, translateColors: Boolean) {
|
||||
val component = if (translateColors) LegacyComponentSerializer.legacyAmpersand().deserialize(message) else Component.text(message)
|
||||
server.console.sendMessage(component)
|
||||
val actualMessage = Component.text().append(Component.text("[TAB] ")).append(component).build()
|
||||
server.console.sendMessage(actualMessage)
|
||||
}
|
||||
|
||||
override fun registerUnknownPlaceholder(identifier: String) {
|
||||
val manager = TAB.getInstance().placeholderManager
|
||||
if (identifier.startsWith("%rel_")) {
|
||||
// One day, when PlaceholderAPI v3 is a thing, this will work. One day...
|
||||
manager.registerRelationalPlaceholder(identifier, manager.getRelationalRefresh(identifier)) { _, _ -> "" }
|
||||
return
|
||||
}
|
||||
val serverIntervals = manager.serverPlaceholderRefreshIntervals
|
||||
val playerIntervals = manager.playerPlaceholderRefreshIntervals
|
||||
if (serverIntervals.containsKey(identifier)) {
|
||||
manager.registerServerPlaceholder(identifier, serverIntervals.get(identifier)!!) { identifier }
|
||||
return
|
||||
}
|
||||
if (playerIntervals.containsKey(identifier)) {
|
||||
manager.registerPlayerPlaceholder(identifier, playerIntervals.get(identifier)!!) { identifier }
|
||||
return
|
||||
}
|
||||
manager.registerPlayerPlaceholder(identifier, manager.defaultRefresh) { identifier }
|
||||
TAB.getInstance().placeholderManager.registerServerPlaceholder(identifier, -1) { identifier }
|
||||
}
|
||||
|
||||
override fun getPluginVersion(plugin: String): String? = server.pluginManager.getPlugin(plugin)?.description?.version
|
||||
override fun getPluginVersion(plugin: String): String? = server.pluginManager.getPlugin(plugin.lowercase())?.description?.version
|
||||
|
||||
override fun loadPlayers() {
|
||||
server.players.forEach { TAB.getInstance().addPlayer(KryptonTabPlayer(it, plugin.getProtocolVersion(it))) }
|
||||
@@ -56,7 +34,6 @@ class KryptonPlatform(private val plugin: Main) : BackendPlatform(KryptonPacketB
|
||||
|
||||
override fun registerPlaceholders() {
|
||||
KryptonPlaceholderRegistry(plugin).registerPlaceholders(TAB.getInstance().placeholderManager)
|
||||
UniversalPlaceholderRegistry().registerPlaceholders(TAB.getInstance().placeholderManager)
|
||||
}
|
||||
|
||||
override fun getPipelineInjector(): PipelineInjector {
|
||||
@@ -78,4 +55,8 @@ class KryptonPlatform(private val plugin: Main) : BackendPlatform(KryptonPacketB
|
||||
override fun getPerWorldPlayerlist(): TabFeature? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun getPacketBuilder(): PacketBuilder {
|
||||
return packetBuilder
|
||||
}
|
||||
}
|
||||
@@ -73,7 +73,7 @@ class KryptonTabPlayer(
|
||||
|
||||
override fun getPlayer(): Player = delegate
|
||||
|
||||
override fun isOnline(): Boolean = delegate.isOnline
|
||||
override fun isOnline(): Boolean = delegate.isOnline()
|
||||
|
||||
override fun isVanished(): Boolean = false
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package me.neznamy.tab.platforms.krypton
|
||||
|
||||
import com.google.inject.Inject
|
||||
import com.viaversion.viaversion.api.Via
|
||||
import me.neznamy.tab.api.ProtocolVersion
|
||||
import me.neznamy.tab.api.TabConstants
|
||||
import me.neznamy.tab.api.TabPlayer
|
||||
@@ -28,12 +27,15 @@ import java.nio.file.Path
|
||||
* Main class for Krypton platform
|
||||
*/
|
||||
@Plugin(
|
||||
"tab",
|
||||
"TAB",
|
||||
TabConstants.PLUGIN_ID,
|
||||
TabConstants.PLUGIN_NAME,
|
||||
TabConstants.PLUGIN_VERSION,
|
||||
"An all-in-one solution that works",
|
||||
TabConstants.PLUGIN_DESCRIPTION,
|
||||
["NEZNAMY", "BomBardyGamer"],
|
||||
[Dependency("luckperms", true), Dependency("viaversion", true)]
|
||||
[
|
||||
Dependency("luckperms", true),
|
||||
Dependency("viaversion", true)
|
||||
]
|
||||
)
|
||||
class Main @Inject constructor(
|
||||
val server: Server,
|
||||
@@ -74,31 +76,10 @@ class Main @Inject constructor(
|
||||
}
|
||||
|
||||
fun getProtocolVersion(player: Player): Int {
|
||||
if (server.pluginManager.isLoaded("viaversion")) return getViaProtocolVersion(player)
|
||||
return TAB.getInstance().serverVersion.networkId
|
||||
}
|
||||
|
||||
private fun getViaProtocolVersion(player: Player, retryLevel: Int = 0): Int {
|
||||
try {
|
||||
if (retryLevel == 10) {
|
||||
TAB.getInstance().debug("Failed to get protocol version of ${player.profile.name} after 10 retries")
|
||||
return TAB.getInstance().serverVersion.networkId
|
||||
}
|
||||
val version = Via.getAPI().getPlayerVersion(player)
|
||||
if (version == -1) {
|
||||
Thread.sleep(5)
|
||||
return getViaProtocolVersion(player, retryLevel + 1)
|
||||
}
|
||||
TAB.getInstance().debug("ViaVersion returned protocol version $version for ${player.profile.name}")
|
||||
return version
|
||||
} catch (exception: InterruptedException) {
|
||||
Thread.currentThread().interrupt()
|
||||
return -1
|
||||
} catch (exception: Throwable) {
|
||||
TAB.getInstance().errorManager.printError("Failed to get protocol version of ${player.profile.name} using ViaVersion " +
|
||||
"v${server.pluginManager.getPlugin("viaversion")?.description?.version}")
|
||||
return TAB.getInstance().serverVersion.networkId
|
||||
if (server.pluginManager.isLoaded(TabConstants.Plugin.VIAVERSION.lowercase())) {
|
||||
return TAB.getInstance().platform.getProtocolVersionVia(player.uuid, player.profile.name, 0)
|
||||
}
|
||||
return TAB.getInstance().serverVersion.networkId
|
||||
}
|
||||
|
||||
class KryptonTABCommand : SimpleCommand {
|
||||
|
||||
+15
-4
@@ -2,18 +2,29 @@ package me.neznamy.tab.platforms.krypton.features.unlimitedtags
|
||||
|
||||
import me.neznamy.tab.api.TabConstants
|
||||
import me.neznamy.tab.shared.TAB
|
||||
import org.kryptonmc.api.entity.player.Player
|
||||
import org.kryptonmc.api.event.Listener
|
||||
import org.kryptonmc.api.event.player.PerformActionEvent
|
||||
import org.kryptonmc.api.event.player.action.PlayerStartSneakingEvent
|
||||
import org.kryptonmc.api.event.player.action.PlayerStopSneakingEvent
|
||||
|
||||
class EventListener(private val feature: KryptonNameTagX) {
|
||||
|
||||
@Listener
|
||||
fun onSneak(event: PerformActionEvent) {
|
||||
val player = TAB.getInstance().getPlayer(event.player.uuid)
|
||||
fun onStartSneak(event: PlayerStartSneakingEvent) {
|
||||
onSneak(event.player, true)
|
||||
}
|
||||
|
||||
@Listener
|
||||
fun onStopSneak(event: PlayerStopSneakingEvent) {
|
||||
onSneak(event.player, false)
|
||||
}
|
||||
|
||||
private fun onSneak(eventPlayer: Player, sneaking: Boolean) {
|
||||
val player = TAB.getInstance().getPlayer(eventPlayer.uuid)
|
||||
if (player == null || feature.isPlayerDisabled(player)) return
|
||||
|
||||
TAB.getInstance().threadManager.runMeasuredTask(feature, TabConstants.CpuUsageCategory.PLAYER_SNEAK) {
|
||||
feature.getArmorStandManager(player)!!.sneak(event.action == PerformActionEvent.Action.START_SNEAKING)
|
||||
feature.getArmorStandManager(player)!!.sneak(sneaking)
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -46,7 +46,7 @@ class KryptonArmorStand(
|
||||
}
|
||||
|
||||
override fun sendTeleportPacket(viewer: TabPlayer) {
|
||||
viewer.sendPacket(PacketOutTeleportEntity(entityId, player.position.x, getArmorStandYFor(viewer), player.position.z, 0F, 0F, false))
|
||||
viewer.sendPacket(PacketOutTeleportEntity(entityId, player.position.x, getArmorStandYFor(viewer), player.position.z, 0, 0, false))
|
||||
}
|
||||
|
||||
private fun getSpawnPackets(viewer: TabPlayer): Array<Packet> {
|
||||
@@ -54,7 +54,7 @@ class KryptonArmorStand(
|
||||
val data = createMetadata(property.getFormat(viewer), viewer)
|
||||
return arrayOf(
|
||||
PacketOutSpawnEntity(entityId, uuid, KryptonEntityTypes.ARMOR_STAND, player.position.x, getArmorStandYFor(viewer),
|
||||
player.position.z, 0F, 0F, 0F, 0, 0, 0, 0),
|
||||
player.position.z, 0, 0, 0, 0, 0, 0, 0),
|
||||
PacketOutSetEntityMetadata(entityId, data.collectAll())
|
||||
)
|
||||
}
|
||||
|
||||
+2
-7
@@ -9,9 +9,7 @@ import me.neznamy.tab.shared.backend.features.unlimitedtags.BackendArmorStandMan
|
||||
import me.neznamy.tab.shared.backend.features.unlimitedtags.BackendNameTagX
|
||||
import org.kryptonmc.api.entity.Entity
|
||||
import org.kryptonmc.api.entity.player.Player
|
||||
import org.kryptonmc.api.event.EventFilter
|
||||
import org.kryptonmc.api.event.EventNode
|
||||
import org.kryptonmc.api.event.player.PerformActionEvent
|
||||
import org.kryptonmc.krypton.packet.EntityPacket
|
||||
import org.kryptonmc.krypton.packet.MovementPacket
|
||||
import org.kryptonmc.krypton.packet.`in`.play.PacketInInteract
|
||||
@@ -24,10 +22,7 @@ class KryptonNameTagX(private val plugin: Main) : BackendNameTagX() {
|
||||
private val eventListener = EventListener(this)
|
||||
|
||||
init {
|
||||
val eventNode = EventNode.filteredForEvent("tab_nametagx", EventFilter.ALL) { event ->
|
||||
if (event !is PerformActionEvent) return@filteredForEvent false
|
||||
event.action == PerformActionEvent.Action.START_SNEAKING || event.action == PerformActionEvent.Action.STOP_SNEAKING
|
||||
}
|
||||
val eventNode = EventNode.all("tab_nametagx")
|
||||
plugin.eventNode.addChild(eventNode)
|
||||
eventNode.registerListeners(eventListener)
|
||||
}
|
||||
@@ -99,7 +94,7 @@ class KryptonNameTagX(private val plugin: Main) : BackendNameTagX() {
|
||||
}
|
||||
|
||||
override fun getEntityType(entity: Any): String {
|
||||
return (entity as Entity).type.toString()
|
||||
return (entity as Entity).type.key().value()
|
||||
}
|
||||
|
||||
override fun createArmorStand(asm: BackendArmorStandManager, owner: TabPlayer, lineName: String, yOffset: Double, staticOffset: Boolean): BackendArmorStand {
|
||||
|
||||
+4
-2
@@ -3,7 +3,7 @@ enableFeaturePreview("VERSION_CATALOGS")
|
||||
|
||||
dependencyResolutionManagement {
|
||||
repositories {
|
||||
mavenCentral() // Netty, SnakeYaml, json-simple, Gson, slf4j, Guava, Kyori event, bStats, AuthLib
|
||||
mavenCentral() // Netty, SnakeYaml, json-simple, slf4j, Guava, Kyori event, bStats, AuthLib
|
||||
maven("https://repo.extendedclip.com/content/repositories/placeholderapi/") // PlaceholderAPI
|
||||
maven("https://repo.viaversion.com/") // ViaVersion
|
||||
maven("https://repo.essentialsx.net/releases/") // Essentials
|
||||
@@ -15,6 +15,7 @@ dependencyResolutionManagement {
|
||||
maven("https://repo.purpurmc.org/snapshots") // Purpur, Vault
|
||||
maven("https://repo.papermc.io/repository/maven-public/") // Velocity
|
||||
maven("https://repo.spongepowered.org/repository/maven-public/") // Sponge
|
||||
maven("https://oss.sonatype.org/content/repositories/snapshots/") // Spark
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,5 +36,6 @@ include(":krypton")
|
||||
include(":velocity")
|
||||
include(":bukkit")
|
||||
include(":bungeecord")
|
||||
//include(":sponge")
|
||||
include(":sponge7")
|
||||
include(":sponge8")
|
||||
include(":jar")
|
||||
@@ -8,4 +8,5 @@ dependencies {
|
||||
compileOnlyApi(libs.guava)
|
||||
compileOnlyApi(libs.floodgate)
|
||||
compileOnlyApi(libs.slf4j)
|
||||
compileOnlyApi(libs.via)
|
||||
}
|
||||
@@ -125,7 +125,7 @@ public class CpuManager implements ThreadManager {
|
||||
*
|
||||
* @return cpu usage map of placeholders
|
||||
*/
|
||||
public Map<String, Float> getPlaceholderUsage(){
|
||||
public Map<String, Float> getPlaceholderUsage() {
|
||||
return getUsage(placeholderUsagePrevious);
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ public class CpuManager implements ThreadManager {
|
||||
*
|
||||
* @return cpu usage map of methods
|
||||
*/
|
||||
public Map<String, Float> getMethodUsage(){
|
||||
public Map<String, Float> getMethodUsage() {
|
||||
return getUsage(methodUsagePrevious);
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ public class CpuManager implements ThreadManager {
|
||||
*
|
||||
* @return map of sent packets per feature
|
||||
*/
|
||||
public Map<String, AtomicInteger> getSentPackets(){
|
||||
public Map<String, AtomicInteger> getSentPackets() {
|
||||
return sortByValue1(packetsPrevious);
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ public class CpuManager implements ThreadManager {
|
||||
* map to convert
|
||||
* @return converted and sorted map
|
||||
*/
|
||||
private Map<String, Float> getUsage(Map<String, AtomicLong> map){
|
||||
private Map<String, Float> getUsage(Map<String, AtomicLong> map) {
|
||||
Map<String, Long> nanoMap = new HashMap<>();
|
||||
String key;
|
||||
for (Entry<String, AtomicLong> nanos : map.entrySet()) {
|
||||
@@ -174,7 +174,7 @@ public class CpuManager implements ThreadManager {
|
||||
*
|
||||
* @return map of CPU usage per feature and type
|
||||
*/
|
||||
public Map<String, Map<String, Float>> getFeatureUsage(){
|
||||
public Map<String, Map<String, Float>> getFeatureUsage() {
|
||||
Map<String, Map<String, Long>> total = new HashMap<>();
|
||||
for (Entry<String, Map<String, AtomicLong>> nanos : featureUsagePrevious.entrySet()) {
|
||||
String key = nanos.getKey();
|
||||
@@ -258,7 +258,7 @@ public class CpuManager implements ThreadManager {
|
||||
* map to sort
|
||||
* @return list of keys sorted from the highest map value to lowest
|
||||
*/
|
||||
private <K> List<K> sortKeys(Map<K, Map<String, Long>> map){
|
||||
private <K> List<K> sortKeys(Map<K, Map<String, Long>> map) {
|
||||
Map<K, Long> simplified = new LinkedHashMap<>();
|
||||
for (Entry<K, Map<String, Long>> entry : map.entrySet()) {
|
||||
simplified.put(entry.getKey(), entry.getValue().values().stream().mapToLong(Long::longValue).sum());
|
||||
|
||||
@@ -32,7 +32,7 @@ public class DynamicText implements Property {
|
||||
private final TabPlayer owner;
|
||||
|
||||
/** Raw value as defined in configuration */
|
||||
private String rawValue;
|
||||
@Getter private String originalRawValue;
|
||||
|
||||
/** Raw value assigned via API, null if not set */
|
||||
@Getter private String temporaryValue;
|
||||
@@ -79,8 +79,8 @@ public class DynamicText implements Property {
|
||||
this.listener = listener;
|
||||
this.owner = owner;
|
||||
this.source = source;
|
||||
this.rawValue = (rawValue == null ? "" : rawValue);
|
||||
analyze(this.rawValue);
|
||||
this.originalRawValue = (rawValue == null ? "" : rawValue);
|
||||
analyze(this.originalRawValue);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -137,11 +137,11 @@ public class DynamicText implements Property {
|
||||
* new source of the text
|
||||
*/
|
||||
public void changeRawValue(String newValue, String newSource) {
|
||||
if (rawValue.equals(newValue)) return;
|
||||
rawValue = newValue;
|
||||
if (originalRawValue.equals(newValue)) return;
|
||||
originalRawValue = newValue;
|
||||
source = newSource;
|
||||
if (temporaryValue == null) {
|
||||
analyze(rawValue);
|
||||
analyze(originalRawValue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,20 +161,15 @@ public class DynamicText implements Property {
|
||||
analyze(this.temporaryValue);
|
||||
} else {
|
||||
this.temporaryValue = null;
|
||||
analyze(rawValue);
|
||||
analyze(originalRawValue);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCurrentRawValue() {
|
||||
return temporaryValue != null ? temporaryValue : rawValue;
|
||||
return temporaryValue != null ? temporaryValue : originalRawValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOriginalRawValue() {
|
||||
return rawValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String updateAndGet() {
|
||||
update();
|
||||
|
||||
@@ -110,7 +110,7 @@ public class ErrorManager {
|
||||
private synchronized void printError(String message, List<String> error, boolean intoConsoleToo, File file) {
|
||||
try {
|
||||
if (!file.exists()) Files.createFile(file.toPath());
|
||||
try (BufferedWriter buf = new BufferedWriter(new FileWriter(file, true))){
|
||||
try (BufferedWriter buf = new BufferedWriter(new FileWriter(file, true))) {
|
||||
if (message != null) {
|
||||
if (file.length() < 1000000)
|
||||
buf.write(dateFormat.format(new Date()) + IChatBaseComponent.fromColoredText("&c[TAB v" + TabConstants.PLUGIN_VERSION + "] ").toRawText() + EnumChatFormat.decolor(message) + System.getProperty("line.separator"));
|
||||
|
||||
@@ -4,6 +4,7 @@ import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import lombok.Getter;
|
||||
import me.neznamy.tab.api.FeatureManager;
|
||||
import me.neznamy.tab.api.TabConstants;
|
||||
import me.neznamy.tab.api.TabFeature;
|
||||
@@ -27,7 +28,7 @@ public class FeatureManagerImpl implements FeatureManager {
|
||||
private final Map<String, TabFeature> features = new LinkedHashMap<>();
|
||||
|
||||
/** All registered features in an array to avoid memory allocations on iteration */
|
||||
private TabFeature[] values = new TabFeature[0];
|
||||
@Getter private TabFeature[] values = new TabFeature[0];
|
||||
|
||||
private boolean objectiveListeners = false;
|
||||
|
||||
@@ -202,7 +203,7 @@ public class FeatureManagerImpl implements FeatureManager {
|
||||
* IN packet coming from player
|
||||
* @return {@code true} if packet should be cancelled, {@code false} if not
|
||||
*/
|
||||
public boolean onPacketReceive(TabPlayer sender, Object packet){
|
||||
public boolean onPacketReceive(TabPlayer sender, Object packet) {
|
||||
boolean cancel = false;
|
||||
for (TabFeature f : values) {
|
||||
if (!f.overridesMethod("onPacketReceive")) continue;
|
||||
@@ -225,7 +226,7 @@ public class FeatureManagerImpl implements FeatureManager {
|
||||
* @param packet
|
||||
* OUT packet coming from the server
|
||||
*/
|
||||
public void onPacketSend(TabPlayer receiver, Object packet){
|
||||
public void onPacketSend(TabPlayer receiver, Object packet) {
|
||||
for (TabFeature f : values) {
|
||||
if (!f.overridesMethod("onPacketSend")) continue;
|
||||
long time = System.nanoTime();
|
||||
@@ -328,9 +329,4 @@ public class FeatureManagerImpl implements FeatureManager {
|
||||
public TabFeature getFeature(String name) {
|
||||
return features.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TabFeature[] getValues() {
|
||||
return values;
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ import java.util.*;
|
||||
public abstract class ITabPlayer implements TabPlayer {
|
||||
|
||||
/** Platform-specific player object instance */
|
||||
protected final Object player;
|
||||
protected Object player;
|
||||
|
||||
/** Player's real name */
|
||||
@Getter private final String name;
|
||||
@@ -32,7 +32,7 @@ public abstract class ITabPlayer implements TabPlayer {
|
||||
@Getter private final UUID uniqueId;
|
||||
|
||||
/** Player's tablist UUID */
|
||||
private final UUID tabListId;
|
||||
@Getter private final UUID tablistId;
|
||||
|
||||
/**
|
||||
* World the player is currently in, {@code "N/A"} if TAB is
|
||||
@@ -50,7 +50,7 @@ public abstract class ITabPlayer implements TabPlayer {
|
||||
private String temporaryGroup;
|
||||
|
||||
/** Player's game type, {@code true} for Bedrock, {@code false} for Java */
|
||||
private final boolean bedrockPlayer;
|
||||
@Getter private final boolean bedrockPlayer;
|
||||
|
||||
/** Player's property map where key is unique identifier and value is property object */
|
||||
private final Map<String, Property> properties = new HashMap<>();
|
||||
@@ -105,7 +105,7 @@ public abstract class ITabPlayer implements TabPlayer {
|
||||
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;
|
||||
this.tablistId = useRealId ? getUniqueId() : offlineId;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -208,11 +208,6 @@ public abstract class ITabPlayer implements TabPlayer {
|
||||
sendCustomPacket(new PacketPlayOutChat(message, ChatMessageType.SYSTEM));
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getTablistUUID() {
|
||||
return tabListId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forceRefresh() {
|
||||
if (!loaded) return;
|
||||
@@ -323,11 +318,6 @@ public abstract class ITabPlayer implements TabPlayer {
|
||||
return setProperty(feature, property, ifNotSet, "None", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBedrockPlayer() {
|
||||
return bedrockPlayer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTeamName() {
|
||||
Sorting sorting = (Sorting) TAB.getInstance().getFeatureManager().getFeature(TabConstants.Feature.SORTING);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package me.neznamy.tab.shared;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import me.neznamy.tab.api.FeatureManager;
|
||||
import me.neznamy.tab.api.TabConstants;
|
||||
import me.neznamy.tab.api.TabFeature;
|
||||
@@ -20,16 +19,14 @@ import me.neznamy.tab.shared.permission.PermissionPlugin;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* An interface with methods that are called in universal code,
|
||||
* but require platform-specific API calls
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
public abstract class Platform {
|
||||
|
||||
/** Platform's packet builder implementation */
|
||||
@Getter private final PacketBuilder packetBuilder;
|
||||
|
||||
public void sendConsoleMessage(String message, boolean translateColors) {
|
||||
Object logger = TAB.getInstance().getLogger();
|
||||
if (logger instanceof java.util.logging.Logger) {
|
||||
@@ -143,6 +140,38 @@ public abstract class Platform {
|
||||
return new BossBarManagerImpl();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns protocol version of requested player using ViaVersion
|
||||
*
|
||||
* @param player
|
||||
* UUID of player to get protocol version of
|
||||
* @param playerName
|
||||
* Name of the player
|
||||
* @return protocol version of the player using ViaVersion
|
||||
*/
|
||||
public int getProtocolVersionVia(UUID player, String playerName, int retryLevel) {
|
||||
try {
|
||||
if (retryLevel == 10) {
|
||||
TAB.getInstance().debug("Failed to get protocol version of " + playerName + " after 10 retries");
|
||||
return TAB.getInstance().getServerVersion().getNetworkId();
|
||||
}
|
||||
int version = Via.getAPI().getPlayerVersion(player);
|
||||
if (version == -1) {
|
||||
Thread.sleep(5);
|
||||
return getProtocolVersionVia(player, playerName, retryLevel + 1);
|
||||
}
|
||||
TAB.getInstance().debug("ViaVersion returned protocol version " + version + " for " + playerName);
|
||||
return version;
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
return -1;
|
||||
} catch (Exception | LinkageError e) {
|
||||
TAB.getInstance().getErrorManager().printError(String.format("Failed to get protocol version of %s using ViaVersion v%s",
|
||||
playerName, getPluginVersion(TabConstants.Plugin.VIAVERSION)), e);
|
||||
return TAB.getInstance().getServerVersion().getNetworkId();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of {@link me.neznamy.tab.api.placeholder.Placeholder}
|
||||
* to handle this unknown placeholder (typically a PAPI placeholder)
|
||||
@@ -186,4 +215,5 @@ public abstract class Platform {
|
||||
|
||||
public abstract @Nullable TabFeature getPerWorldPlayerlist();
|
||||
|
||||
public abstract PacketBuilder getPacketBuilder();
|
||||
}
|
||||
@@ -206,7 +206,7 @@ public class TAB extends TabAPI {
|
||||
*/
|
||||
public void addPlayer(TabPlayer player) {
|
||||
data.put(player.getUniqueId(), player);
|
||||
playersByTabListId.put(player.getTablistUUID(), player);
|
||||
playersByTabListId.put(player.getTablistId(), player);
|
||||
onlinePlayers = data.values().toArray(new TabPlayer[0]);
|
||||
}
|
||||
|
||||
@@ -218,7 +218,7 @@ public class TAB extends TabAPI {
|
||||
*/
|
||||
public void removePlayer(TabPlayer player) {
|
||||
data.remove(player.getUniqueId());
|
||||
playersByTabListId.remove(player.getTablistUUID());
|
||||
playersByTabListId.remove(player.getTablistId());
|
||||
onlinePlayers = data.values().toArray(new TabPlayer[0]);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
package me.neznamy.tab.shared.backend;
|
||||
|
||||
import lombok.Getter;
|
||||
import me.neznamy.tab.api.TabConstants;
|
||||
import me.neznamy.tab.api.TabFeature;
|
||||
import me.neznamy.tab.api.protocol.PacketBuilder;
|
||||
import me.neznamy.tab.shared.Platform;
|
||||
import me.neznamy.tab.shared.features.redis.RedisSupport;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import me.neznamy.tab.shared.permission.LuckPerms;
|
||||
import me.neznamy.tab.shared.permission.None;
|
||||
import me.neznamy.tab.shared.permission.PermissionPlugin;
|
||||
|
||||
public abstract class BackendPlatform extends Platform {
|
||||
|
||||
public BackendPlatform(PacketBuilder packetBuilder) {
|
||||
super(packetBuilder);
|
||||
}
|
||||
@Getter private final TabFeature globalPlayerlist = null;
|
||||
@Getter private final RedisSupport redisSupport = null;
|
||||
|
||||
@Override
|
||||
public @Nullable TabFeature getGlobalPlayerlist() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable RedisSupport getRedisSupport() {
|
||||
return null;
|
||||
public PermissionPlugin detectPermissionPlugin() {
|
||||
if (getPluginVersion(TabConstants.Plugin.LUCKPERMS) != null) {
|
||||
return new LuckPerms(getPluginVersion(TabConstants.Plugin.LUCKPERMS));
|
||||
}
|
||||
return new None();
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -170,7 +170,7 @@ public abstract class BackendArmorStand implements ArmorStand {
|
||||
* @param sleeping
|
||||
* Whether player is sleeping or not
|
||||
* @param sneaking
|
||||
* Whether player is sneakinig or not
|
||||
* Whether player is sneaking or not
|
||||
* @param viewer
|
||||
* Viewer of the armor stand
|
||||
* @return Y to add to player's location
|
||||
|
||||
+3
-3
@@ -65,7 +65,7 @@ public class VehicleRefresher extends TabFeature {
|
||||
if (vehicle != null) {
|
||||
vehicles.put(feature.getEntityId(vehicle), feature.getPassengers(vehicle));
|
||||
playersInVehicle.put(p, vehicle);
|
||||
if (feature.isDisableOnBoats() && feature.getEntityType(vehicle).contains("BOAT")) {
|
||||
if (feature.isDisableOnBoats() && feature.getEntityType(vehicle).contains("boat")) {
|
||||
playersOnBoats.add(p);
|
||||
}
|
||||
}
|
||||
@@ -82,7 +82,7 @@ public class VehicleRefresher extends TabFeature {
|
||||
public void onQuit(TabPlayer disconnectedPlayer) {
|
||||
if (playersInVehicle.containsKey(disconnectedPlayer)) vehicles.remove(feature.getEntityId(playersInVehicle.get(disconnectedPlayer)));
|
||||
for (List<Integer> entities : vehicles.values()) {
|
||||
entities.remove(feature.getEntityId(disconnectedPlayer));
|
||||
entities.remove((Integer)feature.getEntityId(disconnectedPlayer));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ public class VehicleRefresher extends TabFeature {
|
||||
vehicles.put(feature.getEntityId(vehicle), feature.getPassengers(vehicle));
|
||||
feature.getArmorStandManager(p).respawn(); //making teleport instant instead of showing teleport animation
|
||||
playersInVehicle.put(p, vehicle);
|
||||
if (feature.isDisableOnBoats() && feature.getEntityType(vehicle).contains("BOAT")) {
|
||||
if (feature.isDisableOnBoats() && feature.getEntityType(vehicle).contains("boat")) {
|
||||
playersOnBoats.add(p);
|
||||
feature.updateTeamData(p);
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ public class CpuCommand extends SubCommand {
|
||||
double featureTotal = entry.getValue().values().stream().mapToDouble(Float::floatValue).sum();
|
||||
String core = String.format("&8&l%s &7%s &7(%s%%&7):", LINE_CHAR, entry.getKey(), colorize(decimal3.format(featureTotal), 5, 1));
|
||||
List<String> messages = new ArrayList<>();
|
||||
for (Entry<String, Float> type : entry.getValue().entrySet()){
|
||||
for (Entry<String, Float> type : entry.getValue().entrySet()) {
|
||||
messages.add(String.format("&8&l%s &7%s - %s%%", LINE_CHAR, type.getKey(), colorize(decimal3.format(type.getValue()), 5, 1)));
|
||||
}
|
||||
TAB.getInstance().sendConsoleMessage(core, true);
|
||||
@@ -110,7 +110,7 @@ public class CpuCommand extends SubCommand {
|
||||
double featureTotal = entry.getValue().values().stream().mapToDouble(Float::floatValue).sum();
|
||||
String core = String.format("&8&l%s &7%s &7(%s%%&7):", LINE_CHAR, entry.getKey(), colorize(decimal3.format(featureTotal), 5, 1));
|
||||
List<String> messages = new ArrayList<>();
|
||||
for (Entry<String, Float> type : entry.getValue().entrySet()){
|
||||
for (Entry<String, Float> type : entry.getValue().entrySet()) {
|
||||
messages.add("&3" + type.getKey() + " - " + colorize(decimal3.format(type.getValue()), 5, 1) + "%");
|
||||
}
|
||||
IChatBaseComponent message = new IChatBaseComponent(EnumChatFormat.color(core));
|
||||
|
||||
@@ -173,7 +173,7 @@ public class DebugCommand extends SubCommand {
|
||||
*
|
||||
* @return list of extra properties
|
||||
*/
|
||||
public List<String> getExtraLines(){
|
||||
public List<String> getExtraLines() {
|
||||
if (!TAB.getInstance().getFeatureManager().isFeatureEnabled(TabConstants.Feature.UNLIMITED_NAME_TAGS)) return new ArrayList<>();
|
||||
List<String> lines = new ArrayList<>(TAB.getInstance().getConfiguration().getConfig().getStringList("scoreboard-teams.unlimited-nametag-mode.dynamic-lines"));
|
||||
Map<String, Number> staticLines = TAB.getInstance().getConfiguration().getConfig().getConfigurationSection("scoreboard-teams.unlimited-nametag-mode.static-lines");
|
||||
|
||||
@@ -54,7 +54,7 @@ public class GroupCommand extends PropertyCommand {
|
||||
if (hasPermission(sender, TabConstants.Permission.COMMAND_DATA_REMOVE)) {
|
||||
TAB.getInstance().getConfiguration().getGroups().remove(group);
|
||||
for (TabPlayer pl : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (pl.getGroup().equals(group) || TabConstants.DEFAULT_GROUP.equals(group)){
|
||||
if (pl.getGroup().equals(group) || TabConstants.DEFAULT_GROUP.equals(group)) {
|
||||
pl.forceRefresh();
|
||||
}
|
||||
}
|
||||
@@ -113,8 +113,8 @@ public class GroupCommand extends PropertyCommand {
|
||||
* @param value
|
||||
* new value
|
||||
*/
|
||||
private void saveGroup(TabPlayer sender, String group, String type, String value, String server, String world){
|
||||
if (value.length() > 0){
|
||||
private void saveGroup(TabPlayer sender, String group, String type, String value, String server, String world) {
|
||||
if (value.length() > 0) {
|
||||
sendMessage(sender, getMessages().getGroupValueAssigned(type, value, group));
|
||||
} else {
|
||||
sendMessage(sender, getMessages().getGroupValueRemoved(type, group));
|
||||
@@ -123,7 +123,7 @@ public class GroupCommand extends PropertyCommand {
|
||||
if (property.length > 0 && String.valueOf(value.length() == 0 ? null : value).equals(String.valueOf(property[0]))) return;
|
||||
TAB.getInstance().getConfiguration().getGroups().setProperty(group, type, server, world, value.length() == 0 ? null : value);
|
||||
for (TabPlayer pl : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (pl.getGroup().equals(group) || TabConstants.DEFAULT_GROUP.equals(group)){
|
||||
if (pl.getGroup().equals(group) || TabConstants.DEFAULT_GROUP.equals(group)) {
|
||||
pl.forceRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,8 +84,8 @@ public class PlayerCommand extends PropertyCommand {
|
||||
* @param value
|
||||
* new value
|
||||
*/
|
||||
public void savePlayer(TabPlayer sender, String player, String type, String value, String server, String world){
|
||||
if (value.length() > 0){
|
||||
public void savePlayer(TabPlayer sender, String player, String type, String value, String server, String world) {
|
||||
if (value.length() > 0) {
|
||||
sendMessage(sender, getMessages().getPlayerValueAssigned(type, value, player));
|
||||
} else {
|
||||
sendMessage(sender, getMessages().getPlayerValueRemoved(type, player));
|
||||
@@ -96,7 +96,7 @@ public class PlayerCommand extends PropertyCommand {
|
||||
TabPlayer pl = TAB.getInstance().getPlayer(player);
|
||||
try {
|
||||
if (pl == null) pl = TAB.getInstance().getPlayer(UUID.fromString(player));
|
||||
} catch (IllegalArgumentException ignored){} // not an uuid string
|
||||
} catch (IllegalArgumentException ignored) {} // not an uuid string
|
||||
if (pl != null) {
|
||||
pl.forceRefresh();
|
||||
}
|
||||
|
||||
@@ -85,8 +85,8 @@ public class PlayerUUIDCommand extends PropertyCommand {
|
||||
* @param value
|
||||
* new value
|
||||
*/
|
||||
public void savePlayer(TabPlayer sender, TabPlayer player, String type, String value, String server, String world){
|
||||
if (value.length() > 0){
|
||||
public void savePlayer(TabPlayer sender, TabPlayer player, String type, String value, String server, String world) {
|
||||
if (value.length() > 0) {
|
||||
sendMessage(sender, getMessages().getPlayerValueAssigned(type, value, player.getName() + "(" + player.getUniqueId().toString() + ")"));
|
||||
} else {
|
||||
sendMessage(sender, getMessages().getPlayerValueRemoved(type, player.getName() + "(" + player.getUniqueId().toString() + ")"));
|
||||
|
||||
@@ -9,6 +9,7 @@ import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
@@ -17,6 +18,7 @@ import me.neznamy.tab.shared.config.MessageFile;
|
||||
/**
|
||||
* Abstract class representing a subcommand of "/tab" command
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public abstract class SubCommand {
|
||||
|
||||
//all properties assignable with a command
|
||||
@@ -25,28 +27,15 @@ public abstract class SubCommand {
|
||||
//properties that require unlimited NameTag mode
|
||||
protected final List<String> extraProperties = Arrays.asList(TabConstants.Property.ABOVENAME, TabConstants.Property.BELOWNAME, TabConstants.Property.CUSTOMTAGNAME);
|
||||
|
||||
//subcommands of this command
|
||||
@Getter private final Map<String, SubCommand> subcommands = new HashMap<>();
|
||||
|
||||
//name of this subcommand
|
||||
@Getter private final String name;
|
||||
|
||||
//permission required to run this command
|
||||
private final String permission;
|
||||
|
||||
//subcommands of this command
|
||||
@Getter private final Map<String, SubCommand> subcommands = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters
|
||||
*
|
||||
* @param name
|
||||
* command name
|
||||
* @param permission
|
||||
* permission requirement
|
||||
*/
|
||||
protected SubCommand(String name, String permission) {
|
||||
this.name = name;
|
||||
this.permission = permission;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers new subcommand
|
||||
*
|
||||
@@ -137,7 +126,7 @@ public abstract class SubCommand {
|
||||
* beginning of the name
|
||||
* @return List of compatible players
|
||||
*/
|
||||
public List<String> getOnlinePlayers(String nameStart){
|
||||
public List<String> getOnlinePlayers(String nameStart) {
|
||||
List<String> suggestions = new ArrayList<>();
|
||||
for (TabPlayer all : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (all.getName().toLowerCase().startsWith(nameStart.toLowerCase())) suggestions.add(all.getName());
|
||||
@@ -145,7 +134,7 @@ public abstract class SubCommand {
|
||||
return suggestions;
|
||||
}
|
||||
|
||||
public List<String> getStartingArgument(Collection<String> values, String argument){
|
||||
public List<String> getStartingArgument(Collection<String> values, String argument) {
|
||||
return values.stream().filter(value -> value.toLowerCase().startsWith(argument.toLowerCase())).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ public class TabCommand extends SubCommand {
|
||||
* @param sender
|
||||
* player who ran command or null if from console
|
||||
*/
|
||||
private void help(TabPlayer sender){
|
||||
private void help(TabPlayer sender) {
|
||||
if (hasPermission(sender, TabConstants.Permission.COMMAND_ALL)) {
|
||||
if (sender != null) {
|
||||
IChatBaseComponent component = new IChatBaseComponent(EnumChatFormat.color("&3TAB v") + TabConstants.PLUGIN_VERSION);
|
||||
|
||||
@@ -69,7 +69,7 @@ public class AnnounceBarCommand extends SubCommand {
|
||||
if (bar.getName().toLowerCase().startsWith(arguments[0].toLowerCase()) &&
|
||||
bar.isAnnouncementBar()) suggestions.add(bar.getName());
|
||||
}
|
||||
} else if (arguments.length == 2 && b.getBossBar(arguments[0]) != null){
|
||||
} else if (arguments.length == 2 && b.getBossBar(arguments[0]) != null) {
|
||||
for (String time : Arrays.asList("5", "10", "30", "60", "120")) {
|
||||
if (time.startsWith(arguments[1])) suggestions.add(time);
|
||||
}
|
||||
|
||||
Loaded 100 of 167 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user