Compare commits

...
2155 Commits
Author SHA1 Message Date
NEZNAMY 8e5ea29c40 Define decimal separator in one more way to make sure it works properly (#967) 2023-07-07 15:25:11 +02:00
NEZNAMY 287b51a0bf Send warn if using debug command on player who is not loaded (#959) 2023-07-06 20:55:16 +02:00
NEZNAMY 28cbf952fa Send warn if both per world playerlist and layout are enabled 2023-07-06 15:12:28 +02:00
NEZNAMY 598c35a3aa Simplify 2023-07-06 12:37:24 +02:00
NEZNAMY b8b67a64ab Simplify nms loading 2023-07-06 12:33:47 +02:00
NEZNAMY 7f6020ef34 Fix loading on catserver 2023-07-06 12:13:12 +02:00
NEZNAMY aeed453e15 Move named field loading to respective classes 2023-07-05 23:41:54 +02:00
NEZNAMY 71dddcca4c Drop support for mojang mapped server jar 2023-07-05 21:49:54 +02:00
NEZNAMY 46cdf79e20 Use all arg constructor for spawn entity packet on 1.17+ (using the wrong packet still spawns the entity) 2023-07-05 21:12:47 +02:00
NEZNAMY d7af96823b Merge pull request #962 from MachineBreaker/patch-1
Fix ViaVersion bug returning -1 version
2023-07-04 23:11:08 +02:00
MachineBreaker 5a228bd6b3 Fix ViaVersion bug returning -1 version
Explanation:

Both TAB and ViaVersion PlayerJoinEvent priority are LOWEST and seems that TAB registers earlier than ViaVersion the listeners, this causes TAB not being able to get the client protocol version due to ViaVersion not being able to register it firstly.

There might be another way to workaround this since i don't know changing the priority would cause any issue with TAB itself.
2023-07-04 16:19:07 -04:00
NEZNAMY fcd95655ce Send warn when trying to use parse command without any placeholders 2023-07-04 11:09:14 +02:00
NEZNAMY 7f5b57f8d2 Merge pull request #956 from Tanguygab/master
Update skins in Layout's FixedSlots
2023-07-03 17:07:01 +02:00
NEZNAMY f596877716 Fix forwarding unlimited nametag disable status to backend 2023-07-02 17:30:58 +02:00
NEZNAMY 1802c8fd90 Fix debug command not showing properties from unlimited nametag as disabled when they are 2023-07-02 17:30:35 +02:00
Tanguygab e05856facc only update name if skin didn't update 2023-07-02 13:51:37 +02:00
Tanguygab 45cfc3abb0 simplified FixedSlot skin updating 2023-07-02 13:40:08 +02:00
Tanguygab 2d39579861 added support for placeholders in layout's fixed-slots' skins 2023-07-02 13:27:37 +02:00
NEZNAMY 431f4bb4d5 Change Velocity policy 2023-07-02 00:39:10 +02:00
NEZNAMY 7bc9d38176 Slightly improve debug messages 2023-07-01 20:15:50 +02:00
NEZNAMY 7536447a8f Update README.md 2023-06-29 20:47:33 +02:00
NEZNAMY 059b796061 Update CONTRIBUTING.md 2023-06-29 20:35:44 +02:00
NEZNAMY a89942484f Layout - Fix duplicate internal names causing issues 2023-06-28 21:03:13 +02:00
NEZNAMY c28be3fd65 Add (another) warn if plugin's CPU usage is high 2023-06-26 21:04:26 +02:00
NEZNAMY 5f1116795c Add Folia support (#919) 2023-06-25 12:11:41 +02:00
NEZNAMY 4f54d2f6b2 4.0.3-SNAPSHOT 2023-06-25 10:59:05 +02:00
NEZNAMY 6b7bedbe2d Fix NPE when placeholder returns null 2023-06-24 14:30:44 +02:00
NEZNAMY 20ff225c31 Add missing set team color 2023-06-23 22:03:32 +02:00
NEZNAMY af2700798e 4.0.2 2023-06-22 13:07:44 +02:00
NEZNAMY f9c280bbdc Add back vault, so people stop asking 2023-06-22 12:50:36 +02:00
NEZNAMY 6ee31c2c3f Fix unlimited nametag property changes on world switch if per-world settings are used 2023-06-22 11:10:21 +02:00
NEZNAMY cbd944f6f2 Remove redundant field initialization 2023-06-19 21:19:48 +02:00
NEZNAMY cc20748f31 Move ping field initialization 2023-06-19 21:16:20 +02:00
NEZNAMY c9545165aa Rename a few classes 2023-06-19 20:38:19 +02:00
NEZNAMY 05c10bf2e7 Move all scoreboard packet fields & methods to PacketScoreboard class 2023-06-19 19:18:53 +02:00
NEZNAMY 67aeae2094 Create scoreboard implementation using paper api (not used yet) 2023-06-19 17:53:20 +02:00
NEZNAMY 1cc85a0647 Add API function for getting player's team name (#939) 2023-06-19 17:29:04 +02:00
NEZNAMY 988c0f8b4c Construct player object sync 2023-06-19 16:34:03 +02:00
NEZNAMY 62306fa5d6 More cleanup using @SneakyThrows annotation 2023-06-19 12:44:06 +02:00
NEZNAMY 641c5a49c3 Remove unused import 2023-06-19 11:12:16 +02:00
NEZNAMY 5637402435 Fix startup on some bukkit versions & improve compatibility error message 2023-06-18 20:54:25 +02:00
NEZNAMY 728d6c9a25 Make compatibility checks slightly more strict and remove package check. 2023-06-17 23:55:20 +02:00
NEZNAMY 22d3ba2877 Remove layout view on quit to avoid permission checks for offline players 2023-06-17 22:26:38 +02:00
NEZNAMY d1e032e010 Rename methods to reflect on recent change 2023-06-17 21:09:58 +02:00
NEZNAMY 80c4316826 Use Player#getPing() instead of NMS for 1.17+ where it was added 2023-06-17 21:01:02 +02:00
NEZNAMY 3addeba256 Bump bridge protocol 2023-06-17 17:43:21 +02:00
NEZNAMY c52db733b7 Fix potential issue with spectator fix not working if joining with spectator gamemode 2023-06-17 17:42:46 +02:00
NEZNAMY 07a492e353 Forward gamemode from bridge for spectator fix to work on online mode bungee (#934) 2023-06-17 17:42:03 +02:00
NEZNAMY 3c1ec478c2 Small code cleanup using lombok 2023-06-17 11:25:42 +02:00
NEZNAMY f3f614c3de Fix spacing 2023-06-16 17:27:50 +02:00
NEZNAMY a6627ac6c6 Merge pull request #933 from Golfing7/master
Fix loading on velocity
2023-06-16 17:26:14 +02:00
Golfing8 8d1040518f Fix loading on velocity 2023-06-16 11:11:20 -04:00
NEZNAMY ca5d17e6ec Merge pull request #930 from NEZNAMY/v4
Merge v4
2023-06-16 09:08:55 +02:00
NEZNAMY b9fab42510 Update supported version range in error message 2023-06-15 17:31:18 +02:00
NEZNAMY 22f1ef43c4 Add missing return to fix error (#927) 2023-06-15 09:44:14 +02:00
NEZNAMY ffbd4bf26b Move bungee component conversion to shared 2023-06-14 17:59:13 +02:00
NEZNAMY 4d6f93e975 Build adventure components with ProtocolVersion for manually defined legacy colors to actually work 2023-06-14 12:23:51 +02:00
NEZNAMY cb45cff77f 4.0.2-SNAPSHOT 2023-06-14 12:22:29 +02:00
NEZNAMY 4718040345 4.0.1 2023-06-13 00:11:20 +02:00
NEZNAMY afffefcce1 1.20.1 2023-06-13 00:11:10 +02:00
NEZNAMY 4580f47563 Fix bungee kick on 1.7 (#921) 2023-06-12 22:41:07 +02:00
NEZNAMY e51f4bb3a1 Remove unused methods 2023-06-12 13:34:30 +02:00
NEZNAMY e8c8d1dee7 Fix TabComplete on Sponge 7 2023-06-11 19:21:54 +02:00
NEZNAMY 3559afaef7 Fix TabComplete on Fabric 2023-06-11 18:26:39 +02:00
NEZNAMY fc29420eb3 Fix TabComplete on Sponge 8+ 2023-06-11 17:09:42 +02:00
NEZNAMY 023cd3fb75 4.0.0 2023-06-08 14:16:19 +02:00
NEZNAMY 2781d9f232 Fix errors when platform doesn't support unlimited nametags, but it's enabled in config 2023-06-08 14:15:34 +02:00
NEZNAMY d31e5de449 Fix NPE 2023-06-08 13:59:36 +02:00
NEZNAMY 245fcdf917 Update to 1.20 2023-06-08 13:50:47 +02:00
NEZNAMY e3ef3ffa68 Refactor scoreboard command and change /tab announce scoreboard to /tab scoreboard announce 2023-06-07 14:04:36 +02:00
NEZNAMY 95c3608c3f Fix typo 2023-06-07 14:03:34 +02:00
NEZNAMY 7c2236dc96 Not ready yet 2023-06-07 14:03:23 +02:00
NEZNAMY b83ef0e352 API - Add functions for force-updating placeholder values 2023-06-06 11:49:49 +02:00
NEZNAMY 2865871d04 Add check for ViaVersion bug returning -1 version 2023-06-06 11:30:42 +02:00
NEZNAMY 7f7b76a11e Fabric - Remove multi version class 2023-05-28 20:30:20 +02:00
NEZNAMY 52569e4c65 Create method in event listener class for replacing player instead of manually creating it in every class 2023-05-28 20:18:06 +02:00
NEZNAMY 0a0ae6c83b Fabric - Replace player object on respawn because it changes 2023-05-28 20:13:40 +02:00
NEZNAMY 6c8a41388e Unlimited NameTags - Fix disable-condition not working properly when set for the main feature 2023-05-28 16:43:52 +02:00
NEZNAMY fe94e33d85 Use PremiumVanish API code directly instead of reflection 2023-05-28 15:40:33 +02:00
NEZNAMY ca1be457cf Remove error message that was never actually sent 2023-05-25 21:20:22 +02:00
NEZNAMY 550b6350ea Change server version info into a method instead of field and provide more info 2023-05-25 13:38:42 +02:00
NEZNAMY 76470c880d Create player object on join async (broke it in a recode) 2023-05-25 12:23:48 +02:00
NEZNAMY a315bd88b3 Fix MySQL 2023-05-24 21:25:05 +02:00
NEZNAMY bb62930525 Simplify permission plugin data structure 2023-05-24 19:05:43 +02:00
NEZNAMY b7490f0002 Rename a few methods and fields 2023-05-24 13:21:56 +02:00
NEZNAMY 42f3851339 API - Small improvements/fixes and more documentation 2023-05-24 12:37:20 +02:00
NEZNAMY 34f39ac8d5 Fix compilation 2023-05-23 13:02:34 +02:00
NEZNAMY 8c16330119 API - Remove getApiVersion method, since everyone should be up-to-date and users are unlikely to check for it anyway 2023-05-23 12:56:33 +02:00
NEZNAMY 8323c21c3e Move ProtocolVersion enum out of API 2023-05-23 12:49:56 +02:00
NEZNAMY 2a3ca932a4 API - Add functions for unregistering placeholders 2023-05-23 12:41:48 +02:00
NEZNAMY e339928caa Conditions - Fix startsWith and endsWith types (how could they even have worked before?) 2023-05-23 12:40:22 +02:00
NEZNAMY 3eeb025f23 Add API for Layout and move team names to a new sorting class 2023-05-22 21:03:28 +02:00
NEZNAMY f19c1f1baa Another way of breaking the plugin was found by a customer 2023-05-20 18:56:17 +02:00
NEZNAMY 003e6a6adb Forward placeholder output replacements to bridge 2023-05-18 12:01:19 +02:00
NEZNAMY 95d435d61c Create field for viewer instead of passing as parameter 2023-05-17 14:25:19 +02:00
NEZNAMY bbc4e1d767 Unlimited nametags - Compensate for new 1.19.4 bug calling sneak event on vehicle leave with value "true", but never calling with "false" (#894) 2023-05-17 14:01:41 +02:00
NEZNAMY ae46adf8b9 Layout - Make layouts per-player, allowing hiding vanished players and opening new possibilities for the future 2023-05-17 13:31:02 +02:00
NEZNAMY 461ef988d3 Make Platform class an interface and make each implementation override sendConsoleMessage 2023-05-16 20:33:57 +02:00
NEZNAMY 307d21cc85 Remove nickname field, since plugin doesn't track name changes anymore 2023-05-16 19:01:51 +02:00
NEZNAMY e2beac6570 A couple of fixes for disable-conditions 2023-05-16 18:48:02 +02:00
NEZNAMY 75e455f078 Replace NonNull annotation with NotNull for internal methods 2023-05-16 12:52:04 +02:00
NEZNAMY 19c832d370 Rename a few classes 2023-05-16 11:34:02 +02:00
NEZNAMY 9cd4afe1d4 Rework disabled worlds/servers into disable conditions 2023-05-16 11:32:37 +02:00
NEZNAMY 3b00f07f78 Unlimited NameTags - Update visibility on vehicle enter/leave instantly (also maybe fix #894?) 2023-05-16 11:25:15 +02:00
NEZNAMY 0b5008c087 Remove unused fields 2023-05-14 21:59:44 +02:00
NEZNAMY 76f210db03 Print console warn if some placeholder's usage exceeds 50% 2023-05-14 17:43:29 +02:00
NEZNAMY 85c8d9f1b9 Bukkit - Add ViaRewind to softdepend to avoid console warn 2023-05-14 17:12:02 +02:00
NEZNAMY a795fc7f77 BossBar - Send console warn if progress could not be evaluated to a number between 0 and 100 2023-05-14 17:10:39 +02:00
NEZNAMY 7742ab8220 Add native support for multi-character symbols for aligned tabsuffix 2023-05-13 13:18:12 +02:00
NEZNAMY 3e235a8f18 Construct packet class with null title instead of empty string for unregister 2023-05-11 23:56:50 +02:00
NEZNAMY 30f9888f6a Split layout loading into multiple methods for better readability 2023-05-11 19:14:58 +02:00
NEZNAMY d1f8886e2b Layout - Add misconfiguration checks 2023-05-11 16:56:01 +02:00
NEZNAMY 3c037f9aa6 Create and use enums for team visibility and collision 2023-05-11 15:16:45 +02:00
NEZNAMY c70346c57c Fix NPE in injection when player is not loaded yet (#891) 2023-05-09 22:16:36 +02:00
NEZNAMY bd40dd85af Global PlayerList - Properly display players on other servers as spectators if enabled (#890) 2023-05-09 16:42:21 +02:00
NEZNAMY eacd929b0f Remove redundant fully qualified name of imported classes 2023-05-04 01:04:31 +02:00
NEZNAMY 0ff5f17b7d Create and use more constants instead of literal strings 2023-05-04 00:57:46 +02:00
NEZNAMY 57fa01151e Move command implementation for platforms into separate classes instead of being a nested class inside main class 2023-05-04 00:29:51 +02:00
NEZNAMY e7bc1fc74b Move sendPlayerListHeaderFooter method from TabPlayer to TabList 2023-04-29 21:32:40 +02:00
NEZNAMY 897f35ab53 Remove BulkUpdateTabList class and make all implementations update entries one by one 2023-04-29 16:32:51 +02:00
NEZNAMY 7f8b738a69 Add more NotNull / NonNull / Nullable annotations to methods 2023-04-29 15:10:30 +02:00
NEZNAMY 079302fb05 Small code cleanup 2023-04-28 23:31:31 +02:00
NEZNAMY 630fcc9e50 Remove underscore from class names 2023-04-27 16:08:20 +02:00
NEZNAMY c1601ca487 Remove nick compatibility hook, as it should no longer be needed 2023-04-27 14:03:47 +02:00
NEZNAMY d035b9cb80 Fix NPE 2023-04-27 13:20:49 +02:00
NEZNAMY 8db5e4d8ba Add NotNull / NonNull / Nullable annotations to fields and methods 2023-04-26 15:33:06 +02:00
NEZNAMY 4d51bb39d7 Print warn if both global playerlist and layout are enabled 2023-04-25 23:19:16 +02:00
NEZNAMY 7eb0231e08 Move floodgate hook into a separate class 2023-04-25 22:57:30 +02:00
NEZNAMY 6412461576 Simplify 2023-04-25 19:46:07 +02:00
NEZNAMY 5732eb366b Remove unused fields and methods 2023-04-25 19:36:03 +02:00
NEZNAMY ed3df8bb68 Recode redisbungee support and fix many bugs 2023-04-25 19:07:13 +02:00
NEZNAMY 787f531203 Remove unused fields 2023-04-25 19:00:57 +02:00
NEZNAMY cf5d888901 Remove unused parameter 2023-04-23 22:08:59 +02:00
NEZNAMY 1969e5f755 Global playerlist - Remove redundant entry removal on server switch (proxy removes it) 2023-04-23 15:57:43 +02:00
NEZNAMY 8d12ee0958 Remove unused import 2023-04-23 15:57:10 +02:00
NEZNAMY c3bbc89c5b Add final modifier where possible 2023-04-23 15:56:57 +02:00
NEZNAMY 625c7cf3c2 Fix issue with legacy color codes 2023-04-23 11:58:35 +02:00
NEZNAMY 14f0321992 Reduce static usage 2023-04-22 22:43:25 +02:00
NEZNAMY e5294c596a Change way of detection for presence of other plugins 2023-04-22 21:04:57 +02:00
NEZNAMY c83290a99a Fix error in RedisBungee 2023-04-22 20:56:48 +02:00
NEZNAMY 8c66310af0 Add RedisBungee support to Velocity as well 2023-04-22 19:17:05 +02:00
NEZNAMY 5ae91bf89e Update config comment (global playerlist will no longer duplicate players if this issue occurs) 2023-04-22 13:44:13 +02:00
NEZNAMY d5dc1b7bdb Simplify 2023-04-22 13:39:12 +02:00
NEZNAMY 864eee3349 Spectator Fix - Resend on server switch 2023-04-22 13:32:43 +02:00
NEZNAMY 88932e3a5e Move bungee component conversion out of shared to avoid class not found error 2023-04-20 21:59:04 +02:00
NEZNAMY 4ebc60ff00 Print original error instead of the current one 2023-04-20 21:43:05 +02:00
NEZNAMY b0cb63b05d Remove weird code in error printing 2023-04-20 21:19:08 +02:00
NEZNAMY 1db40ee2d5 Fix layout loading 2023-04-19 21:20:50 +02:00
NEZNAMY fd3f0ebd21 Move classes into packages 2023-04-19 11:46:22 +02:00
NEZNAMY ce73069345 Remove hover/click event from chat components 2023-04-18 13:54:06 +02:00
NEZNAMY 088f2748e3 Print amount of startup warns into the console 2023-04-17 20:39:35 +02:00
NEZNAMY d9a8c69f43 Refactor ViaVersion hook and drop ProtocolSupport hook as the plugin is abandoned 2023-04-17 19:23:54 +02:00
NEZNAMY 16ff503b6a Add back task queue while plugin is loading 2023-04-17 18:20:54 +02:00
NEZNAMY 68c78b9c73 Make field public 2023-04-17 18:04:17 +02:00
NEZNAMY 0c9d78a644 Fix method name 2023-04-15 18:59:54 +02:00
NEZNAMY 99d22642e2 Scoreboard - Fix placeholders not being updated in title on scoreboard switch 2023-04-15 15:22:02 +02:00
NEZNAMY dc762eacf8 Fill all fields in plugin.yml 2023-04-13 20:47:01 +02:00
NEZNAMY 5a44f30140 Reorder permission constants 2023-04-13 20:37:53 +02:00
NEZNAMY 82e86b0f8a Fix NPE on reload 2023-04-13 18:02:21 +02:00
NEZNAMY 9c4eb4359c Document empty methods 2023-04-12 21:53:32 +02:00
NEZNAMY 827c380463 Move more reflection related methods to ReflectionUtils 2023-04-12 21:50:01 +02:00
NEZNAMY 7c4fc324c8 Simplify 2023-04-12 21:18:29 +02:00
NEZNAMY 46215f3304 Fix indentation 2023-04-12 21:15:16 +02:00
NEZNAMY 1accc21365 Avoid possible NPE 2023-04-12 21:11:29 +02:00
NEZNAMY b74c2f62f7 Replace star import with explicit imports 2023-04-12 21:08:38 +02:00
NEZNAMY 9d14c0c923 Resend header/footer on server switch because velocity clears it 2023-04-12 16:17:12 +02:00
NEZNAMY 650fda5781 Reorder class loading to make it cleaner 2023-04-11 16:43:40 +02:00
NEZNAMY 286ccf5836 Reorder class loading to make it cleaner 2023-04-10 19:08:54 +02:00
NEZNAMY dfa310666c Move reflection related methods to ReflectionUtils 2023-04-10 19:02:35 +02:00
NEZNAMY 06595241ab Remove plugins from softdepend which are no longer being hooked into 2023-04-10 18:38:57 +02:00
NEZNAMY 0f80dd1cfd Simplify 2023-04-10 18:33:02 +02:00
NEZNAMY 7bc5be264c Define dependencies directly instead of using versions file 2023-04-10 16:23:44 +02:00
NEZNAMY e31784fb1e Include initial task delay to prevent errors while plugin is still loading 2023-04-10 13:15:14 +02:00
NEZNAMY ae156f424b Move layout to config.yml 2023-04-10 13:11:41 +02:00
NEZNAMY cfe0b3883e Remove deleted placeholder from default configuration 2023-04-10 12:49:54 +02:00
NEZNAMY fc6beaa0a5 Add removing of removed config option to converter 2023-04-10 12:45:11 +02:00
NEZNAMY 5f2140b147 Make placeholder output replacements no longer require splitting config section with each "." used in placeholder 2023-04-10 12:43:28 +02:00
NEZNAMY c497bdff39 Swap condition registration order for proper detection of type 2023-04-10 12:22:16 +02:00
NEZNAMY 7c84b6432e Simplify condition classes (or maybe just make them more complicated?) 2023-04-10 01:21:14 +02:00
NEZNAMY 3f787c3b0b Create separate Platform class for consistency 2023-04-10 00:00:32 +02:00
NEZNAMY 2046a39e99 Simplify 2023-04-09 23:42:32 +02:00
NEZNAMY 2ccf89e396 Further simplify Fabric code changes for older server versions 2023-04-08 22:45:43 +02:00
NEZNAMY efaebc3cb0 Simplify code changes for older versions on Fabric 2023-04-08 17:03:56 +02:00
NEZNAMY d7c952cc36 Fix placeholders from bridge not updating if player is not loaded yet when response is sent 2023-04-08 15:19:56 +02:00
NEZNAMY 1d3ea37129 Prevent bridge form re-registering placeholders that got deleted from config 2023-04-08 15:06:58 +02:00
NEZNAMY 1e9c47398d Add bridge connection status to debug command 2023-04-08 14:43:05 +02:00
NEZNAMY 5a1f48f1a5 Apparently it cannot be null 2023-04-08 14:25:03 +02:00
NEZNAMY ed65554d30 Remove duplication in player/playeruuid/group commands 2023-04-07 22:36:35 +02:00
NEZNAMY 0f19970401 Clean up ChatModifier serialization 2023-04-07 22:04:57 +02:00
NEZNAMY b419499710 Remove unnecessary fully qualified name 2023-04-07 21:58:38 +02:00
NEZNAMY 14a5f30b74 Split method for processing plugin messages into multiple 2023-04-07 21:48:38 +02:00
NEZNAMY 302cdf200f Small refactor of classes implemented by platforms 2023-04-07 21:32:15 +02:00
NEZNAMY bdde257cac Remove unused fields 2023-04-07 13:01:25 +02:00
NEZNAMY 73af013bca Change usage of methods which didn't exist before on fabric 2023-04-06 18:26:26 +02:00
Callum Seabrook e421427007 Disabled access widener validation task for Fabric 2023-04-06 16:17:51 +01:00
NEZNAMY 169a180d68 Remove unused imports 2023-04-06 16:28:28 +02:00
Callum Seabrook 16a19bf578 Switched to access wideners for player info entries on Fabric 2023-04-06 14:29:43 +01:00
Callum Seabrook 5b39204a8a Cleaned up Krypton code 2023-04-06 13:54:54 +01:00
Callum Seabrook b2bb125248 Switched Krypton tab list to API and removed server dependency 2023-04-06 13:35:08 +01:00
NEZNAMY 980354104b Remove fabric constant that is only used once 2023-04-06 00:18:15 +02:00
NEZNAMY b27571dcaa Catch UnsupportedOperationException 2023-04-05 22:27:44 +02:00
NEZNAMY b215bf9000 Fix dumb mistake 2023-04-05 21:10:04 +02:00
NEZNAMY ab75b13b3f Add option to choose target minecraft version on Fabric all the way down to 1.17 2023-04-05 20:42:51 +02:00
Callum Seabrook 31cd2aeb08 Made getFeature generic and removed casts 2023-04-05 19:18:39 +01:00
Callum Seabrook 8b6b33b314 Fixed compile 2023-04-05 18:40:10 +01:00
Callum Seabrook 1b66257ece Removed chat session from ProxyTabPlayer 2023-04-05 18:30:52 +01:00
Callum Seabrook bed9fcf212 Show new blank scoreboard to joining players on Krypton 2023-04-05 18:22:01 +01:00
Callum Seabrook 692f309750 Switched to API instead of packets for Krypton scoreboard 2023-04-05 16:30:19 +01:00
Callum Seabrook 2c9c9b502a Renamed Main to KryptonTAB for consistency 2023-04-05 15:48:50 +01:00
Callum Seabrook 3da8fd2a77 Fixed failed startup without Spark present on Krypton 2023-04-05 15:45:56 +01:00
Callum Seabrook ba6826f3d1 Added variable to change target Minecraft version for Fabric 2023-04-05 12:19:59 +01:00
Callum Seabrook 68b3629437 Added permissions API support for Fabric 2023-04-05 12:08:32 +01:00
Callum Seabrook 8bc5962d1c Use reflection for changing player info entries 2023-04-05 11:55:25 +01:00
NEZNAMY b8aa1982e4 Improve ViaVersion check on Fabric 2023-04-05 00:57:35 +02:00
NEZNAMY e0a427732e Update README.md 2023-04-04 23:25:38 +02:00
NEZNAMY 8d1f60f5fa Fix github actions 2023-04-04 23:16:15 +02:00
NEZNAMY 5cd7fdf385 Small improvements and fixes to fabric 2023-04-04 23:14:51 +02:00
Callum Seabrook e54d342ac5 Made relocations have a consistent pattern 2023-04-04 21:30:52 +01:00
Callum Seabrook 9019261c2a Fabric support 2023-04-04 21:27:55 +01:00
Callum Seabrook b1a5092053 Added Adventure-based boss bar handler for platforms using Adventure 2023-04-04 20:11:27 +01:00
NEZNAMY ef8bdbb40f Spectator fix - Add delay on join to avoid being too early 2023-04-04 21:08:19 +02:00
Callum Seabrook 0d67826b3d Removed message component cache on Bukkit 2023-04-04 19:34:24 +01:00
NEZNAMY 6c99e28d51 Improve code style in Scoreboard class 2023-04-04 17:21:38 +02:00
NEZNAMY 13931aafa5 Rethrow exceptions as IllegalStateException instead of RuntimeException 2023-04-04 17:01:17 +02:00
NEZNAMY 089e7ce8b5 Move class out of package 2023-04-04 15:52:01 +02:00
NEZNAMY 54287c8a29 Fix color getter 2023-04-04 15:41:18 +02:00
NEZNAMY 5ebc5dee21 Make gamemode change detection a periodic task instead of listening to packets 2023-04-04 15:29:34 +02:00
NEZNAMY bedbdbcca9 Remove redundant interface class 2023-04-04 14:44:37 +02:00
NEZNAMY a1c35adf4c Convert to adventure components directly instead of deserializing string 2023-04-04 14:34:56 +02:00
NEZNAMY 81b6a9be8b Remove redundant component deserialization attempts 2023-04-04 13:50:21 +02:00
Callum Seabrook 88eee58329 Moved chat system out of API 2023-04-02 22:49:15 +01:00
Callum Seabrook 2f02a5bda4 Removed unlimited nametags from Krypton 2023-04-02 21:11:05 +01:00
Callum Seabrook ba716df634 Removed unlimited nametags from Sponge 8 2023-04-02 20:12:30 +01:00
NEZNAMY 988292b82a XD 2023-04-02 16:30:06 +02:00
Callum Seabrook d52cfdd6e6 Start of Fabric 2023-04-02 13:55:38 +01:00
Callum Seabrook b13a49539f Updated to Gradle 8 2023-04-02 13:47:37 +01:00
NEZNAMY 32a39a361c Improve marking vanish placeholder as used for features listening to vanish status change 2023-04-02 13:46:20 +02:00
NEZNAMY 0e2e9b9ae6 Fix playerlist formatting not updating on unvanish 2023-04-02 13:41:14 +02:00
NEZNAMY 331faefde2 Fix compilation 2023-04-02 12:57:46 +02:00
NEZNAMY 1603ebe9fc Remove unused parameter 2023-04-02 12:43:15 +02:00
NEZNAMY bad4359469 Remove usage of separated initializers 2023-04-02 12:17:16 +02:00
NEZNAMY a860b463ed Merge ifs 2023-04-02 12:13:01 +02:00
NEZNAMY b3b0a96bb8 Remove commented out code that will never come back 2023-04-02 12:11:20 +02:00
NEZNAMY c211724d13 RedisBungee - Don't send yellow number / belowname if feature is disabled (#861) 2023-04-02 12:02:01 +02:00
NEZNAMY 0fb9a832ca Fix raw generic use 2023-04-02 00:34:42 +02:00
NEZNAMY 7ce1a97c93 Remove player from map on quit 2023-04-02 00:10:33 +02:00
NEZNAMY 1d461c1adf Make Scoreboard class generic to avoid massive casting 2023-04-02 00:02:31 +02:00
NEZNAMY 5ec09c37bc Remove things from API which shouldn't be there 2023-04-01 22:10:11 +02:00
NEZNAMY 95a20766c3 Simplify redisbungee belowname/yellow number forwarding 2023-04-01 17:41:25 +02:00
NEZNAMY 87feb1c2bf Improve misconfiguration checks and management 2023-04-01 17:33:34 +02:00
NEZNAMY 8c732ac7e9 Use defined constant instead of literal string 2023-04-01 13:01:26 +02:00
NEZNAMY 977c1f4d74 Remove unused field 2023-04-01 12:46:04 +02:00
NEZNAMY 65ac22aadb Perform scoreboard objective & team re-registration on server switch instead of listening to Login packet, which is assumed to be sent always 2023-04-01 12:37:02 +02:00
NEZNAMY 8e7a14bdb8 PlayerList - Format players after they un-vanish 2023-04-01 12:07:19 +02:00
NEZNAMY 4693a297b6 Remove unused field 2023-04-01 01:41:03 +02:00
NEZNAMY af69dcd9b5 Add this branch to github actions 2023-04-01 01:20:56 +02:00
NEZNAMY 71110fc722 Remove redundant conversion from older versions 2023-04-01 01:16:50 +02:00
NEZNAMY c2af5632a2 Remove hidden ghost player fix feature 2023-04-01 01:13:21 +02:00
NEZNAMY 399e813ca4 Remove placeholder refresh intervals categories to reduce confusion, split them in code based on identifier 2023-04-01 01:10:05 +02:00
NEZNAMY daac7c6171 Rename config conversion methods 2023-04-01 00:52:30 +02:00
NEZNAMY 940352ef2c Replace null checks with @NonNull 2023-04-01 00:47:21 +02:00
NEZNAMY c70b909c0f Remove disabled worlds/servers from bossbar and scoreboard, since conditions can achieve the same 2023-04-01 00:43:36 +02:00
NEZNAMY dcc2eb9217 Remove vault hook, vault placeholders and %afk% placeholder 2023-04-01 00:34:12 +02:00
NEZNAMY 5425b3b6ea Finish previous commit and remove pet fix feature 2023-04-01 00:17:48 +02:00
NEZNAMY a90ea3e3fa Remove ping spoof feature 2023-04-01 00:03:21 +02:00
NEZNAMY 6d52b7b615 4.0.0-SNAPSHOT 2023-04-01 00:01:43 +02:00
NEZNAMY 51635a7322 3.3.2 2023-03-31 20:44:09 +02:00
NEZNAMY 481b33ba55 Print error message if plugin message could not be sent 2023-03-31 15:30:30 +02:00
NEZNAMY 22c785fc99 Add error message when plugin message could not be processed 2023-03-31 15:21:53 +02:00
NEZNAMY 42d4159b69 Global PlayerList - Register placeholders in constructor to avoid it being registered as PAPI placeholder 2023-03-31 14:41:21 +02:00
NEZNAMY 6d95a2f06d Fix error on concurrent access 2023-03-31 13:40:50 +02:00
NEZNAMY 7f0b1d8a2e Fix rare error on /btab reload 2023-03-31 13:40:37 +02:00
NEZNAMY a3fecd0fea Unregister tab expansion on unload to fix compatibility with latest PAPI release 2023-03-30 21:17:09 +02:00
NEZNAMY f3d6a54a2a Merge remote-tracking branch 'origin/master' 2023-03-29 17:24:21 +02:00
NEZNAMY 1d434f2557 Add more documentation 2023-03-29 17:24:11 +02:00
NEZNAMY b3500086e4 Merge pull request #856 from zelvalea/master
optimizations in CPUManager
2023-03-28 23:23:48 +02:00
Amoeba bf9202af38 added time constants 2023-03-28 20:31:29 +03:00
Amoeba bd2c683568 fixed happens before and cpu usage statistics 2023-03-28 20:09:51 +03:00
Amoeba c03feaab23 fixed nanosToPercent 2023-03-28 19:44:11 +03:00
Amoeba 9cb9ccbd2a optimize 2023-03-28 19:21:48 +03:00
Callum Seabrook 4606ebd588 Use single thread for tasks and remove ThreadManager from API 2023-03-28 12:32:13 +01:00
Callum Seabrook 679be83c5a Merge pull request #854 from zelvalea/master 2023-03-28 11:51:03 +01:00
NEZNAMY afe868bb95 Fix group update through bridge after recoding group updating 2023-03-28 01:21:29 +02:00
ZelvaLea c9ce3aa23e reduced number of threads in the pool, fixed races 2023-03-28 01:15:04 +03:00
NEZNAMY 11a49c4874 Remove unnecessary full import 2023-03-27 21:21:27 +02:00
NEZNAMY 65d2a0fba9 Remove unused field 2023-03-27 21:19:15 +02:00
NEZNAMY c1219195c7 Remove workarounds for fixing compilation, which are no longer needed 2023-03-26 17:06:57 +02:00
NEZNAMY fca0dfc91b More constant extraction to plugin.yml & bungee.yml 2023-03-26 17:02:32 +02:00
NEZNAMY 7f1cc3063c Move text cutting to 16/32 characters to avoid duplication 2023-03-26 16:53:47 +02:00
NEZNAMY e444c25287 Convert krypton to java 2023-03-26 16:36:51 +02:00
NEZNAMY 476354e407 Change thrown exception 2023-03-25 23:25:07 +01:00
NEZNAMY 9f84d3f22f Remove cpu measurement of chosen methods 2023-03-25 23:22:28 +01:00
NEZNAMY 4608ff360c Simplify 2023-03-25 23:12:48 +01:00
NEZNAMY 68b12e199d Placeholders - Measure per-placeholder cpu usage on join as well 2023-03-25 20:54:53 +01:00
NEZNAMY 4b1151f769 Use defined value instead of duplicating it in build settings 2023-03-25 20:25:27 +01:00
NEZNAMY 6687214f2a Sponge - Add support all the way down to Sponge 5 2023-03-25 19:22:07 +01:00
NEZNAMY a57757258e Sponge - Use API for scoreboards instead of packets (also small bug fix) 2023-03-25 18:41:56 +01:00
NEZNAMY 3a6060c45d Fix display name change on 1.7 2023-03-25 14:29:27 +01:00
NEZNAMY ee375c1b60 Unify tablist management between proxies 2023-03-25 14:22:40 +01:00
NEZNAMY c9d870cca0 Use placeholder refreshing engine for refreshing player groups instead of creating another thread 2023-03-23 14:52:19 +01:00
NEZNAMY 3ad8015cc1 Placeholder manager - Initialize task with the lowest refresh interval immediately instead of re-initializing 2023-03-23 14:19:42 +01:00
NEZNAMY 33609c322f Remove duplicated Field#setAccessible 2023-03-22 00:59:02 +01:00
NEZNAMY 431b89c487 Create constant for "textures" String in skin data 2023-03-22 00:33:16 +01:00
NEZNAMY 35a146992c Remove redundant checks and simplify 2023-03-22 00:27:46 +01:00
NEZNAMY dedee114c4 BungeeCord - Split boss bar handler into 2 classes 2023-03-21 20:07:11 +01:00
NEZNAMY 9d42af0388 Bukkit - Split boss bar handler into 3 classes 2023-03-21 18:39:08 +01:00
NEZNAMY 8f5d81bc33 Remove redundant annotation 2023-03-21 18:38:41 +01:00
NEZNAMY b17f5563dd Remove unused method 2023-03-21 14:09:57 +01:00
NEZNAMY 0ab8bb363a Unlimited NameTags - Force marker tag for 1.8.x and remove config option 2023-03-20 22:33:56 +01:00
NEZNAMY ac5fca86bd Split TabFeature into multiple interfaces based on used methods 2023-03-20 19:36:40 +01:00
NEZNAMY 28c2c2e193 Fix armor stand metadata on spawn 2023-03-20 16:25:37 +01:00
NEZNAMY 904c0b6a17 Fix anti-override for tablist name formatting (and possibly ping spoof & spectator fix) 2023-03-20 16:21:23 +01:00
NEZNAMY f3c31bc92c Fix error 2023-03-20 12:42:42 +01:00
NEZNAMY 6016b84889 BungeeCord - Fix bossbar color & style update 2023-03-19 22:24:13 +01:00
NEZNAMY cfb5cb3a9f Create object for calling bossbar methods 2023-03-19 22:07:45 +01:00
NEZNAMY 1746f6b1d0 Bukkit - Send all tablist packets grouped, ViaVersion splits them properly for 1.7 players 2023-03-19 21:21:33 +01:00
NEZNAMY 9c3979a0d9 More tablist fixes on 1.7 2023-03-19 21:04:52 +01:00
NEZNAMY 810676c69f Bukkit - Fix NPE on <1.8 servers 2023-03-19 16:44:55 +01:00
NEZNAMY d0892a245a BungeeCord - Fix NPE kick on 1.7 2023-03-19 16:40:53 +01:00
NEZNAMY f539b1b93b BungeeCord - Split TabList class into 3 based on version & make 1.7 actually work (potential future use?) 2023-03-19 14:50:02 +01:00
NEZNAMY adfa64a29f Scoreboard - Fix unregistering teams of lines that aren't displayed due to placeholder output being empty 2023-03-19 14:07:44 +01:00
NEZNAMY d4f86ee79d Remove redundant declaration 2023-03-19 13:43:06 +01:00
NEZNAMY 6ebe31b737 Add @NonNull / @Nullable annotations to TeamManager (#843) 2023-03-19 13:38:58 +01:00
NEZNAMY dcbd5e62d4 Fix packet un-cancel breaking PetFix (#842) 2023-03-19 13:26:24 +01:00
NEZNAMY a7e6e49363 Fix #845 (1.7 requires non-null title in scoreboard unregister action) 2023-03-19 12:52:56 +01:00
NEZNAMY d115257ff7 Move DisplaySlot class inside Scoreboard 2023-03-18 23:53:49 +01:00
NEZNAMY d578be276c Remove duplicated caches 2023-03-18 22:35:16 +01:00
NEZNAMY e338f57441 Completely get rid of PacketBuilder class 2023-03-18 22:25:05 +01:00
Callum Seabrook c87321b5b0 Rewrote packet injection for Krypton 2023-03-18 19:37:34 +00:00
NEZNAMY 84bb9b449b Add methods for manipulating entities instead of using sendPacket 2023-03-18 19:22:29 +01:00
NEZNAMY 9d613fc24d Rework tablist packet management to make it more API-style 2023-03-18 17:44:43 +01:00
NEZNAMY 3f2ae3131e Add back a default animation, which is still used in default scoreboard 2023-03-18 00:14:56 +01:00
NEZNAMY 0e9f53bd58 Fix wrong action on objective unregister 2023-03-17 18:20:47 +01:00
NEZNAMY 3981815b63 Create Scoreboard interface for calling scoreboard-related methods 2023-03-17 15:04:55 +01:00
NEZNAMY 3ef99e4e7c Better abstraction of pipeline injection 2023-03-16 15:16:24 +01:00
NEZNAMY 76767a0958 Use API-style managing of scoreboard teams 2023-03-16 13:53:50 +01:00
NEZNAMY 1683943d58 Use API-style managing of scoreboard objectives 2023-03-16 01:07:21 +01:00
NEZNAMY cc0dbe8623 Move sendPluginMessage method to ProxyTabPlayer 2023-03-16 00:03:13 +01:00
NEZNAMY b056251e07 Remove calculating of packets sent by the plugin 2023-03-15 23:50:23 +01:00
NEZNAMY 3b352c66e2 Change way how scoreboard score and display objective packets are sent 2023-03-15 23:31:30 +01:00
NEZNAMY b4f0ea73c1 Supplier with Exception is Callable 2023-03-15 21:43:27 +01:00
NEZNAMY 1c683788b5 BungeeCord - Create cleaner methods for player info action conversion 2023-03-15 21:29:58 +01:00
NEZNAMY 250597df2d Sponge 8 - Fix class cast exception 2023-03-15 21:07:20 +01:00
NEZNAMY 0d2d1d5aaa Sponge 8 - Use direct code instead of reflection for entity teleport packet 2023-03-15 21:00:42 +01:00
NEZNAMY 061375d1e7 3.3.2-SNAPSHOT 2023-03-15 21:00:14 +01:00
NEZNAMY 5b05614305 Remove unused field 2023-03-15 20:13:29 +01:00
NEZNAMY 69db2e0e53 Use API style code for bossbars since packets were not used anymore 2023-03-15 20:03:10 +01:00
NEZNAMY 00ef364324 Use APIs for header/footer instead of packets where possible (rip bukkit) 2023-03-15 16:13:31 +01:00
NEZNAMY de68312b6b Use APIs for chat messages instead of packets 2023-03-15 14:36:25 +01:00
NEZNAMY ddac08bcbc Fix bungee compilation (did md5 break something?) 2023-03-15 14:31:59 +01:00
NEZNAMY 517e285bb3 Fix bossbar error on <1.9 from recode 2023-03-15 14:29:13 +01:00
NEZNAMY 81a08a6b51 3.3.1 2023-03-14 19:18:01 +01:00
NEZNAMY 4dfef1d032 1.19.4 support 2023-03-14 19:15:15 +01:00
NEZNAMY 5d38e28cae Extract more constants and add config option 2023-03-14 18:35:25 +01:00
NEZNAMY 66a12d10c4 Layout - Resend on server switch on Velocity 2023-03-14 17:27:27 +01:00
NEZNAMY 1a4027c8d5 Remove unused fields and methods 2023-03-14 16:15:55 +01:00
NEZNAMY 2a0243c51a RedisSupport - Add missing packet source 2023-03-14 15:24:13 +01:00
NEZNAMY 4851d09e70 More abstraction of unlimited nametag mode & packets it uses 2023-03-14 15:20:49 +01:00
NEZNAMY 3cdf3accfd Remove redundant checks 2023-03-14 10:46:27 +01:00
NEZNAMY fd1f094216 Layout - Small cleanup in code 2023-03-14 00:22:02 +01:00
NEZNAMY 25ece1ecb8 Move ViaVersion hook (and remove safety checks, hopefully it works correctly now) 2023-03-13 23:31:10 +01:00
NEZNAMY 802e65c280 Change constructor fields to getters in features 2023-03-13 23:04:22 +01:00
NEZNAMY 882688f056 Layout - Cache remove packet 2023-03-13 21:52:29 +01:00
NEZNAMY 97d60d0ab3 Bungee - Remove unused field (and simplify) 2023-03-13 21:33:48 +01:00
NEZNAMY 9ef99daed1 Revert feature loading as references were not null when they were supposed to be 2023-03-13 21:31:48 +01:00
NEZNAMY 71c85d9d39 NameTags - Speed up unloading 2023-03-13 19:36:05 +01:00
NEZNAMY b981ab46be Add debug messages about feature unloading times 2023-03-13 19:35:45 +01:00
NEZNAMY 016633e494 BelowName - Speed up reloads by caching values for players (tested with 100 bots, reloads were 2x faster) 2023-03-13 19:22:00 +01:00
NEZNAMY 1db862ab56 NameTags - Speed up reloading (tested with 100 bots, reload was 3x faster) 2023-03-13 19:15:45 +01:00
NEZNAMY 3563786310 PlayerList - Drastically speed up reloads (up to 10+ times with high player counts) 2023-03-13 19:01:26 +01:00
NEZNAMY ac8851dd6a Cache EnumSets for info packet for better performance 2023-03-13 18:22:16 +01:00
NEZNAMY 53ab2d9793 Commands - Do not load widths for widthcheck command unless command is used 2023-03-13 18:03:55 +01:00
NEZNAMY 2a58c86ffc Move code from initializer to load 2023-03-13 16:35:30 +01:00
NEZNAMY fa46d527ae Spectator Fix - Don't send useless packets on load/unload 2023-03-13 15:17:13 +01:00
NEZNAMY 667bd38305 Velocity - Fix Velocity being Velocity exception 2023-03-13 14:51:52 +01:00
NEZNAMY faba439466 Global PlayerList - Send all affected entries in a single packet, reducing amount of packets sent and improving performance 2023-03-13 14:47:29 +01:00
NEZNAMY c301157758 Global PlayerList - No longer delay task on quit as I was not able to reproduce the bug; Update placeholders periodically as they didn't update properly on vanish change anyway 2023-03-13 14:14:06 +01:00
NEZNAMY 8d09d425a4 Global PlayerList - No longer prevent other sources from removing players, better organize adding on server switch as well 2023-03-13 13:26:12 +01:00
NEZNAMY 11f03d5a10 Simplify 2023-03-13 12:58:19 +01:00
NEZNAMY 83625202a1 Merge pull request #841 from NEZNAMY/better-pipeline-injection
Better pipeline injection
2023-03-12 14:39:19 +01:00
Callum Seabrook eb4b715a88 Move pipeline injection to its own package 2023-03-12 13:35:47 +00:00
Callum Seabrook 89dce941cf Add RequiredArgsConstructor to NettyPipelineInjector 2023-03-12 13:31:58 +00:00
Callum Seabrook 6371b67e9e Removed player Channel and moved Netty injection to NettyPipelineInjector 2023-03-12 13:23:16 +00:00
NEZNAMY 966e27418a Bukkit - Attempt to fix error on ArrayList#remove 2023-03-11 15:35:31 +01:00
NEZNAMY 4adf7d1734 Bukkit - Fix NoSuchElementException that doesn't make sense 2023-03-11 15:25:06 +01:00
NEZNAMY 1a4c4a6fe8 Add more debug messages about feature loading times 2023-03-11 15:14:12 +01:00
NEZNAMY 7ff36592ae Do not re-initialize ErrorManager 2023-03-11 14:27:23 +01:00
NEZNAMY 1b513412d2 Remove redundant import 2023-03-10 13:20:14 +01:00
NEZNAMY f2bb43fbcd Make tabExpansion variable not null and add default empty implementation 2023-03-10 13:16:22 +01:00
NEZNAMY df5d07d885 Include forgotten code from previous commit 2023-03-10 13:13:21 +01:00
NEZNAMY 0ad2f33c4c Further clean up feature loading and mutual hooks 2023-03-10 12:45:28 +01:00
NEZNAMY dee48fccb3 Partially de-spaghetti feature loading and mutual hooking 2023-03-09 00:13:15 +01:00
NEZNAMY 9ca372ab13 Velocity is XD 2023-03-07 23:07:26 +01:00
NEZNAMY 58a849a902 Update README.md 2023-03-06 18:15:04 +01:00
NEZNAMY 895072ec35 Update README.md 2023-03-06 18:07:14 +01:00
NEZNAMY 2b2c4d2c39 Update README.md 2023-03-06 12:03:45 +01:00
NEZNAMY d534b6e2e8 Layout - Make fixed slots take priority over player groups if a slot is used in both 2023-03-05 15:31:14 +01:00
NEZNAMY 783e9d9931 Fix wrong values in widths.txt 2023-03-02 21:06:15 +01:00
NEZNAMY a109d9b55b Enable widthcheck command and fix error in it 2023-03-02 20:54:28 +01:00
NEZNAMY 5ce59ce44f Fix compilation 2023-03-02 20:33:37 +01:00
NEZNAMY 1e9195a9bc Velocity - Add try/catch for calling new methods on old versions 2023-03-01 18:49:41 +01:00
NEZNAMY 3099d16468 Create SECURITY.md 2023-03-01 12:23:39 +01:00
NEZNAMY c9c6af346c Add new issue templates 2023-03-01 12:18:23 +01:00
NEZNAMY af80a43628 Catch Throwable in pipeline instead of Exception to reduce chance of plugin causing player disconnect in future unsupported versions 2023-02-28 23:33:31 +01:00
NEZNAMY dc3c98ec91 Bukkit - Change how ViaVersion is detected (to avoid wrong detection due to a plugin order load bug in 1.17.1) 2023-02-25 18:41:25 +01:00
NEZNAMY dffa2c83f6 Typo 2023-02-24 23:45:40 +01:00
NEZNAMY dc66f253a7 Config converter - Remove placeholder that got deleted 2023-02-24 23:42:35 +01:00
NEZNAMY 17498cbfc2 BungeeCord - Fix bytebuf deserialization from previous commits 2023-02-24 23:15:01 +01:00
NEZNAMY 96e4d30168 Include 1.5 in supported version range 2023-02-24 16:48:56 +01:00
NEZNAMY c9d1934bb9 Use lombok for empty private constructor 2023-02-24 16:33:39 +01:00
NEZNAMY 8bec083194 Remove redundant duplicated checks 2023-02-24 16:30:34 +01:00
NEZNAMY abf047be23 Fix global playerlist class being instantiated twice 2023-02-24 16:22:02 +01:00
NEZNAMY 4a95399d56 3.3.1-SNAPSHOT 2023-02-24 16:19:01 +01:00
NEZNAMY 885bf5154e NameTags - Fix updating nametag visibility of players in disabled world/server 2023-02-24 15:43:58 +01:00
NEZNAMY 3e146fc496 Simplify 2023-02-24 15:41:30 +01:00
NEZNAMY 95710bcaf5 Sorting - Fix team name change registering teams for players in disabled worlds/servers 2023-02-24 15:37:40 +01:00
NEZNAMY edd620f17d BelowName - Fix text refreshing packets being sent to players in disabled worlds/servers 2023-02-24 15:25:09 +01:00
NEZNAMY 9c466d8b1e Update comment 2023-02-24 14:57:56 +01:00
NEZNAMY b385ab70fb Simplify 2023-02-24 14:52:22 +01:00
NEZNAMY 140224840b Remove double registration of sorting feature 2023-02-23 21:24:10 +01:00
NEZNAMY 2078cd5a5f Downgrade sponge API dependencies to confirm support 2023-02-21 18:46:43 +01:00
NEZNAMY 27bae7fdbd 3.3.0 2023-02-21 17:03:39 +01:00
NEZNAMY 174b4214de Bukkit - Fix error from previous commits 2023-02-21 13:52:21 +01:00
NEZNAMY 4ac524840c Remove non-existing branch from build.yml 2023-02-20 20:42:48 +01:00
NEZNAMY dd4ce4e2c3 Remove redundant library (gson) 2023-02-20 17:34:38 +01:00
NEZNAMY 2a03d69628 Add @SuppressWarnings annotation to a method 2023-02-20 17:33:44 +01:00
NEZNAMY c28252e6ce RGB - Fix redundant color codes in conversion to legacy, causing issues with limits (#827) 2023-02-20 17:02:20 +01:00
NEZNAMY da1768d833 Further code cleanup 2023-02-20 16:43:49 +01:00
NEZNAMY b58c3e6b47 Fix typos 2023-02-20 12:11:58 +01:00
NEZNAMY c7575bdc8f Remove redundant throws and empty method 2023-02-20 12:00:01 +01:00
NEZNAMY e275d22061 Bukkit - Fix startup on <1.8 2023-02-20 00:35:50 +01:00
NEZNAMY b5600ef22a Fix merge conflict 2023-02-20 00:29:05 +01:00
NEZNAMY b8e14c9256 Merge branch 'master' of https://github.com/NEZNAMY/TAB
 Conflicts:
	krypton/src/main/kotlin/me/neznamy/tab/platforms/krypton/KryptonPlaceholderRegistry.kt
2023-02-19 23:58:11 +01:00
NEZNAMY 1af5b9a308 Bukkit - Further split NMS loading and packet creation 2023-02-19 23:58:01 +01:00
Callum Seabrook 2dd719c3a5 Added Spark placeholder support back to Krypton 2023-02-19 21:08:04 +00:00
NEZNAMY 45d94694cd Bukkit - Split NMS fields and initialization into multiple classes 2023-02-19 21:15:10 +01:00
NEZNAMY 3ce8c6a192 Code style - Extract duplicated code 2023-02-19 17:41:06 +01:00
NEZNAMY 7deb86f105 Fix typo 2023-02-19 17:28:25 +01:00
NEZNAMY d9b4f6a43f Bukkit - Move data watcher serializer initialization 2023-02-19 17:15:58 +01:00
NEZNAMY 54a7fb8721 Code style - Extract duplicated code for permission plugin detection 2023-02-19 16:08:02 +01:00
NEZNAMY d1dcb2f437 Merge remote-tracking branch 'origin/master' 2023-02-18 17:35:03 +01:00
NEZNAMY a92bab617a Unlimited nametags - Fix error caused by wrong method being called 2023-02-18 17:34:52 +01:00
Callum Seabrook 57e34bc595 Updated to latest Krypton and added TAB prefix to console 2023-02-15 23:58:25 +00:00
Callum Seabrook 953baa273c Build Krypton targeting Java 8 2023-02-15 20:23:39 +00:00
NEZNAMY c403cb3187 Fix startup after recode 2023-02-15 21:03:19 +01:00
NEZNAMY ffd6dc5bb9 Disable krypton compilation to fix Sponge 7 startup (due to a Sponge 7 bug) 2023-02-15 20:53:06 +01:00
NEZNAMY 0f6504a3dc Remove unused local variable 2023-02-15 20:28:55 +01:00
NEZNAMY f376fea598 Formatting 2023-02-15 20:26:50 +01:00
NEZNAMY 4896cdff91 Further extend lombok usage 2023-02-15 19:17:29 +01:00
NEZNAMY b4c87431bc Scoreboard - Fix placeholders rarely not refreshing in title 2023-02-15 19:16:29 +01:00
NEZNAMY 1cffbab97d Remove plugin message text from /tab cpu due to being impossible to read 2023-02-15 15:14:30 +01:00
NEZNAMY 9b0711075a Code style - Use constants in more places 2023-02-15 15:06:15 +01:00
NEZNAMY 17a8e902eb Velocity - Use data folder given by the platform instead of manually defining it 2023-02-15 15:01:16 +01:00
Callum Seabrook 4bdb5ba245 Use more constants for plugin info 2023-02-15 12:16:48 +00:00
NEZNAMY fd7748d280 Merge remote-tracking branch 'origin/master' 2023-02-15 12:51:36 +01:00
NEZNAMY 317b0292ff Fix error on sponge (and redundancy on bukkit) 2023-02-15 12:51:19 +01:00
Callum Seabrook b87be649bc Made ARMOR_STAND_ID constant and removed packet builder singleton for Sponge 2023-02-15 11:51:09 +00:00
Callum Seabrook e2dda54011 Added sneaking support for unlimited nametags Sponge 2023-02-15 11:43:05 +00:00
NEZNAMY d17518c39b Sponge7 - Fix broken scoreboards 2023-02-14 23:19:33 +01:00
NEZNAMY 48541dd0bd Placeholders - Fix NPE 2023-02-14 22:29:28 +01:00
NEZNAMY b83b023fee Sponge8 - Add ViaVersion hook 2023-02-14 22:29:13 +01:00
NEZNAMY 60e0c78033 Add Sponge7 module 2023-02-14 22:28:32 +01:00
NEZNAMY a395f7f01f Unlimited NameTags - Fix entity type detection from previous commits 2023-02-14 18:46:17 +01:00
NEZNAMY 09c36ef69e Relocate yamlassist as well 2023-02-14 18:28:45 +01:00
NEZNAMY 9d5fa685a0 Rename folder as well 2023-02-14 18:25:08 +01:00
NEZNAMY 6794f593fa Rename sponge module to sponge8 2023-02-14 17:39:41 +01:00
NEZNAMY 5e9965276f Code style - Change how packet builder is initialized in Platform class 2023-02-14 16:54:58 +01:00
NEZNAMY 1473038955 Code style - Fix redundant imports, throws, extract constants, grammar 2023-02-14 16:39:21 +01:00
Callum Seabrook 2041ca57f3 Finished Sponge support 2023-02-14 14:38:09 +00:00
NEZNAMY 098782d820 3.3.0-SNAPSHOT 2023-02-14 12:53:10 +01:00
NEZNAMY 87e9a6defd 3.2.5 2023-02-13 16:40:36 +01:00
NEZNAMY 3d896ff828 More abstraction of unlimited nametag mode (also a small fix from previous commit) 2023-02-13 14:25:38 +01:00
NEZNAMY bf93240888 Unlimited NameTags - Make armor stands visible for spectators (#785) 2023-02-13 13:57:49 +01:00
NEZNAMY 0b0e30c3c9 Disable sponge module until compilation is fixed 2023-02-13 12:54:05 +01:00
NEZNAMY 84d3816bd1 Fix NPE 2023-02-12 12:51:37 +01:00
NEZNAMY 04ff606947 Merge branch 'master' of https://github.com/NEZNAMY/TAB 2023-02-12 12:29:06 +01:00
NEZNAMY 1cb8e6e238 Almost finish Sponge 8 2023-02-12 12:29:01 +01:00
NEZNAMY 4a2226170d Merge pull request #819 from Tanguygab/master
added support for *server or *world (just like server* and world*)
2023-02-12 12:27:03 +01:00
Tanguygab 1469124cfc added support for *server or *world (just like server* and world*) 2023-02-12 11:41:11 +01:00
NEZNAMY 0826095e73 Merge branch 'master' of https://github.com/NEZNAMY/TAB 2023-02-11 15:34:05 +01:00
NEZNAMY 1bd698adde Code style - Create custom cache object to avoid code duplication 2023-02-11 14:33:31 +00:00
Callum Seabrook 1058d269ff Start of rewrite of Sponge for v8 over v7 2023-02-11 14:13:05 +00:00
NEZNAMY bacd87b78e Code style - Create custom cache object to avoid code duplication 2023-02-11 13:08:20 +01:00
Callum Seabrook 5befbe8780 Updated Sponge platform 2023-02-10 23:11:38 +00:00
Callum Seabrook e159b2adae Finished Sponge implementation (mostly) 2023-02-10 23:08:21 +00:00
Callum Seabrook 52f7418853 The start of Sponge 2023-02-10 23:08:21 +00:00
Callum Seabrook 76061f7ccd Set up Sponge skeleton project 2023-02-10 23:08:21 +00:00
NEZNAMY 7d39e21eae Fix mistake after recode 2023-02-11 00:07:10 +01:00
NEZNAMY fee3723474 Code style - More abstraction of features and feature loading 2023-02-10 23:06:52 +01:00
NEZNAMY 2f0e4c6888 Merge remote-tracking branch 'origin/master' 2023-02-10 12:58:49 +01:00
NEZNAMY b04cb6d3c5 Config converter - Reverse old config detection (#762) 2023-02-10 12:58:07 +01:00
Callum Seabrook a9228a698a Fixed NPE being thrown when player info data name is null for Krypton 2023-02-09 16:18:13 +00:00
NEZNAMY 27102495d8 Code style - Use lombok in more locations 2023-02-08 00:49:48 +01:00
NEZNAMY d1bf96ab33 Code style - Use lombok for getters/setters 2023-02-07 23:14:02 +01:00
NEZNAMY 3360dbb468 Update README.md 2023-02-07 20:21:14 +01:00
NEZNAMY d224e7584e Create CONTRIBUTING.md 2023-02-07 20:20:31 +01:00
Callum Seabrook 6373540076 Updated Krypton platform and removed Indra 2023-02-07 16:56:58 +00:00
NEZNAMY 5f78aca997 Hide proxy-only methods into proxy player object 2023-02-07 15:33:24 +01:00
NEZNAMY 145d944d33 Bukkit - Remove unused (and incorrectly implemented) code 2023-02-07 15:26:01 +01:00
NEZNAMY ac91940e3b Velocity - Send packet using wanted player uuid instead of random if entry does not exist (apparently it goes through even if not registered) 2023-01-31 21:36:26 +01:00
NEZNAMY ef8452be73 Code style - Simplify BungeeCord info packet read/write based on client version 2023-01-31 18:23:24 +01:00
NEZNAMY 47e0810697 Placeholders - Remove %essentialsnick% placeholder due to being pretty redundant (keeping empty implementation so users don't get it suddenly broken) 2023-01-31 17:11:45 +01:00
NEZNAMY 1f30f225c7 Code style - Use reflection for PremiumVanish API instead of direct code with dependencies 2023-01-31 16:17:33 +01:00
NEZNAMY fcbfd60ddb Code style - Call method directly when command sender is console 2023-01-31 15:55:28 +01:00
NEZNAMY 46f9033713 Code style - Add final modifier to variable 2023-01-31 15:54:48 +01:00
NEZNAMY 7e65018a0e Velocity - Switch to non-deprecated method 2023-01-31 15:51:28 +01:00
NEZNAMY 9ef3485968 Code style - Create a method for convenience to avoid duplicated code 2023-01-27 15:52:38 +01:00
NEZNAMY 257f8f1145 Commands - Remove properly length from debug output 2023-01-27 15:24:26 +01:00
NEZNAMY 8d65cbb0e5 3.2.5-SNAPSHOT 2023-01-26 10:35:08 +01:00
NEZNAMY 20d221e3ca Merge pull request #806 from NotAlexNoyle/proposal
Propose adopting open source license
2023-01-25 12:17:56 +01:00
NEZNAMY 94072acf10 3.2.4 2023-01-25 10:39:44 +01:00
NEZNAMY 0422cc2597 Update issue templates 2023-01-24 14:00:13 +01:00
NEZNAMY 58f61e645b 3.2.4-SNAPSHOT 2023-01-24 10:45:11 +01:00
NEZNAMY 5f416bd9e5 Unlimited NameTags - Avoid Bukkit API NPE (#800, #804) 2023-01-24 10:44:35 +01:00
NotAlexNoyle 64528c913c Propose adopting open source license 2023-01-23 22:33:21 -05:00
NEZNAMY 357e7c6a49 Revert "Remove redundant try/catch"
This reverts commit 1777d8bf01.
2023-01-23 14:39:54 +01:00
NEZNAMY 81dd202053 3.2.3 2023-01-21 14:58:34 +01:00
NEZNAMY 189797aa73 Bukkit - Use the other constructor for player info packet which is cleaner (also #797) 2023-01-21 00:18:19 +01:00
NEZNAMY 1ae2ef7cad Fix compilation 2023-01-21 00:17:02 +01:00
NEZNAMY de14e14d33 Revert "Placeholders - Add timeout for placeholders to return value, causing TAB to freeze"
This reverts commit 37caed3123.
2023-01-19 22:30:09 +01:00
NEZNAMY 19892c14c1 Revert "Placeholders - Increase placeholder retrieve timeout to 500ms (#792)"
This reverts commit 6d85875fde.
2023-01-19 22:29:59 +01:00
NEZNAMY 2e00c4c002 Revert "NameTags - Fix error that doesn't make sense (#794)"
This reverts commit 12f5dd52b4.
2023-01-19 22:29:52 +01:00
NEZNAMY 97aa367629 Revert "Fix thread pool not being single threaded (maybe #781?)"
This reverts commit 87cc9a030b.
2023-01-19 22:28:22 +01:00
NEZNAMY 87cc9a030b Fix thread pool not being single threaded (maybe #781?) 2023-01-19 22:01:11 +01:00
NEZNAMY 8ba83d1cb1 BossBar - Fix errors when progress is below 0 or above 100 2023-01-19 16:59:05 +01:00
NEZNAMY 9f0e60bd47 Per world PlayerList - Remove redundant task schedule to main thread 2023-01-19 16:58:45 +01:00
NEZNAMY 93b2a25b2e Merge pull request #795 from Chris6ix/update-actions
Update Actions
2023-01-17 22:01:37 +01:00
Chris 4242d7a839 Remove Test Build Trigger 2023-01-17 21:33:33 +01:00
Chris 0ddb99bd46 Trigger Test Build 2023-01-17 21:29:34 +01:00
Chris 969672e3ad Update Actions 2023-01-17 21:26:40 +01:00
NEZNAMY 2423fbb150 Update README.md 2023-01-17 20:28:47 +01:00
NEZNAMY a99928dbf5 Placeholders - Colorize output of relational placeholders as well 2023-01-17 20:25:06 +01:00
NEZNAMY 12f5dd52b4 NameTags - Fix error that doesn't make sense (#794) 2023-01-17 15:38:20 +01:00
NEZNAMY 2bd105446e Bukkit - Properly send RGB messages into console (only for Paper+, Spigot doesn't support RGB at all) 2023-01-17 14:11:51 +01:00
NEZNAMY 6d85875fde Placeholders - Increase placeholder retrieve timeout to 500ms (#792) 2023-01-16 18:49:23 +01:00
NEZNAMY 42810aa490 3.2.3-SNAPSHOT 2023-01-16 18:47:42 +01:00
NEZNAMY bd31521bd3 3.2.2 2023-01-15 12:02:05 +01:00
NEZNAMY ec0deb8378 Yellow Number - Disable the feature for Bedrock players 2023-01-12 21:57:56 +01:00
NEZNAMY ae66b6e9a1 RGB - Fix MiniMessage->Bukkit conversion being after Bukkit->TAB, making it not translate anymore 2023-01-12 14:55:41 +01:00
NEZNAMY 3b86becebd Header/Footer - Do not add &r after \n anymore 2023-01-12 14:53:38 +01:00
NEZNAMY 4a8d86825b Configuration - Small changes to default configuration files 2023-01-10 18:56:34 +01:00
NEZNAMY 54a3bd81b4 Global PlayerList - Increase player removal prevention delay to 2000ms from 500ms 2023-01-10 16:49:16 +01:00
NEZNAMY b6768cca99 CPU manager - Add try/catch for task scheduling (#781) 2023-01-10 16:48:28 +01:00
NEZNAMY 60c414deed Bukkit - Remove redundant methods in nms loader 2023-01-05 16:48:16 +01:00
NEZNAMY 009283a83f Update README.md 2023-01-05 16:04:38 +01:00
Callum Seabrook 4a430b97df Merge pull request #779 from JT122406/master
Updates
2023-01-04 22:50:08 +00:00
NEZNAMY 722333da2e Fix RejectedExecutionException (#769) 2023-01-04 19:15:56 +01:00
NEZNAMY 1215af5262 Bukkit - Add 1.5.0 support 2023-01-04 18:28:24 +01:00
NEZNAMY 254088c37b Bukkit - Repackage nms loaders (also fix startup on Thermos) 2023-01-04 18:14:39 +01:00
J.T. McQuiggandCallum Seabrook cb2ce4acca Update gradle/libs.versions.toml
Co-authored-by: Callum Seabrook <callum.seabrook@prevarinite.com>
2023-01-04 11:20:55 -05:00
J.T.McQuigg 872adca8fd Updates 2023-01-03 23:09:35 -05:00
J.T.McQuigg f37cc0bdd8 Gradle 7.6 2023-01-03 23:02:04 -05:00
NEZNAMY 4063578ac3 Code style - Remove duplicate .toLowerCase() 2023-01-02 20:45:23 +01:00
NEZNAMY 2528de7eeb Code style - Use built-in String#trim function 2023-01-02 20:25:11 +01:00
NEZNAMY 37caed3123 Placeholders - Add timeout for placeholders to return value, causing TAB to freeze 2022-12-23 14:49:31 +01:00
NEZNAMY 27fe9dfb12 Commands - Make player command update player instantly if uuid is used instead of player name 2022-12-21 22:00:58 +01:00
NEZNAMY 0169cbd4d2 Bukkit - Fix wrong method taken sometimes, causing player kick with unlimited nametag mode 2022-12-20 15:08:18 +01:00
NEZNAMY ed760aec08 Aligned PlayerList - Fix rare error that makes no sense 2022-12-20 15:04:48 +01:00
NEZNAMY 858cbcefeb Code style - Add toString override 2022-12-20 15:04:21 +01:00
NEZNAMY 8a87d581a9 Scoreboard - Do not send packets to players who cannot see that specific scoreboard 2022-12-18 17:16:26 +01:00
NEZNAMY 6d642f4e51 NameTags - Fix players getting unregistered with wrong team name 2022-12-17 19:12:00 +01:00
NEZNAMY aca63640bc Attempt to fix rare NPE 2022-12-17 19:08:32 +01:00
NEZNAMY 1845a35315 3.2.2-SNAPSHOT 2022-12-16 22:25:39 +01:00
NEZNAMY cab5f89a95 Remove redundant check 2022-12-16 22:03:21 +01:00
NEZNAMY 1777d8bf01 Remove redundant try/catch 2022-12-16 21:14:47 +01:00
NEZNAMY 91b0bfaa9d Configuration - Simplify file copying, since default files already are encoded with UTF-8 encoding 2022-12-16 15:04:52 +01:00
NEZNAMY f1cf994d10 3.2.1 2022-12-16 11:27:48 +01:00
NEZNAMY 69957be933 Pet name fix - Fix excessive CPU usage caused by heavy operation and not caching the result 2022-12-15 00:22:23 +01:00
NEZNAMY b78eb5efb6 Bukkit - Remove forgotten debug stack trace printing 2022-12-15 00:21:28 +01:00
NEZNAMY 3577ad1964 Bukkit - Fix NPE in packet creation on <1.13 (#763) 2022-12-14 18:02:04 +01:00
NEZNAMY 4510491177 3.2.0 2022-12-12 09:46:21 +01:00
NEZNAMY 01b3a12377 1.19.3 support 2022-12-12 09:46:12 +01:00
NEZNAMY 64ae9863fb Bukkit - Drop old event API system 2022-12-10 12:27:51 +01:00
NEZNAMY ecd315a407 Sorting - Fix error from previous commit (.toLowerCase made string longer) 2022-12-08 11:20:58 +01:00
NEZNAMY 678eed288e Conditions - Add OR type for anonymous conditions using "|" symbol 2022-12-06 10:32:41 +01:00
NEZNAMY 9510455cb1 Conditions - Fix anonymous conditions not updating from previous commit 2022-12-06 10:31:29 +01:00
NEZNAMY e925ce23d0 Conditions - Fix nested conditions not working if they are defined below the condition using them 2022-12-06 09:51:16 +01:00
NEZNAMY c68cad6a1e Global PlayerList - Fix feature breaking nick/skin changes (minecraft mechanic changed in 1.19) (#752) 2022-12-06 09:50:00 +01:00
NEZNAMY 01d6eda4fb Configuration - Use luckperms placeholders instead of vault in default configuration (and make them return empty value if LP is not found) 2022-12-04 14:19:21 +01:00
NEZNAMY 73e7119bbc Configuration - add hidden server-name option for %server% value (useful with MySQL) 2022-12-04 11:49:59 +01:00
NEZNAMY cea781382a Sorting - Fix wrong team name being unregistered (#727) 2022-12-03 21:18:38 +01:00
NEZNAMY cf25b84e86 Commands - Fix debug command showing sorting is disabled even if layout is enabled for sorting 2022-12-03 21:16:29 +01:00
NEZNAMY 86e1d22390 Sorting - Only use 1 character for sorting by groups, permissions and predefined values; Improve debug output of sorting results 2022-12-03 12:16:38 +01:00
NEZNAMY 1625be111f Global PlayerList - Make server names in server groups and spy-servers not case-sensitive 2022-12-02 23:18:40 +01:00
NEZNAMY 00cda3b2aa Placeholders - Load all used placeholders on join in placeholder manager to make cpu usage appear under that "feature" instead of a feature actually using the placeholders 2022-12-01 22:46:40 +01:00
NEZNAMY 85a00a4436 Code style - Extract minimum placeholder refresh interval into an editable constant 2022-12-01 22:36:33 +01:00
NEZNAMY 37aec1a497 Global PlayerList - Add %playerlist-group_<group>% placeholder for online count in each group 2022-12-01 22:32:43 +01:00
NEZNAMY ef637616ee Placeholders - Improve error message 2022-11-27 17:13:24 +01:00
NEZNAMY af3b5067fb BossBar - Ignore players in disabled worlds/servers in announce command (#748) 2022-11-25 11:23:48 +01:00
NEZNAMY 53e5b15f96 Tab Expansion - Fix error in nested placeholder parsing 2022-11-24 11:01:55 +01:00
NEZNAMY 6a3afae607 Implement empty method 2022-11-16 12:24:03 +01:00
NEZNAMY 2e05c7d9d1 Another attempt for #727 2022-11-15 19:15:49 +01:00
NEZNAMY fb698a04b7 Configuration - Merge default config.yml files into one 2022-11-12 19:11:36 +01:00
NEZNAMY 52bdf30ddb Merge remote-tracking branch 'origin/master' 2022-11-09 22:34:22 +01:00
NEZNAMY a92f07aa40 Tab Expansion - Resend values to bridge on server switch (#740) 2022-11-09 22:34:09 +01:00
NEZNAMY 003ff7f99d Merge pull request #739 from CoachYT1/patch-1
bump org.yaml:snakeyaml to 1.33
2022-11-09 21:59:08 +01:00
NEZNAMY 47b9806ae7 Tab Expansion - Parse nested placeholders in replace function 2022-11-07 22:26:17 +01:00
CoachYT d2a7c65e08 bump org.yaml:snakeyaml to 1.33
snakeyaml 1.30 is affected by 5 vulnerabilities and should be upgraded to the latest version
2022-11-07 17:53:24 +01:00
NEZNAMY e232336a5f Add check for modifying non-existing teams (#727) 2022-11-06 22:42:23 +01:00
NEZNAMY 8816c75212 BungeeCord - Fix crash on 1.7 caused by unregistering non-existing objectives (login packet cleared them) (#727) 2022-11-04 13:31:34 +01:00
NEZNAMY f9d54751ba Fix rare ConcurrentModificationException 2022-11-04 12:53:00 +01:00
NEZNAMY 43d41ee761 BungeeCord - Improve unsupported BungeeCord build message 2022-11-01 17:55:43 +01:00
NEZNAMY 4512ba8d5e NameTags - Print a console warn if both unlimited nametags and invisible nametags are enabled 2022-10-30 17:56:00 +01:00
NEZNAMY 8b55bca564 Remove redundant variable 2022-10-30 13:40:32 +01:00
NEZNAMY d8d54970d3 Code style - Clean up vanish check code 2022-10-30 13:29:45 +01:00
NEZNAMY 15ea4482f9 Bukkit - Drop direct Essentials hook for vanishing as it supports metadata 2022-10-30 13:27:24 +01:00
NEZNAMY 87f9f38eac Update issue templates 2022-10-29 18:35:11 +02:00
NEZNAMY dba559f041 Layout - Fix startup error caused by invalid number as slot 2022-10-29 12:17:04 +02:00
NEZNAMY c610b6f323 PlayerList - Fix name applying on server switch when pipeline injection is disabled 2022-10-26 17:36:08 +02:00
NEZNAMY a5fb900e19 API - Add back TabPlayer#getTeamName() 2022-10-24 14:05:39 +02:00
NEZNAMY 09d6e455f5 Layout - Implement a fix for compatibility with plugins which add empty player name into their 2022-10-21 19:55:59 +02:00
NEZNAMY e68097b0f4 Layout - Fix startup error if slots is a single number instead of interval 2022-10-16 15:32:26 +02:00
NEZNAMY 0744fed953 Merge branch 'master' of https://github.com/NEZNAMY/TAB 2022-10-16 14:40:42 +02:00
NEZNAMY de0adf4067 MySQL - Attempt to fix startup error (#717) 2022-10-16 13:12:54 +02:00
NEZNAMY 76bf2b3efc Update links in README 2022-10-16 13:11:56 +02:00
NEZNAMY c089badeb4 Configuration - Remove owner and admin settings from default configuration 2022-10-15 19:15:38 +02:00
NEZNAMY b3b99d366a Placeholders - Fix relational placeholders updating causing normal placeholders to not refresh 2022-10-14 19:28:05 +02:00
NEZNAMY 4a36486f65 Bukkit - Fix startup on 1.8 2022-10-08 12:41:05 +02:00
NEZNAMY 75126d00d9 BossBar - Fix countdown placeholder not activating on usage in PlaceholderAPI 2022-10-06 16:43:06 +02:00
NEZNAMY 17ebf95d5b BossBar - Fix announcement bars disappearing on refresh 2022-10-06 16:42:32 +02:00
NEZNAMY c764420cfe Code Style - Simplify field value assignment 2022-10-06 15:33:50 +02:00
Callum Seabrook 28f05fc2af Changed publishing artifact IDs to begin with "tab-" 2022-10-06 12:02:28 +01:00
Callum Seabrook a420892887 Fixed publishing ID 2022-10-06 11:54:06 +01:00
NEZNAMY d910dc5913 Header / Footer - Prioritize world over server in config.yml as well 2022-10-06 11:11:00 +02:00
NEZNAMY c9c1cbc349 Layout - Fix anti-override for playerlist names being disabled even when no layout is visible 2022-09-26 11:02:14 +02:00
NEZNAMY fd4704f75e 3.1.5 2022-09-20 15:46:28 +02:00
NEZNAMY 5400ca637f Global PlayerList - Do not fill display name for 1.7 players 2022-09-19 18:23:16 +02:00
NEZNAMY 79d2610117 Global PlayerList - Fix server switch when pipeline injection is disabled 2022-09-17 18:38:06 +02:00
NEZNAMY 6a51f4cb9d BungeeCord - Fix 1.7 players not being processed fully on server switch (reapplying scoreboards) 2022-09-13 18:33:52 +02:00
NEZNAMY c190776665 Scoreboard - Fix show command enabling scoreboard for players who disabled it using toggle command 2022-09-13 18:32:54 +02:00
NEZNAMY 3765a1232e Merge pull request #697 from JT122406/master
Updates and Velocity Deprecation Fix
2022-08-27 19:48:00 +02:00
J.T. McQuigg 28866eba21 More Updates and Build Fix 2022-08-27 13:07:28 -04:00
J.T. McQuigg 08adee3dc3 Recomment this out for PR 2022-08-27 11:57:34 -04:00
J.T. McQuigg 8a1adaf2cd More Updates 2022-08-27 11:57:08 -04:00
J.T. McQuigg fdb9accaa6 Updates and don't use Deprecation in Velocity module 2022-08-27 11:42:15 -04:00
NEZNAMY 4f7656748b Merge pull request #695 from Tanguygab/master
added StartWith `|-` and EndsWith `-|` condition types
2022-08-25 22:25:48 +02:00
Tanguygab 03e4495ac7 added |- and -| conditions 2022-08-25 15:15:21 +02:00
NEZNAMY 01af5cb9e1 Placeholders - Fix nested placeholders not being applied when updating from nested?!! (#694) 2022-08-24 16:52:01 +02:00
NEZNAMY 8d49f32df2 Code style - Change the way API instance is set 2022-08-22 20:30:16 +02:00
NEZNAMY 8a955b3bc8 Javadoc - Further improve documentation 2022-08-22 20:27:20 +02:00
NEZNAMY ead40cb413 Merge pull request #691 from Tanguygab/master
Commands - Added target and -s arguments for /tab nametag preview/toggle (#690)
2022-08-22 16:22:32 +02:00
Tanguygab 5e07f78d4f updated messages.yml 2022-08-22 16:20:43 +02:00
Tanguygab c7d98795bc Revert "* for all players in /tab scoreboard show"
This reverts commit e4f33b58f7.
2022-08-22 16:13:46 +02:00
Tanguygab 9f637e3d6a added target and -s arguments for /tab nametag preview/toggle 2022-08-22 16:09:23 +02:00
Tanguygab 2d5f074c78 Merge remote-tracking branch 'upstream/master' 2022-08-22 15:35:23 +02:00
NEZNAMY 3be6ba484d API - Fix show_item hover event on 1.16+ 2022-08-18 22:36:43 +02:00
NEZNAMY d9d74e7a32 Placeholders - Fix NPE in %essentialsnick% event listener due to Essentials bug (#684) 2022-08-18 12:46:54 +02:00
NEZNAMY 887306a5ed Bukkit - Include 1.19.2 in supported version range 2022-08-16 01:25:15 +02:00
NEZNAMY 4b2542eb4f Global Playerlist - Add config option to disable (and enable) profile key filling (#680) 2022-08-15 13:28:56 +02:00
NEZNAMY 66bd3baa3e Layout - Add config option to show vanished players in layout 2022-08-14 15:41:19 +02:00
NEZNAMY bf32004f8f Layout - Do not format original entries in any way (can cause spaces) 2022-08-13 17:50:28 +02:00
NEZNAMY bfb2df9c95 Commands - Show storage type in debug output 2022-08-13 17:44:46 +02:00
Callum Seabrook ddeb05e408 Merge pull request #662 from JT122406/Updates
Update Gradle Wrapper to 7.5
2022-08-12 16:58:38 +01:00
Callum Seabrook 9312d61258 Fix some more BS 2022-08-12 16:49:30 +01:00
Callum Seabrook d44909bc42 Fixed some BS 2022-08-12 16:41:26 +01:00
Callum Seabrook 1d77df335c Switched to Indra for publishing and improved code reuse in build scripts 2022-08-12 16:29:12 +01:00
NEZNAMY a268dc25f4 BungeeCord - Use direct code for proxy module again 2022-08-12 15:46:14 +02:00
NEZNAMY 8c5696faa0 Bukkit - Register universal placeholders after bukkit ones to fix reference issue with nested placeholders 2022-08-12 15:05:40 +02:00
NEZNAMY 94f3ccfb7d Javadoc - Further improve documentation 2022-08-12 15:04:49 +02:00
NEZNAMY 576329214d Add 1.19.2 to known versions 2022-08-11 17:57:49 +02:00
NEZNAMY 5c13c2e225 Velocity - Remove join processing delay since the required delay is already included elsewhere 2022-08-11 17:49:42 +02:00
NEZNAMY 1070f85617 Placeholders - Retry updateValue if player is not loaded yet (might fix #564) 2022-08-11 17:48:26 +02:00
NEZNAMY 7c9dc87fcb NameTags - Make canSeeFriendlyInvisibles flag configurable 2022-08-09 14:12:14 +02:00
NEZNAMY 363e58bf91 API - Expose another method 2022-08-04 17:06:30 +02:00
NEZNAMY daca3f5b71 3.1.4 2022-08-04 15:43:53 +02:00
NEZNAMY a7d2ec084b Use profile key in player info packet (#673) 2022-08-03 12:57:48 +02:00
NEZNAMY 167f8cd0ff BungeeCord - Remove Waterfall tablist rewrite hook since the option doesn't work as I expected 2022-08-03 11:14:10 +02:00
NEZNAMY 170307f45f Catch everything 2022-07-29 15:49:59 +02:00
NEZNAMY 2f36377780 Revert "Placeholder output replacements - Apply again after applying nested placeholders"
This reverts commit 2706cd5881.
2022-07-29 12:48:13 +02:00
NEZNAMY 48c565d85d 3.1.3 2022-07-28 17:59:15 +02:00
NEZNAMY 86b3cc4044 Sorting - Fix startup error caused by misconfiguration (#664) 2022-07-28 11:40:42 +02:00
NEZNAMY 6a2d5091b8 Bukkit - Add 1.19.1 support 2022-07-28 11:30:34 +02:00
J.T. McQuigg dc09e77190 Update Gradle Wrapper to 7.5 2022-07-26 17:16:56 -04:00
NEZNAMY 4fc139c0c6 Remove synchronized lock from sendCustomPacket method 2022-07-26 21:57:36 +02:00
NEZNAMY e5d800f469 API - Expose a few more methods 2022-07-26 21:56:16 +02:00
NEZNAMY 4879ac28b5 PingSpoof - Add Layout compatibility 2022-07-25 15:34:33 +02:00
NEZNAMY bd0badab48 Feature management - Don't deserialize objective packets if no feature is listening to them 2022-07-24 21:20:55 +02:00
NEZNAMY 5575a26d3b Placeholders - Use event instead of refresh task for %essentialsnick% placeholder 2022-07-24 20:27:43 +02:00
NEZNAMY d8cbe96949 BossBar - Fix issues with hidden-by-default enabled 2022-07-24 17:55:04 +02:00
NEZNAMY cfb506a7ff BossBar - Make Wither's size (nearly) zero on 1.8 (#654) 2022-07-24 13:28:18 +02:00
Tanguygab d5b0ff7f40 Merge remote-tracking branch 'upstream/master' 2022-07-24 13:11:11 +02:00
NEZNAMY 31d259210c Bukkit - Add support for mojang mapped jars 2022-07-21 12:56:23 +02:00
NEZNAMY 39112b8d41 Tab expansion - Add %tab_nametag_visibility% and rename %tab_ntpreview% to %tab_nametag_preview% 2022-07-20 00:14:38 +02:00
NEZNAMY 4c92286ebb Thread management - Increase max thread pool size to 20 2022-07-19 14:02:44 +02:00
NEZNAMY a317aeba85 Plugin message handling - Fix ClassCastException when a placeholder is externally registered as a server placeholder 2022-07-19 13:30:32 +02:00
NEZNAMY dcaf17294e Aligned PlayerList - Fix commit ebd67dd - Do not save config if no changes were made 2022-07-19 12:00:16 +02:00
NEZNAMY 0bc734689a Unlimited Nametags - Fix per-world formatting not applying on world switch 2022-07-19 00:22:11 +02:00
NEZNAMY d0c2c00cc9 BungeeCord - Respect Waterfall's tablist rewrite config option (#652) 2022-07-18 19:25:07 +02:00
NEZNAMY fd02328af9 Aligned PlayerList - Update widths.txt for 1.19 2022-07-18 14:55:05 +02:00
NEZNAMY 3b7de31324 Aligned PlayerList - Add a subcommand (disabled by default) for mass-verifying character widths 2022-07-18 14:52:44 +02:00
NEZNAMY ebd67dd025 Aligned PlayerList - Remove custom widths from config that match default value 2022-07-17 21:30:56 +02:00
NEZNAMY 4557a39ae2 RGB - Fix &r getting removed 2022-07-17 21:29:59 +02:00
NEZNAMY ce1eb299d3 Conditions - Fix conditions being 1 loop behind nested placeholders 2022-07-16 22:58:37 +02:00
Callum Seabrook 20ab3f0a72 Disabled JavaDoc generation for all but API and added property to enable for API 2022-07-16 20:11:58 +01:00
NEZNAMY d61f90c25c Code style - use api module instead of shared where possible 2022-07-16 20:56:59 +02:00
NEZNAMY 90474e7592 Layout - Fix startup error when a layout is missing groups section 2022-07-16 19:15:18 +02:00
NEZNAMY a2e28003bc Code style - Move TabConstants class to api module 2022-07-16 19:13:31 +02:00
NEZNAMY 6e409c3dcd Thread management - Use scheduled executor for repeating and delayed tasks 2022-07-16 18:39:13 +02:00
NEZNAMY 85a699c8de Commands - Only show announcement bars in auto-complete for bossbar announcement command 2022-07-16 18:33:57 +02:00
NEZNAMY a788d1fb23 Commands - Add missing permission check when toggling scoreboard using player argument 2022-07-16 14:14:35 +02:00
NEZNAMY ab5b72375c Code style - Remove redundant suppression and cast 2022-07-13 16:42:36 +02:00
NEZNAMY 3a023c51b5 Catch NoClassDefFoundError which is rarely thrown on reloads and leads to memory leaks 2022-07-13 16:24:17 +02:00
NEZNAMY 0ad91bcafe Sorting - Fix space in sorting types causing it to not work 2022-07-13 15:25:30 +02:00
NEZNAMY f41ea3bcab Unlimited Nametags - Improve heights to match vanilla & remove config option for space between lines, since original value was found 2022-07-13 14:57:07 +02:00
NEZNAMY 327dc4b416 Unlimited Nametags - Fix sneaking not being detected immediately on reload 2022-07-13 14:55:39 +02:00
NEZNAMY 27e7779456 Unlimited Nametags - Do not spawn for <1.8 players 2022-07-13 14:02:33 +02:00
NEZNAMY a7b2f5bb22 BungeeCord - Fix NPE on <1.8 clients 2022-07-13 13:32:53 +02:00
NEZNAMY 19fcb7c946 Layout - Do not send latency update packets to <1.8 clients 2022-07-13 13:32:23 +02:00
NEZNAMY 2706cd5881 Placeholder output replacements - Apply again after applying nested placeholders 2022-07-13 12:17:39 +02:00
NEZNAMY 4e2abd9c5b Bukkit - Fix startup on 1.7.x and 1.8.0 2022-07-13 12:04:21 +02:00
NEZNAMY 51ba2fa80a Placeholder output replacements - Fix exact match detection when input is not colored (new placeholderapi version) 2022-07-11 00:28:14 +02:00
NEZNAMY fd60cd0a21 Change the way the module is disabled 2022-07-06 22:00:52 +02:00
NEZNAMY 5025372c05 Revert "Code style - Remove unused method" 2022-07-06 21:15:54 +02:00
NEZNAMY 4806bd075f Configuration - Fix NPE when disabled world/server is null 2022-07-05 19:09:56 +02:00
NEZNAMY 370d17757a Add poor and unreliable MiniMessage support 2022-07-04 18:06:19 +02:00
NEZNAMY a648d7e75f Scoreboard - Fix NPE when using show command from console without player argument (#639) 2022-07-04 14:05:44 +02:00
NEZNAMY 518e1c5310 AlignedPlayerList - Fix rare NPE caused by multi-thread access 2022-07-04 13:46:29 +02:00
NEZNAMY 11539d8290 Commands - Allow removing per-world/server values 2022-07-04 13:44:08 +02:00
Tanguygab e4f33b58f7 * for all players in /tab scoreboard show 2022-07-04 13:34:04 +02:00
NEZNAMY 073caa9515 Compilation - Bump Authlib version 2022-07-04 13:33:00 +02:00
NEZNAMY 2b06b11916 Scoreboard - Fix same lines of text not appearing with use-numbers true 2022-06-24 21:16:45 +02:00
NEZNAMY 032b0f8a41 Configuration - Fix NPE when copying bukkit config to bungeecord 2022-06-19 14:05:59 +02:00
NEZNAMY 9391363f9b Unlimited Nametags - Disable on boat with chest as well (#625) 2022-06-19 12:36:35 +02:00
NEZNAMY 467fb2e9c7 Bukkit - Use reflection for LibsDisguises hook 2022-06-18 16:12:53 +02:00
NEZNAMY 257893b8de Downgrade dependency to fix compilation 2022-06-18 16:12:09 +02:00
NEZNAMY e919839de5 Merge pull request #623 from JT122406/Updates
Repo Bumps
2022-06-18 14:12:41 +02:00
J.T. McQuigg 77d372cbee Use new RedisBungee 2022-06-18 07:42:38 -04:00
J.T. McQuigg 03e9facaf7 Repo Bumps 2022-06-18 07:35:45 -04:00
NEZNAMY f3e459d911 Revert "BungeeCord - Retry plugin message processing if player isn't loaded for any reason (#564)"
This reverts commit dffac5deb8.
2022-06-17 14:15:39 +02:00
NEZNAMY 36feff0e04 Sorting - Fix off-by-1 possibly causing sorting to not work correctly for players without sorting group/permission 2022-06-16 18:53:42 +02:00
NEZNAMY 0320140a1b BungeeCord - Fix vanish/invisible status not resetting on server switch 2022-06-12 14:16:20 +02:00
NEZNAMY 4fb1b1c9f9 3.1.2 2022-06-11 18:01:17 +02:00
NEZNAMY 37f3896a41 Update to 1.19 2022-06-11 18:01:08 +02:00
NEZNAMY e1c152d95d Add missing change in previous commit 2022-06-11 18:00:08 +02:00
NEZNAMY dffac5deb8 BungeeCord - Retry plugin message processing if player isn't loaded for any reason (#564) 2022-06-11 17:57:18 +02:00
NEZNAMY 8aa3bbfad3 Scoreboard - Fix RGB codes not translating into legacy correctly in long lines 2022-06-09 23:10:44 +02:00
NEZNAMY 5bb4006e55 Scoreboard - Fix additional empty lines when use-numbers is enabled 2022-06-08 00:46:32 +02:00
NEZNAMY e06a406682 Clean up repositories 2022-06-08 00:45:21 +02:00
NEZNAMY a19719be4b Configuration - Remove deleted placeholder from default config 2022-06-03 23:47:41 +02:00
NEZNAMY 35856a9f3d Merge branch 'master' of https://github.com/NEZNAMY/TAB 2022-06-02 15:50:46 +02:00
NEZNAMY cf1d5d5ee2 Code style - Remove unused method 2022-06-01 20:23:16 +02:00
NEZNAMY f69a845e51 Bukkit - Implement chat message sending on <1.7 2022-05-31 12:21:07 +02:00
NEZNAMY db67e93bb8 Disable compilation of a module 2022-05-31 11:51:21 +02:00
NEZNAMY 313f089222 Aligned Suffix - Fix memory leak 2022-05-20 01:10:00 +02:00
NEZNAMY 458c08ded7 Tab expansion - Slightly optimize placeholder retrieving 2022-05-18 01:39:20 +02:00
NEZNAMY fe6cc7417f Placeholders - Fix refresh interval forwarding to bridge (#597) (2nd attempt) 2022-05-17 19:00:23 +02:00
NEZNAMY 181c94a808 Code style - Extract strings into constants 2022-05-13 00:42:30 +02:00
NEZNAMY 9ff6f02d8d Code style - Remove unused code and other minor changes 2022-05-12 22:49:41 +02:00
NEZNAMY 3cf74516d9 Bukkit - Remove unused data watcher registries 2022-05-12 22:25:18 +02:00
NEZNAMY 31f5502c16 BungeeCord - Delete TAB's bungeecord events (to make users switch to universal ones) 2022-05-12 22:04:37 +02:00
NEZNAMY 671d60bd72 API - Throw user-friendly exception if player is not loaded yet (#585) 2022-05-10 18:32:09 +02:00
NEZNAMY 294e866501 Placeholders - Fix refresh interval forwarding to bridge (#597) 2022-05-10 18:21:13 +02:00
NEZNAMY 96789100e3 Bukkit - Wrap incoming components instead of deserializing and then serializing them 2022-05-10 13:22:27 +02:00
NEZNAMY ea934fc7fb GroupManager - Add null check for player group from permission plugin 2022-05-08 12:48:06 +02:00
NEZNAMY d529b7b340 Sorting - Allow placeholders with ":" inside to work properly in PLACEHOLDER sorting type 2022-05-08 12:47:40 +02:00
NEZNAMY 092ca7f9f8 Aligned Suffix - Assume players can see themselves when vanished 2022-05-03 18:03:29 +02:00
NEZNAMY 79f4bdb869 Unlimited Nametags - Do not delay respawn by 1 tick anymore to fix OOM 2022-05-01 13:07:42 +02:00
NEZNAMY b0d2d0f7dc NickCompatibility - Clean up code 2022-04-30 20:01:40 +02:00
NEZNAMY cdf58c1dfe Teams - set canSeeFriendlyInvisibles to true 2022-04-30 18:21:46 +02:00
NEZNAMY 4680de6022 Feature management - Add try/catch for each feature in join processing (#560) 2022-04-30 17:22:03 +02:00
NEZNAMY e8f61181b6 Error logging - Log (critical) errors into console even when error file is full 2022-04-30 17:20:24 +02:00
NEZNAMY 75e9e007d0 Fix disabled worlds not loading correctly (from #6f07cf4) 2022-04-28 17:27:23 +02:00
NEZNAMY 3574ef7c0b Belowname - Do not update score when entering disabled world 2022-04-28 12:20:54 +02:00
NEZNAMY 86158036d2 Commands - Make permission group assigning more obvious in debug output 2022-04-28 11:55:21 +02:00
NEZNAMY e73beb47a3 API - Fix scoreboard Line#setText not working 2022-04-26 23:23:42 +02:00
NEZNAMY 0db5f1dd73 Scoreboard - Fix NPE when a line is null 2022-04-23 14:18:30 +02:00
NEZNAMY 6dcdc2aa58 PetFix - Fix attack packet cancellation 2022-04-20 10:46:08 +02:00
NEZNAMY 64601137e8 Scoreboard - Show empty lines when defined as empty, only hide when placeholder output is empty 2022-04-15 00:07:44 +02:00
NEZNAMY af7697b670 BungeeCord - Fixed NPE from moving to reflection 2022-04-14 23:24:45 +02:00
NEZNAMY 9e4f46088b Commands - Do not force refresh players who are not loaded yet (#560) 2022-04-12 11:21:06 +02:00
NEZNAMY 91e71a9b9c Layout - Fixed NPE when player had no layout visible 2022-04-10 23:32:13 +02:00
NEZNAMY 1198ffb847 BungeeCord - Use reflection for proxy module access due to the repository no longer being available 2022-04-10 23:31:51 +02:00
NEZNAMY 72116ecd0c Javadoc - Further improve documentation 2022-04-10 21:08:19 +02:00
NEZNAMY 04ebb7123d Code style - Move NMS object declaration and initialization 2022-04-10 20:28:29 +02:00
NEZNAMY 43096beafe Bukkit - Use ConsoleCommandSender for colored messages (#555) 2022-04-09 18:27:37 +02:00
NEZNAMY 2a08c62456 Tab expansion - Fix server placeholders not loading on join 2022-04-07 15:44:58 +02:00
NEZNAMY b62d74c3fa Code style - Remove unnecessary reflection 2022-04-06 20:38:03 +02:00
NEZNAMY 652fb5a6ad Bukkit - Switch from Paper to Purpur API 2022-04-06 19:11:19 +02:00
NEZNAMY d1f25cc19f Bukkit - Disable checking for plugins with compatibility issue 2022-04-06 18:25:12 +02:00
NEZNAMY dc6a9d9761 Fix layout startup 2022-04-06 13:44:16 +02:00
NEZNAMY 838d725715 Code style - Removed redundant static modifiers 2022-04-06 13:31:31 +02:00
NEZNAMY c45acb39ca Code style - Clean up variable initialization 2022-04-06 13:10:11 +02:00
NEZNAMY 957edf2a52 Javadoc - Fixed compilation warn 2022-04-06 12:44:54 +02:00
NEZNAMY d969c6ed0e Code style - Change way of checking if server is proxy 2022-04-06 12:41:20 +02:00
NEZNAMY dd6fca961c Code style - Clean up configuration loading 2022-04-06 12:34:39 +02:00
NEZNAMY e88a6df456 Config - remove hidden unregister-before-register option and remove the function entirely. Hopefully with improved checks this should not be necessary anymore. It caused client errors, as well as #549 2022-04-06 11:35:03 +02:00
NEZNAMY 3a4530c999 RGB - Finish #552 - Only replace clean gradients in property initialization 2022-04-05 23:24:37 +02:00
NEZNAMY b623dba40a Merge branch 'master' of https://github.com/NEZNAMY/TAB 2022-04-05 23:20:13 +02:00
NEZNAMY e2fd945109 Merge pull request #552 from lucypoulton/feat/kyori-rgb-format
Add support for Kyori MiniMessage RGB format
2022-04-05 23:19:52 +02:00
NEZNAMY e6dc3cda31 Unlimited nametags - Manually destroy armor stands on world switch 2022-04-05 20:21:36 +02:00
Lucy Poulton 18d8ff127a add support for kyori minimessage rgb format 2022-04-05 14:25:22 +01:00
NEZNAMY 4a9526451f Code style - Remove redundant "triggerMode" flag from Placeholder class due being redundant. Setting refresh to -1 has the same effect. 2022-04-04 19:03:51 +02:00
NEZNAMY 669d89c870 Code style - Move tab expansion code to interface 2022-04-04 18:15:06 +02:00
NEZNAMY 39161f2af5 Nametags - Reduced CPU usage of anti-override 2022-04-04 16:02:32 +02:00
NEZNAMY be8c33e3fc Velocity - Delay join event processing to avoid unformatted tablist names 2022-04-03 14:08:19 +02:00
NEZNAMY 7c1a27f9df Javadoc - Further improve documentation 2022-04-02 19:07:18 +02:00
NEZNAMY 342cc93dbf Code style - Clean up code 2022-04-02 13:17:15 +02:00
NEZNAMY 6f07cf439b Code style - Clean up loading of disabled servers/worlds 2022-04-01 23:40:04 +02:00
NEZNAMY 1d4d00b69b Code style - Clean up code with usage of @Inject 2022-04-01 23:21:30 +02:00
NEZNAMY 54cb3e4d54 3.1.1 2022-04-01 10:02:26 +02:00
NEZNAMY b0fc2caef9 RedisBungee - Detect player name change from other proxies 2022-03-31 21:54:51 +02:00
NEZNAMY 1221509d24 MySQL - Do not lowercase _DEFAULT_ group name, which caused it to not load (#546) (for real this time) 2022-03-31 20:52:12 +02:00
NEZNAMY 17f5f60504 MySQL - Do not lowercase _DEFAULT_ group name, which caused it to not load (#546) 2022-03-31 17:02:12 +02:00
NEZNAMY a8b0b488c6 Layout - Implement latency updating for player slots (#545) 2022-03-31 15:45:14 +02:00
NEZNAMY 6d922d5b70 Unlimited nametags - Fix NPE when player moves too quickly after joining 2022-03-31 14:50:54 +02:00
NEZNAMY 1ab62a33e3 Placeholders - Improve refresh task interval adaptation (#543) 2022-03-31 10:01:10 +02:00
NEZNAMY f9540a1e78 Tab Expansion - Fix placeholders not loading on player join 2022-03-29 11:17:04 +02:00
NEZNAMY a720bf2c8b Unlimited nametags - Do not allow preview command when armor stands are disabled for player 2022-03-28 21:25:42 +02:00
NEZNAMY c143eab6fb Global playerlist - Fix player possibly being removed from playerlist after reconnecting rapidly (#539) 2022-03-28 20:57:47 +02:00
NEZNAMY 1afb20af8b Code style - Avoid reassigning parameters 2022-03-28 12:57:31 +02:00
NEZNAMY c6f27c839d Code style - Document empty method body 2022-03-28 12:49:37 +02:00
NEZNAMY 742f1708c5 Code style - Remove unused import 2022-03-28 12:47:19 +02:00
NEZNAMY ac9601a48b Unlimited nametags - Fix nametag toggle command not hiding vanilla name on players with disabled armor stands via API 2022-03-28 12:13:23 +02:00
NEZNAMY 4cd109a5fc Javadoc - Update style and fix alignment after replacing tabs with spaces 2022-03-26 23:13:19 +01:00
NEZNAMY 078554a8b0 RedisBungee - Fix /btab reload removing players from tablist when global playerlist is disabled 2022-03-25 14:46:59 +01:00
NEZNAMY 464e2f4f64 RedisBungee - Fix duplicated team names through proxies 2022-03-25 14:46:22 +01:00
NEZNAMY b84f55aa18 RedisBungee - Fix errors and issues when unlimited nametag mode is enabled 2022-03-25 14:45:55 +01:00
NEZNAMY be2f780bfa Drop LuckPerms event hook and go back to periodic task. Too many issues related to events. 2022-03-25 10:27:36 +01:00
NEZNAMY 262d8493a6 fix NPE 2022-03-25 09:33:32 +01:00
NEZNAMY 24e12e871b finish #534 2022-03-24 22:33:18 +01:00
NEZNAMY a2ee75339c 3.1.1-pre2 2022-03-24 22:20:25 +01:00
NEZNAMY 9c28c4d63c add auto complete for group names in group command 2022-03-22 22:12:55 +01:00
NEZNAMY 7d57da1424 fix disableArmorStands method not destroying armor stands 2022-03-22 13:06:28 +01:00
NEZNAMY b77b20ba4d expose placeholder output getters in the API 2022-03-22 11:54:30 +01:00
NEZNAMY 57ae58f093 call super.onQuit as it should 2022-03-21 20:26:56 +01:00
NEZNAMY b29c878688 Merge remote-tracking branch 'origin/master' 2022-03-21 08:51:52 +01:00
NEZNAMY 5a5a6c76c1 another banger that took a week to fix 2022-03-21 08:51:32 +01:00
NEZNAMY f6a53f537c fix NPE 2022-03-21 08:46:02 +01:00
NEZNAMY d86ed37208 allow negative values in replacement intervals using ~ 2022-03-20 17:55:17 +01:00
NEZNAMY 92b945f28d Merge pull request #534 from itsmemac/master
fix nametag preview help text
2022-03-20 15:03:07 +01:00
Mac cb164f0055 fix nametag preview help text
it seems new update `/tab ntpreview` has been replaced with `/tab nametag preview`
Help text was not updated
2022-03-20 19:31:38 +05:30
NEZNAMY acfe37c1b5 fix NPE 2022-03-20 12:50:30 +01:00
NEZNAMY 44ded26df4 change method call order in which groups are refreshed 2022-03-19 16:13:39 +01:00
NEZNAMY 6dbd92a010 remove players from map on quit 2022-03-19 16:12:06 +01:00
NEZNAMY f729ca0ad2 fix NPE 2022-03-19 16:11:45 +01:00
NEZNAMY 065490c077 Merge branch 'master' of https://github.com/NEZNAMY/TAB 2022-03-18 17:12:20 +01:00
NEZNAMY da6425dd93 Merge pull request #530 from CoachYT1/master
Update dependencies & GitHub actions
2022-03-15 08:25:12 +01:00
CoachYT 250dcbc676 Update build.yml 2022-03-14 12:18:41 +01:00
CoachYT de4ca4a88f Update libs.versions.toml 2022-03-14 12:15:58 +01:00
NEZNAMY 723a0c890e fix NPE 2022-03-13 22:36:37 +01:00
NEZNAMY 7085e7df20 do not forward group if assigning by permissions 2022-03-13 22:36:25 +01:00
NEZNAMY 09496d60f3 add argument check 2022-03-13 13:19:05 +01:00
NEZNAMY bf6bc26a5c add check into API for all the users who shade API into their projects 2022-03-13 13:16:20 +01:00
NEZNAMY a7217eae15 fix placeholders used only in tab expansion not refreshing 2022-03-13 13:12:37 +01:00
NEZNAMY 2a532ef9b7 update README.md 2022-03-13 13:11:37 +01:00
NEZNAMY c304ded924 avoid thread spam from LP events 2022-03-11 15:06:13 +01:00
NEZNAMY 4d8c47a505 #517 - make group names not case-sensitive when connected to MySQL 2022-03-09 10:22:51 +01:00
NEZNAMY d3e0ccbf34 forward nametag preview on server switch 2022-03-09 09:08:49 +01:00
NEZNAMY 3c82b46148 fix updating of invalid score on server switch when pipeline injection is disabled 2022-03-08 23:09:29 +01:00
NEZNAMY 07d7f2cc17 catch StackOverflowError as well 2022-03-08 21:50:10 +01:00
NEZNAMY 54d4f09ab1 fix StackOverflowError when using placeholder identifier inside its own replacements (will act the same as %value%) 2022-03-08 21:45:11 +01:00
NEZNAMY e8c698b5e8 #517 - fix mysql header/footer download/upload 2022-03-07 22:14:49 +01:00
NEZNAMY b096906ffd 3.1.1-pre1 2022-03-07 18:59:40 +01:00
NEZNAMY 5a9cec12fa WeakHashMap isn't so weak after all (fixed memory leak) 2022-03-07 18:59:22 +01:00
NEZNAMY a2ed71751f fix NPE 2022-03-07 18:58:10 +01:00
NEZNAMY 5a3a2df920 simplify 2022-03-07 15:50:24 +01:00
NEZNAMY 9d07e669ea merge ifs 2022-03-07 15:50:12 +01:00
NEZNAMY aa18f1cc35 remove unnecessary full path 2022-03-07 14:03:04 +01:00
NEZNAMY 668d78ea64 remove redundant constructor 2022-03-07 13:59:38 +01:00
NEZNAMY 6f62581d6e print OOM into file instead of throwing into console 2022-03-07 12:53:12 +01:00
NEZNAMY 06686ada5c add synchronized lock to printError method 2022-03-07 12:21:47 +01:00
NEZNAMY 4380482606 remove direct reference to player channel on bukkit 2022-03-07 12:21:24 +01:00
NEZNAMY d5112b3d32 fix group refreshing introduced in previous commit which in the end didn't even fix the issue it was supposed to 2022-03-06 20:26:49 +01:00
NEZNAMY ef67506640 fix error caused by concurrent access 2022-03-06 12:01:50 +01:00
NEZNAMY c2ea4d2793 #516 - skin signature can be null 2022-03-05 16:29:16 +01:00
NEZNAMY f0d8d479bd 3.1.0 2022-03-04 22:46:16 +01:00
NEZNAMY 2d46d70c92 Fix super rare permission group detecting issue when using TAB on bungeecord with assigning by permissions with using backend permissions with many online players. Jesus. 2022-03-04 22:38:43 +01:00
NEZNAMY 4320bb7cb4 try to fix rare error that doesn't make sense 2022-03-04 22:36:53 +01:00
NEZNAMY 398e8ed5ff remove redundant space 2022-03-04 12:31:43 +01:00
NEZNAMY 4e8b804337 prefer per-world settings over per-server 2022-03-04 10:39:45 +01:00
NEZNAMY de7c664e0d remove redundant check 2022-03-02 14:17:05 +01:00
NEZNAMY c7600a2e3d fix issues for players with unknown version 2022-03-02 13:34:29 +01:00
NEZNAMY 8b34e82aab simplify 2022-03-02 12:49:26 +01:00
NEZNAMY c96efe8802 use Logger for console messages 2022-03-02 12:46:33 +01:00
NEZNAMY 0a1bfd3a2e 3.1.0-pre3 2022-03-02 10:57:23 +01:00
NEZNAMY 755cf9ce43 1.18.2 2022-03-02 10:56:46 +01:00
NEZNAMY c6aca74396 fix NPE when assigning groups by permissions on bungeecord 2022-03-01 22:37:37 +01:00
NEZNAMY b5b7f3c16c add try/catch for PremiumVanish hook 2022-02-28 23:26:53 +01:00
NEZNAMY 293162b484 show name of file with syntax error correctly in error message 2022-02-28 15:27:17 +01:00
NEZNAMY bd543b7b9d fix rare NPE (#504) 2022-02-25 20:49:40 +01:00
NEZNAMY 994fe9f482 fix conversion error when bossbar names are numbers (#506) 2022-02-25 20:48:28 +01:00
NEZNAMY f657bdb14c update README.md 2022-02-22 23:42:16 +01:00
NEZNAMY a4238e1191 compensate for 1.8.0 client sided bug (#501) 2022-02-22 08:05:45 +01:00
NEZNAMY daf08423b4 3.1.0-pre2 2022-02-21 19:01:40 +01:00
NEZNAMY 91367f3d3a fix wrong text displayed 2022-02-21 16:33:21 +01:00
NEZNAMY 9dbd52b638 replace tabs with 4 spaces 2022-02-21 16:15:52 +01:00
NEZNAMY 22c6be2770 fix names not updating when new max player joins 2022-02-21 16:05:51 +01:00
NEZNAMY fb261c9f90 cleanup 2022-02-21 12:43:23 +01:00
NEZNAMY 638e35bf90 more abstraction 2022-02-21 12:40:15 +01:00
NEZNAMY 25d13862ae initialize server version & data folder constants instead of having per-platform getters 2022-02-21 12:30:02 +01:00
NEZNAMY 1c8f483138 split content of plugin message handler classes into other classes 2022-02-21 11:57:43 +01:00
NEZNAMY 92ad215873 more code abstraction 2022-02-21 11:06:02 +01:00
NEZNAMY 7ed3cfbb7c fix vanish status not refreshing correctly on bungeecord 2022-02-20 23:42:43 +01:00
NEZNAMY 53e75a27be avoid bytebuf instance check entirely if deserialization is disabled 2022-02-20 23:08:15 +01:00
NEZNAMY 1b67819c3c only forward relevant properties to expansion and fix values not updating 2022-02-20 15:16:12 +01:00
NEZNAMY 07f8020f79 fix syntax error in default file 2022-02-20 14:53:31 +01:00
NEZNAMY b12d0680d8 massively optimize some API methods 2022-02-20 14:50:05 +01:00
NEZNAMY 64247d913e implement "/tab nametag toggle" command hiding nametags of all players for command sender 2022-02-19 21:29:22 +01:00
NEZNAMY 3575cdae85 move code & respawn armor stands on world switch if preview is enabled 2022-02-19 14:27:04 +01:00
NEZNAMY f71a542247 add check for directory existence 2022-02-19 13:56:59 +01:00
NEZNAMY 46cc59138b skip action if list is empty 2022-02-19 13:31:00 +01:00
NEZNAMY 46bfa5112e for some reason this check is needed as well 2022-02-19 13:29:32 +01:00
NEZNAMY fcdff51783 use pre-allocated enum values array (again) 2022-02-19 13:29:18 +01:00
NEZNAMY a4be4ae419 fix check not working properly 2022-02-19 13:28:05 +01:00
NEZNAMY 7083352b9a cache enum values to reduce memory allocations 2022-02-18 23:37:27 +01:00
NEZNAMY 956a0f46c0 name the second thread pool as well 2022-02-18 23:26:26 +01:00
NEZNAMY aea1864627 iterate over arrays to reduce allocations 2022-02-18 23:01:29 +01:00
NEZNAMY 803b87111a make packet deserializing on BungeeCord use 30x less CPU 2022-02-18 22:40:36 +01:00
NEZNAMY f64a641b63 fix NPE caused by a dumb mistake 2022-02-18 12:49:28 +01:00
NEZNAMY 7f9bb354d7 remove wrong null checks 2022-02-18 12:48:08 +01:00
NEZNAMY 4b7b6284f8 move code to avoid duplication 2022-02-18 12:38:55 +01:00
NEZNAMY bbccd26415 remove %maxplayers% placeholder 2022-02-18 12:35:31 +01:00
NEZNAMY bab7c737b3 add more precondition checks 2022-02-18 12:31:06 +01:00
NEZNAMY 3169787b41 fix NPE on /btab parse 2022-02-18 11:13:34 +01:00
NEZNAMY f29bbc6657 move config option loading 2022-02-17 23:04:21 +01:00
NEZNAMY f53cd5ae11 fix armor stands heights not updating 2022-02-17 22:39:59 +01:00
NEZNAMY 38d36b5ab5 remove unused softdependency 2022-02-17 21:33:54 +01:00
NEZNAMY 8f8f596abc drop direct UltraPermissions hook (still supported via Vault) 2022-02-17 16:28:43 +01:00
NEZNAMY 2afc8abdb2 rename fields from "method" to "action" 2022-02-17 16:19:57 +01:00
NEZNAMY 38dd948306 cleanup 2022-02-17 11:37:28 +01:00
NEZNAMY e393cf0a10 make code more universal 2022-02-17 11:35:36 +01:00
NEZNAMY 4f451017e3 make PacketBuilder not abstract and add default implementation to delete a redundant class 2022-02-17 11:17:27 +01:00
NEZNAMY 9cb31af48a class cleanup using consumer 2022-02-17 10:56:45 +01:00
NEZNAMY 2c17041b27 universal registration of %online_<server>% on proxies 2022-02-17 10:34:55 +01:00
NEZNAMY 72c75a443e more abstraction of RedisBungee feature 2022-02-16 20:04:06 +01:00
NEZNAMY 1ba6384647 update README.md 2022-02-16 18:57:40 +01:00
NEZNAMY e2edf9a37c delete unused file 2022-02-16 17:35:23 +01:00
NEZNAMY cb0bfd095d 3.1.0-pre1 2022-02-15 13:05:53 +01:00
NEZNAMY ec03dd4755 fix long line creating empty line above it 2022-02-15 13:05:21 +01:00
NEZNAMY de44f5ae42 update issue templates 2022-02-14 21:34:22 +01:00
NEZNAMY 5ee6796172 implement #347 and probably fix original issue in #475 2022-02-14 21:13:38 +01:00
NEZNAMY d034fca513 add MySQL data conversion commands 2022-02-14 15:58:28 +01:00
NEZNAMY f65c3fb29a remove unused code 2022-02-14 00:02:38 +01:00
NEZNAMY 7192bc9d69 resend objectives/teams on server switch even when pipeline injection is disabled 2022-02-14 00:02:06 +01:00
NEZNAMY d7636a05f4 drastically reduce amount of permission checks by the feature 2022-02-13 23:05:47 +01:00
NEZNAMY bd93301634 send missing packets on that thing through bridge 2022-02-13 21:58:32 +01:00
NEZNAMY b0558ba0a2 just one \t 2022-02-13 21:57:53 +01:00
NEZNAMY 251934bb4b fix NPE on group info when mysql is enabled 2022-02-13 17:01:13 +01:00
NEZNAMY f2c9ef5d30 implement tab expansion on BungeeCord through bridge 2022-02-13 16:43:17 +01:00
NEZNAMY 15a072bbaa fix weird NPE 2022-02-13 13:52:07 +01:00
NEZNAMY 8f1c303862 implement /tab groups and /tab group <name> subcommands 2022-02-12 14:07:23 +01:00
NEZNAMY c79d2e3e6e fix BossBar placeholders not updating when changing value while it was hidden 2022-02-11 19:41:59 +01:00
NEZNAMY f45d8d860b default condition type to AND instead of OR 2022-02-11 19:40:54 +01:00
NEZNAMY 88f31184a0 add back \t for stack traces 2022-02-11 17:54:11 +01:00
NEZNAMY d5368baab4 add final modifier 2022-02-11 17:22:14 +01:00
NEZNAMY 10f645226c fix bridge placeholder refreshing from replacements 2022-02-11 17:12:54 +01:00
NEZNAMY 322c572cd6 add new issue template for wiki changes 2022-02-11 14:19:24 +01:00
NEZNAMY fdfeb178b5 update error.yml 2022-02-10 21:04:37 +01:00
NEZNAMY 1c63cdba91 update error.yml 2022-02-10 21:03:31 +01:00
NEZNAMY 289d0db8e3 create error template 2022-02-10 21:02:26 +01:00
NEZNAMY 9adacca77f upgrade bug report template 2022-02-10 20:59:12 +01:00
NEZNAMY 7dc6813274 avoid NegativeArraySizeException when copying collection by avoiding that operation 2022-02-10 17:53:30 +01:00
NEZNAMY 77bf1cfbb9 #494 2022-02-10 15:44:07 +01:00
NEZNAMY 8f28350579 initial unlimited nametags on bungee support 2022-02-10 15:33:35 +01:00
NEZNAMY 2d06d0c1d3 fix compatibility issue with other plugins 2022-02-06 13:21:35 +01:00
NEZNAMY 7e8301afcd goodbye 3 days of my life 2022-02-05 13:59:12 +01:00
NEZNAMY 2600e8f856 send empty player slots in a single packet 2022-02-03 22:58:35 +01:00
NEZNAMY 914748e14e add toString override to Skin 2022-02-03 22:32:54 +01:00
NEZNAMY 21a7b633e7 simplify 2022-02-01 19:15:57 +01:00
NEZNAMY a77d4352e2 convert classes into anonymous ones 2022-02-01 18:54:01 +01:00
NEZNAMY a7a21e0e51 fix another config conversion bug 2022-02-01 14:49:53 +01:00
NEZNAMY a0a14cd285 fix NPE 2022-02-01 14:18:03 +01:00
NEZNAMY 44b7bedd53 fix bossbar never showing when joining disabled world/server 2022-02-01 14:16:04 +01:00
NEZNAMY 409a0808c1 fix NumberFormatException with Placeholder sorting type 2022-02-01 14:08:22 +01:00
NEZNAMY 4214d02fad send join plugin message on server switch as well 2022-02-01 12:52:02 +01:00
NEZNAMY bc1abb1b58 more javadocs and moved some variables around 2022-01-31 21:37:10 +01:00
NEZNAMY 2f2f53ba4d #488 2022-01-31 20:26:19 +01:00
NEZNAMY cbeb4c151d remove errorDescription parameter from submitted tasks 2022-01-30 19:01:22 +01:00
NEZNAMY 1d5ca70790 remove bridge placeholder usage from cpu command since it's no longer measured 2022-01-30 18:38:03 +01:00
NEZNAMY 1f619ff4d3 allow enabling pet fix feature on proxy and forward status to bridge 2022-01-30 00:43:55 +01:00
NEZNAMY f5acdebe60 bridge recode to drastically reduce packet flow & allow relational placeholder support 2022-01-30 00:34:00 +01:00
NEZNAMY bd59922204 more docs, general cleanup 2022-01-29 15:49:55 +01:00
NEZNAMY c4d9482c79 remove unused code 2022-01-28 21:12:31 +01:00
NEZNAMY 8faef8f017 class cleanup 2022-01-28 20:56:02 +01:00
NEZNAMY 284161db77 create and use Skin class instead of forwarding Objects 2022-01-28 20:54:33 +01:00
NEZNAMY 78db2b66ef placeholder cleanup, unification and performance improvements 2022-01-28 17:18:52 +01:00
NEZNAMY 0d71643ecb make ping value of layout slots configurable 2022-01-28 16:25:39 +01:00
NEZNAMY 9a7a105e7b fix %serveronline% and %worldonline% inaccuracies 2022-01-28 11:25:13 +01:00
NEZNAMY f54d024d97 3.0.2 2022-01-27 20:43:29 +01:00
NEZNAMY 94338bd53f update nested placeholders immediately on plugin message 2022-01-27 13:17:24 +01:00
NEZNAMY 1a9ecc0313 fix belowname update packets being sent in disabled worlds / servers 2022-01-26 22:04:13 +01:00
NEZNAMY 4baeb7b945 properly cancel delayed tasks on shutdown / reload 2022-01-26 18:24:24 +01:00
NEZNAMY baee479fb5 3.0.2-pre6 2022-01-26 01:03:29 +01:00
NEZNAMY 5ad4b2e9c4 so many issues from one wrong method call 2022-01-25 22:57:31 +01:00
NEZNAMY 26657cddfc code style suggestions by intellij 2022-01-25 22:56:52 +01:00
NEZNAMY 947a922f8c reduce amount of logged warns in console 2022-01-25 16:08:46 +01:00
NEZNAMY a2be76184e use tab's thread manager for scoreboard and bossbar announcing 2022-01-25 00:43:57 +01:00
NEZNAMY 8ddb733dc3 do not freeze tab's thread with delayed tasks 2022-01-25 00:33:44 +01:00
NEZNAMY 94e016129b run repeating task for the first time with initial delay 2022-01-25 00:33:21 +01:00
NEZNAMY 5e653ded5d process events in a single thread on velocity as well 2022-01-23 22:04:47 +01:00
NEZNAMY 1bf8097c3f 3.0.2-pre5 2022-01-23 21:39:16 +01:00
NEZNAMY 3d2f11ffd2 move enable call just in case 2022-01-23 18:28:08 +01:00
NEZNAMY 5e77a22d7a further javadoc progress 2022-01-23 18:27:46 +01:00
NEZNAMY 1dffcb1dc3 remove all thread safety checks since they are no longer needed 2022-01-23 17:24:26 +01:00
NEZNAMY edc18cbafb run all tasks in the same thread 2022-01-23 16:49:50 +01:00
NEZNAMY 2f23194432 3.0.2-pre4 2022-01-23 11:06:42 +01:00
NEZNAMY 20709472be fix vehicle / passenger handling 2022-01-23 11:06:16 +01:00
NEZNAMY 7a8c6a0cec some more velocity fixes 2022-01-22 23:11:51 +01:00
NEZNAMY 88558e40a7 round health even when copying max health 2022-01-21 14:49:27 +01:00
NEZNAMY 79386b2b6b allow 64 character scoreboard on <1.13 using "Long|" line prefix 2022-01-21 13:12:03 +01:00
NEZNAMY 3aad8d3cb5 allow per-server / per-world properties through commands 2022-01-21 10:49:06 +01:00
NEZNAMY 272a6f37ad fix NPE 2022-01-20 18:49:33 +01:00
NEZNAMY e10081025d fix load() method not executing methods in correct order resulting in enormous load times with large player counts 2022-01-20 18:31:04 +01:00
NEZNAMY e03a6d8f11 attempt to fix rare error probably caused by concurrent access 2022-01-20 18:29:37 +01:00
NEZNAMY 98e7dc0321 match velocity fixes in AlignedPlayerList as well 2022-01-20 18:24:52 +01:00
NEZNAMY 74438c5d74 so this is why someone was getting a NPE 2022-01-20 18:02:14 +01:00
NEZNAMY 0c4e548565 further increase event processing delay on velocity 2022-01-20 17:06:03 +01:00
NEZNAMY cc70e01e96 merge classes together 2022-01-20 14:34:19 +01:00
NEZNAMY 7c635748af simplify 2022-01-20 13:58:05 +01:00
NEZNAMY 0c874ad56d only keep lowercase entries in sorting map 2022-01-20 13:51:24 +01:00
NEZNAMY 2fb7f80b71 always display bossbars in defined order 2022-01-20 13:14:40 +01:00
NEZNAMY 3f7c3414ce increase server switch processing delay on velocity 2022-01-18 11:23:04 +01:00
NEZNAMY 97165db44d fix bridge placeholders rarely not working in scoreboard 2022-01-18 11:11:10 +01:00
NEZNAMY 82cdf04cf0 add feature override check for onServerChange 2022-01-18 11:10:34 +01:00
NEZNAMY 171d899609 3.0.2-pre3 2022-01-14 20:51:37 +01:00
NEZNAMY 6432278d5d fix scoreboard detection from other plugins not resetting on server switch 2022-01-14 20:41:15 +01:00
NEZNAMY ccaff12451 fix NPE caused by concurrent access 2022-01-14 20:40:54 +01:00
NEZNAMY 11347c080b more debug messages 2022-01-14 15:50:13 +01:00
NEZNAMY 553676c3f9 catch LinkageError instead of more specific ones 2022-01-14 15:49:49 +01:00
NEZNAMY 40b70e7418 fix compatibility with forks that set version field to "Unknown" 2022-01-14 14:22:52 +01:00
NEZNAMY 0ea75019ae catch NoSuchMethodError as well 2022-01-14 14:21:46 +01:00
NEZNAMY dbc092df77 add some missing bossbar command feedback (#462) 2022-01-14 11:09:15 +01:00
NEZNAMY 68049f0dca extract duplicated code into method (and also cancel tasks if plugin fails to load) 2022-01-13 20:54:58 +01:00
NEZNAMY 9db5dfc175 fix NPE when getting last value but placeholder threw error 2022-01-13 20:48:49 +01:00
NEZNAMY 039a316b3b clear players if plugin fails to load 2022-01-13 20:48:16 +01:00
NEZNAMY f4b529f1ce update README.md 2022-01-11 18:50:44 +01:00
NEZNAMY 9c6d606103 code cleanup 2022-01-11 17:57:15 +01:00
NEZNAMY 6cdc06aae7 fix config option path 2022-01-11 17:45:54 +01:00
NEZNAMY 2684654e7b drop redundant remove-strings option 2022-01-11 17:45:07 +01:00
NEZNAMY 25bcc33204 remove harming check 2022-01-10 20:44:41 +01:00
Callum Seabrook e5b3f6215b Added relocation for event 2022-01-10 15:03:16 +00:00
NEZNAMY 9306eadd90 a couple of config conversion fixes 2022-01-09 18:42:13 +01:00
NEZNAMY a27fbb5b8b MessageFile now extends YamlConfigurationFile 2022-01-08 17:27:28 +01:00
NEZNAMY cd4c82b0b8 Merge pull request #477 from JannesStroehlein/master
Fixed localization issue when dealing with floats numbers
2022-01-08 14:45:57 +01:00
Jannes Ströhlein aa6179ee9e made all decimal seperators points instead of some being commas. The commas made the placeholder replacement logic malfunction (2,43 -> 243 instead of 2.43) 2022-01-08 14:39:11 +01:00
NEZNAMY 6594b8c2dc fix replacements being applied twice for bridge placeholders (#476) 2022-01-07 10:47:19 +01:00
NEZNAMY d4c2cdf003 fix startup error when using placeholders with colors inside 2022-01-06 18:41:05 +01:00
NEZNAMY 2b529c37f5 fix rare concurrent modification 2022-01-06 17:55:16 +01:00
NEZNAMY 8599cd925b fix %vanished% refreshing with a much higher delay than it should on bungeecord 2022-01-05 14:32:22 +01:00
NEZNAMY 89f37b4b9e add synchronized modifier to stay safe 2022-01-04 16:46:40 +01:00
NEZNAMY f3136e85ee use equals instead of equalsIgnoreCase for better performance 2022-01-04 16:21:18 +01:00
NEZNAMY 845743073c fix wrong mysql checks 2022-01-04 15:33:36 +01:00
NEZNAMY b2c7bacaf9 fix errors when eventbus fails to load 2022-01-04 15:16:34 +01:00
NEZNAMY ed1673f032 fix #472 2022-01-04 15:15:53 +01:00
NEZNAMY bac9d443ea process all bungee events async 2022-01-03 20:32:28 +01:00
NEZNAMY 90e3868c08 use WeakHashMap for player mysql data & fix playeruuid not working 2022-01-03 15:53:07 +01:00
NEZNAMY c428572e01 add null check that doesn't really make sense, but someone needs it 2022-01-03 14:33:16 +01:00
NEZNAMY 884b5755ec 3.0.2-pre2 2022-01-02 22:47:51 +01:00
NEZNAMY 32d7366795 several fixes in redisbungee support when global playerlist is disabled 2022-01-02 22:47:11 +01:00
NEZNAMY 21bf4a5450 fix using % symbol without any placeholders resulting in %% being displayed 2022-01-02 22:38:59 +01:00
NEZNAMY 8042b02cf5 update README.md 2022-01-02 21:59:08 +01:00
NEZNAMY ae7cdd3982 no longer sending redundant packets on server/world switch 2022-01-01 22:03:19 +01:00
NEZNAMY 9ba945ad76 cache components on velocity as well 2022-01-01 21:51:18 +01:00
NEZNAMY 9cd04c3660 small optimization 2022-01-01 19:12:01 +01:00
NEZNAMY 444bc19781 fix pipeline injection detection on velocity 2022-01-01 18:23:46 +01:00
NEZNAMY eb08c4ba04 convert %afk% replacement when upgrading from free version as well 2022-01-01 14:34:57 +01:00
NEZNAMY 5846e24a29 improve placeholder API 2022-01-01 01:33:03 +01:00
NEZNAMY 9c2c09e433 remove debug messages 2021-12-31 14:20:08 +01:00
NEZNAMY 3c4329697b add PlayerLoadEvent#isJoin() method 2021-12-31 14:12:36 +01:00
NEZNAMY af9951d993 Merge branch 'master' of https://github.com/NEZNAMY/TAB 2021-12-31 13:54:52 +01:00
NEZNAMY 630f6df2f5 Merge pull request #467 from NamiUni/patch-1
Correctly display the number of players online.
2021-12-31 13:54:38 +01:00
Namiu/うにたろう fcf07b8e7b Correctly display the number of players online. 2021-12-31 21:49:12 +09:00
NEZNAMY 4824c2f626 send remove packet always, just to stay safe 2021-12-30 14:01:05 +01:00
NEZNAMY 2b6b2e1b63 create a constant to reduce memory allocations 2021-12-29 18:02:22 +01:00
NEZNAMY 6926c1e57f redisbungee should not add/remove players when global playerlist is disabled 2021-12-29 17:12:16 +01:00
NEZNAMY 6a00a7f1ca fix wrong map key type 2021-12-29 00:32:51 +01:00
NEZNAMY 288c3d4c87 add onClickCopyToClipBoard method to ChatModifier class 2021-12-29 00:27:11 +01:00
NEZNAMY ac497bcc41 ignore vanished players in layout 2021-12-28 22:31:45 +01:00
NEZNAMY 7b8d0d6845 fix startup error when fixes slots list is null 2021-12-28 22:05:44 +01:00
NEZNAMY a9a4589fae disable logging of invalid numbers due to false positive on BungeeCord before bridge placeholders are initialized 2021-12-28 18:53:29 +01:00
NEZNAMY b8f972a774 disable scoreboard score packet check due to problems it causes 2021-12-28 18:44:14 +01:00
NEZNAMY 305e388478 translate to a more user-friendly exception when bossbar.yml is missing when trying to convert configuration 2021-12-26 15:18:42 +01:00
NEZNAMY 97e7848a78 add catch for IllegalStateException which may be thrown when using plugman 2021-12-26 15:15:16 +01:00
NEZNAMY d33058a924 fix rare error caused by concurrent access 2021-12-26 15:14:53 +01:00
NEZNAMY eda3cc1f17 fix yellow number & belowname not appearing after client reset packet (on server switch) 2021-12-26 14:47:02 +01:00
NEZNAMY 47043ad4ad fix check if injection is loaded by external plugin 2021-12-24 01:10:26 +01:00
NEZNAMY acf20088cc do not send packet if not needed 2021-12-24 01:09:43 +01:00
NEZNAMY 374cb2766c initialize array just in case 2021-12-24 00:54:31 +01:00
NEZNAMY 31685b9ba5 unregister-before-register should always be disabled on proxy 2021-12-24 00:35:38 +01:00
NEZNAMY 722ff4ce52 3.0.2-pre1 2021-12-23 21:05:45 +01:00
NEZNAMY 161b375043 add floodgate as softdepend to avoid md5 message 2021-12-23 21:04:17 +01:00
NEZNAMY 2c14191cde do not send yellow number to players in disabled worlds/servers 2021-12-23 20:48:45 +01:00
NEZNAMY 486546918f (probably) fix #455 2021-12-23 19:18:09 +01:00
NEZNAMY 23d08e58a4 make help menu text configurable (#448) 2021-12-23 19:15:55 +01:00
NEZNAMY 4c4c34ecaa fix #453 2021-12-23 18:55:29 +01:00
NEZNAMY bd3f2fd70a initialize EventBus in declaration 2021-12-23 18:52:59 +01:00
NEZNAMY b80e42a635 fix NPE in custom lines 2021-12-23 15:32:19 +01:00
NEZNAMY 9446a034d0 fix layout resetting on server switch on velocity 2021-12-23 13:41:13 +01:00
NEZNAMY da0c6ab3fd remove unused import 2021-12-23 11:58:57 +01:00
NEZNAMY c1adb27ee5 remove PacketAPI class as it's no longer needed 2021-12-22 20:54:03 +01:00
NEZNAMY 980d3027e3 use defined constant 2021-12-22 19:23:21 +01:00
NEZNAMY 53ba533f9b small optimizations in reducing amount of sent packets 2021-12-22 19:20:27 +01:00
NEZNAMY e40827da65 don't send empty packets 2021-12-22 18:45:15 +01:00
NEZNAMY b9848b6a96 add debug message for player quit processing time 2021-12-22 18:09:03 +01:00
NEZNAMY 147593b11a use WeakHashMap to store player data in features to not need to remove it on quit 2021-12-22 18:08:47 +01:00
NEZNAMY 21652f928b remove online placeholder update on join/leave 2021-12-22 16:05:07 +01:00
NEZNAMY 5b0352aff0 only unregister teams, no need for scores as well 2021-12-22 15:18:21 +01:00
NEZNAMY b2da2fa096 update README.md 2021-12-22 15:04:12 +01:00
NEZNAMY 0cbb01a2a8 fix #447 2021-12-22 15:02:55 +01:00
NEZNAMY 179840968d Merge branch 'master' of https://github.com/NEZNAMY/TAB 2021-12-22 15:00:53 +01:00
NEZNAMY 3b9c1649a1 Merge pull request #452 from kacperleague9/v3
Setup workflow artifact
2021-12-22 14:47:41 +01:00
NEZNAMY 5750c7dbe1 Merge pull request #440 from NEZNAMY/common-events
Added platform agnostic event system
2021-12-22 14:01:16 +01:00
Callum Seabrook 7ceca359be Let's not recreate the event bus on reload 2021-12-22 12:42:48 +00:00
Callum Seabrook 0f8152a6ed Remove priorities, make events interfaces, and expose bus to API 2021-12-22 11:44:56 +00:00
Callum Seabrook b3258bb020 Added platform agnostic event system 2021-12-22 11:43:30 +00:00
Kacper Smoliński 4b2e705cbc Update build.yml 2021-12-22 08:43:48 +01:00
Kacper Smoliński 31e41382f8 Update build.yml 2021-12-22 08:39:30 +01:00
Kacper Smoliński ecda7192dc Update build.yml 2021-12-22 08:22:32 +01:00
Kacper Smoliński 9a48562b9f test gradle workflow 2021-12-22 08:20:18 +01:00
NEZNAMY c181b58bc1 fix NPE that makes no sense 2021-12-21 17:18:32 +01:00
NEZNAMY 2624afa2ed update README.md 2021-12-21 12:04:18 +01:00
Callum Seabrook 3690af1e35 Removed vanished placeholder from Krypton registry 2021-12-20 18:09:13 +00:00
NEZNAMY 98966d3b38 update README.md 2021-12-20 19:06:09 +01:00
NEZNAMY 41fdd16ce1 fix error when running /tab scoreboard show 2021-12-19 18:52:25 +01:00
NEZNAMY 1bc94859c0 Merge branch 'master' of https://github.com/NEZNAMY/TAB 2021-12-19 18:42:23 +01:00
Callum Seabrook 60f6f36437 Error manager good print stack trace bad 2021-12-19 13:16:43 +00:00
Callum Seabrook 82267ba16a Updated dependencies 2021-12-19 13:10:02 +00:00
NEZNAMY 14260deef8 make method synchronized to avoid rare bug caused by misconfiguration 2021-12-18 23:41:11 +01:00
NEZNAMY 8ba7342ccf register vanish placeholder in universal since implementation is same 2021-12-18 12:19:32 +01:00
NEZNAMY f6b935d78e fix double vanish status request on placeholder refresh 2021-12-18 12:17:39 +01:00
NEZNAMY 8cf3ae2091 ping spoof should only affect real players (#444) 2021-12-17 14:55:40 +01:00
NEZNAMY e02b997521 do not use %tps% in default config on bungeecord 2021-12-17 14:50:20 +01:00
NEZNAMY 229cef13c9 add cooldowns for attribute refreshing to prevent massive packet spam with many online players 2021-12-17 14:37:14 +01:00
NEZNAMY f503d6f896 move initialization to declaration to try to fix #442 2021-12-17 14:36:33 +01:00
NEZNAMY d851166bb7 add check for duplicated objectives and score updates without objectives 2021-12-17 13:56:44 +01:00
NEZNAMY 638a861350 display plugin message content in sent packets logging 2021-12-16 20:41:09 +01:00
NEZNAMY 20d7e4cbb0 fix entries with same value skipped in /tab cpu 2021-12-16 20:40:27 +01:00
NEZNAMY 36ccedd7c6 remove unused import 2021-12-16 18:08:38 +01:00
NEZNAMY 31854ba7a6 fix world being requested from bridge twice on reload 2021-12-16 18:07:22 +01:00
NEZNAMY 2639f07f5c recode and fixed 11 issues in config conversion 2021-12-16 17:56:29 +01:00
NEZNAMY b6e13f557f small fix in default config 2021-12-16 17:02:41 +01:00
NEZNAMY 6333d90059 remove redundant check 2021-12-16 17:02:27 +01:00
NEZNAMY fea5d0ec56 Merge branch 'master' of https://github.com/NEZNAMY/TAB 2021-12-16 11:07:50 +01:00
NEZNAMY c77f02d1fd disable LD hook until they fix the repository 2021-12-16 11:04:43 +01:00
NEZNAMY c498965cae add API to return player's active scoreboard 2021-12-16 11:03:54 +01:00
Callum Seabrook cdaa77071d Updated Krypton to 0.59.2 2021-12-14 11:48:25 +00:00
NEZNAMY 6a72678c8d simplify 2021-12-14 10:19:47 +01:00
NEZNAMY bb67fc622f fix errors when redisbungee is not enabled correctly 2021-12-13 18:22:16 +01:00
NEZNAMY 5b50c02d93 fix replacements not working in some placeholders 2021-12-13 16:36:54 +01:00
NEZNAMY ffec7e3266 fix world/server groups loading in header/footer 2021-12-13 14:09:56 +01:00
NEZNAMY 039c1e7027 fix velocity compilation 2021-12-11 21:27:29 +01:00
NEZNAMY b27a21b3b8 remove unused variable and imports 2021-12-11 20:03:44 +01:00
NEZNAMY 2bcb5f617e create constants for feature names 2021-12-11 19:51:11 +01:00
NEZNAMY 7bf5294f9f remove redundant check 2021-12-11 17:43:49 +01:00
NEZNAMY c2fd1940f0 separate character width file loading into another method 2021-12-11 17:41:35 +01:00
NEZNAMY 2d095ce6db fix compilation 2021-12-11 17:24:57 +01:00
NEZNAMY e88bc36fca remove unused field 2021-12-11 17:23:20 +01:00
NEZNAMY 5613ea4f77 fix placeholders not updating in replacements 2021-12-11 17:12:58 +01:00
NEZNAMY 9c41599d60 remove redundant escape (again) 2021-12-11 16:04:40 +01:00
NEZNAMY 5f8dd869e0 remove redundant escape in RGB patterns 2021-12-11 15:58:45 +01:00
NEZNAMY fb17df0b7e add registered placeholders to command complete in parse command 2021-12-11 14:53:38 +01:00
NEZNAMY 900ae83028 3.0.1 2021-12-11 12:11:58 +01:00
NEZNAMY 2c09db25b7 Merge pull request #432 from LeonMangler/patch-1
Load TAB after PremiumVanish
2021-12-11 12:10:26 +01:00
NEZNAMY 004e53fa29 Merge pull request #437 from Tanguygab/master
fix NPE when executing scoreboard cmd from console
2021-12-11 12:10:01 +01:00
NEZNAMY e285b143d5 3.0.0-pre3 2021-12-11 00:15:44 +01:00
NEZNAMY f78eb0ffed add API to change group temporarily 2021-12-11 00:14:13 +01:00
NEZNAMY 4d761e1d6e allow decimals in sorting by placeholder 2021-12-11 00:04:20 +01:00
NEZNAMY 4a8c975319 fix startup on bungeecord when assigning groups by permissions AND using bukkit permission manager 2021-12-10 23:45:55 +01:00
NEZNAMY fe56b7ed2d add LP group event listener as well & fix refreshing when assigning by permissions 2021-12-10 23:21:40 +01:00
NEZNAMY 5a74654807 fix scoreboard being enabled by default when converting config 2021-12-10 22:16:08 +01:00
NEZNAMY 533ce4a529 remove unused import 2021-12-10 20:55:19 +01:00
Tanguygab 4ea3780114 fix NPE when executing cmd from console 2021-12-10 19:36:45 +01:00
NEZNAMY 0d229ee26c do not send objective changes before they are registered 2021-12-10 18:25:56 +01:00
NEZNAMY 29079ecad5 add 1.18.1 to recognized versions 2021-12-10 16:01:21 +01:00
NEZNAMY ea88401a58 fix NPE when placeholder returns null 2021-12-10 15:25:17 +01:00
NEZNAMY 298cef4d1f fix startup error if replacement value is null 2021-12-10 15:24:45 +01:00
NEZNAMY a51e9495de add player load status checks to other placeholder types as well 2021-12-10 15:12:43 +01:00
NEZNAMY eead8ca1e2 attempt to avoid rare concurrent modification 2021-12-10 15:11:39 +01:00
NEZNAMY a30712bc38 unregister on bungeecord as well to avoid issues with new bukkit-focused check 2021-12-10 14:56:06 +01:00
NEZNAMY 07b443fb21 actually fixed the error 2021-12-10 14:54:23 +01:00
NEZNAMY 61d927305c add very likely useless check to try to prevent errors 2021-12-10 13:24:29 +01:00
NEZNAMY 8f21c2f27d fix mohist (again) 2021-12-09 22:34:20 +01:00
NEZNAMY 9fcf76e0c4 3.0.1-pre2 2021-12-09 14:53:16 +01:00
NEZNAMY 773afe2fb5 fix _DEFAULT_ not being used when using MySQL (#433) 2021-12-09 14:05:28 +01:00
NEZNAMY 83ce5bd476 Drop <#RRGGBB> format due to conflict with the gradient pattern starting the same way (#430) 2021-12-09 13:50:04 +01:00
NEZNAMY 75a341c240 fix placeholder refreshing being broken for time travelers 2021-12-09 13:44:51 +01:00
NEZNAMY 921a793b5c return identifier instead of null for sync placeholders before initialized 2021-12-09 13:05:31 +01:00
NEZNAMY c1b92868cd fix world forwarding on bungeecord 2021-12-08 20:39:51 +01:00
NEZNAMY 94d19d728d fix condition refresh when only trigger placeholders are used inside 2021-12-08 20:38:39 +01:00
NEZNAMY 8ef518f7e2 add null check for tablist properties when refreshing 2021-12-08 19:11:43 +01:00
NEZNAMY 79fd1148a9 add back animation format converting from 2.8.10 -> 2.9.0 2021-12-08 18:51:00 +01:00
NEZNAMY 313ba8d765 attempt to fix error caused by concurrent access 2021-12-08 18:43:22 +01:00
NEZNAMY c12c422357 fix NPE when editing unknown bossbar 2021-12-08 18:37:56 +01:00
NEZNAMY b14c97d18a add try/catch for ConcurrentModificationException 2021-12-08 18:34:39 +01:00
NEZNAMY 2fe345cb65 add back "barcolors" animation since it's used in default config 2021-12-08 18:11:03 +01:00
NEZNAMY 96ff81370c fix animations lagging when using nested animations 2021-12-08 18:09:48 +01:00
Leon Mangler c4a1f41673 Load TAB after PremiumVanish
When BungeeTabPlayer#isVanished uses PV's API, PV needs to actually be enabled, not just loaded. A soft-dependency should ensure that PV is fully enabled before TAB's onEnable() uses the API.
2021-12-08 17:37:13 +01:00
NEZNAMY ca4c8ccb20 Merge branch 'master' of https://github.com/NEZNAMY/TAB 2021-12-08 15:57:51 +01:00
Callum Seabrook 7471006f8a Updated to Krypton 0.58 2021-12-07 18:14:23 +00:00
NEZNAMY 896c709824 fix small memory leak 2021-12-04 22:41:55 +01:00
NEZNAMY 473a37cb6a fix NPE 2021-12-04 22:29:10 +01:00
NEZNAMY 9e84d96051 Add back %essentialsnick% for all the crybabies we get in #community-support who didn't even bother reading changelog of a major plugin update which is supposed to hint big changes were made and the changelog should be read. 2021-12-04 20:56:30 +01:00
NEZNAMY 019466d84d remove unused code 2021-12-04 19:27:02 +01:00
NEZNAMY c222061529 slightly optimize width calculation & partially avoid #347 2021-12-04 19:15:36 +01:00
NEZNAMY acdd99404c use different functions for file operations 2021-12-04 19:08:58 +01:00
NEZNAMY 799381bff3 properly convert objects to string 2021-12-04 19:02:11 +01:00
NEZNAMY b3654977ca cast to long 2021-12-04 18:59:03 +01:00
NEZNAMY b67d1928b5 add "final" modifier 2021-12-04 18:58:00 +01:00
NEZNAMY 052748d2b9 simplify 2021-12-04 18:47:18 +01:00
NEZNAMY e265187ff8 call function instead of duplicating code 2021-12-04 18:10:44 +01:00
NEZNAMY c622a95550 use fixed interval to avoid startup error 2021-12-04 17:09:40 +01:00
NEZNAMY 94d71a245b Merge branch 'master' of https://github.com/NEZNAMY/TAB 2021-12-04 13:28:23 +01:00
NEZNAMY a9403269be add LP softdepend on bungeecord 2021-12-04 13:26:16 +01:00
Callum Seabrook dfe6768eb5 Moved YamlAssist to Krypton repository version 2021-12-04 12:19:55 +00:00
Callum Seabrook d88bf65806 Setup publishing for all but the JAR module 2021-12-04 12:05:35 +00:00
NEZNAMY 30929062d6 what happened here 2021-12-04 12:20:56 +01:00
NEZNAMY 747e3d692d clear registered teams on login packet 2021-12-04 12:16:07 +01:00
Callum Seabrook 1d3ecbb7ed Somehow forgot that display name is now nullable 2021-12-04 10:28:25 +00:00
Callum Seabrook 39b88b0dd5 Updated Krypton to 0.57 2021-12-04 10:24:18 +00:00
NEZNAMY d13d3eb055 bridge placeholders will return identifier until they are initialized instead of null 2021-12-03 16:21:04 +01:00
NEZNAMY f8f72b9074 rgb support for remaining players text as well 2021-12-03 15:47:51 +01:00
NEZNAMY a9d0b0a0ae 3.0.1-pre1 2021-12-03 15:38:46 +01:00
NEZNAMY 37bd624537 double-fix for bungeecord bug kick 2021-12-03 15:37:23 +01:00
NEZNAMY e19f4ed771 reorder bungee.yml to match PluginDescription.java order 2021-12-03 12:11:27 +01:00
NEZNAMY c828fa8d52 Merge remote-tracking branch 'origin/master' 2021-12-03 12:00:36 +01:00
NEZNAMY 9e080a5f5c add argument check 2021-12-03 12:00:20 +01:00
NEZNAMY 7d7d4c05ab remove debug message 2021-12-03 11:59:34 +01:00
NEZNAMY d4c7044708 add proper color support to layout more players text 2021-12-02 20:36:38 +01:00
Callum Seabrook 52dd8c7c8b Added run folder to gitignore for test servers 2021-12-02 18:49:11 +00:00
NEZNAMY 398ac8b6cf register invalid relational placeholders on proxy correctly, so it doesn't throw errors 2021-12-02 18:12:53 +01:00
NEZNAMY 911792b214 Merge branch 'master' of https://github.com/NEZNAMY/TAB 2021-12-02 13:50:21 +01:00
Callum Seabrook 8e54989502 Setup new publish repository for API 2021-12-02 12:49:11 +00:00
NEZNAMY 4f16579063 support mineskin by uuid 2021-12-02 11:01:19 +01:00
NEZNAMY e1f1698413 fix startup on mohist 1.12.2 2021-12-02 10:09:25 +01:00
NEZNAMY 5eb999b98a fixed typos, capital letters, more docs 2021-12-01 15:52:18 +01:00
NEZNAMY 5e7af835d8 %online% cannot be trigger due to vanish checks 2021-12-01 10:12:05 +01:00
NEZNAMY f19f2c5a20 add conversion for multiple groups with same sorting priority 2021-12-01 08:57:24 +01:00
NEZNAMY ff2aceb781 fix placeholder in default layout.yml 2021-12-01 08:50:37 +01:00
NEZNAMY dc1410adbb update README 2021-11-30 22:05:57 +01:00
NEZNAMY 49af38f3c5 3.0.0 2021-11-30 19:42:48 +01:00
NEZNAMY 09cf4dcd07 actually fix krypton compilation 2021-11-30 19:42:37 +01:00
Callum Seabrook 95c92285b9 Fixed Krypton 2021-11-30 18:05:07 +00:00
NEZNAMY 81b7be9205 remove tpsbar from default config (it's on wiki now) 2021-11-30 18:19:06 +01:00
NEZNAMY c308cde139 fix condition default value of "false" 2021-11-29 18:47:27 +01:00
NEZNAMY 49889cd2cc fix %afk% conversion 2021-11-29 12:33:28 +01:00
NEZNAMY d0ea71f0c9 fix method name 2021-11-28 21:42:25 +01:00
NEZNAMY a6f93dae1e Merge pull request #418 from KryptonMC/v3
Added blossom for plugin version source replacement
2021-11-28 13:34:09 +01:00
Callum Seabrook f968999393 Added blossom for plugin version source replacement 2021-11-28 12:21:15 +00:00
NEZNAMY 37348ed1f4 3.0.0-pre4 2021-11-28 12:19:41 +01:00
NEZNAMY 8602d39d7c fix mysql & load playerdata on every join 2021-11-28 12:14:34 +01:00
NEZNAMY fd41390e20 Merge pull request #417 from NEZNAMY/revert-416-v3
Revert "Switched to adapters over whacky NMSStorage"
2021-11-28 00:44:36 +01:00
NEZNAMY 712064bced Revert "Switched to adapters over whacky NMSStorage" 2021-11-28 00:44:25 +01:00
NEZNAMY 771a696de0 Merge pull request #416 from KryptonMC/v3
Switched to adapters over whacky NMSStorage
2021-11-28 00:02:01 +01:00
Callum Seabrook a56cbcc2f4 Added 1_17_R1 adapter 2021-11-27 23:01:11 +00:00
Callum Seabrook 8e659a2c97 Switched to adapters over whacky NMSStorage 2021-11-27 22:41:04 +00:00
NEZNAMY 423bd0adb8 1.18 2021-11-27 21:28:41 +01:00
NEZNAMY 1987848f8b fix weird NPE 2021-11-27 21:28:36 +01:00
NEZNAMY 13ac8541f2 fix utf symbol in default config 2021-11-27 21:04:31 +01:00
NEZNAMY 0e42d61ffa add %tab_scoreboard_name% placeholder 2021-11-27 18:09:35 +01:00
NEZNAMY 64b4cb1bb9 fix component cloning missing color 2021-11-27 14:08:13 +01:00
NEZNAMY efd723deec add else statement 2021-11-26 21:19:46 +01:00
NEZNAMY 4c2d2068a4 Merge pull request #415 from AlessioGr/v3
Improve TAB Completion for /tab width command
2021-11-25 11:14:37 +01:00
AlessioGr 32529dd7e9 Improve TAB Completion for /tab width command
Signed-off-by: AlessioGr <alessio@gravili.de>
2021-11-25 11:12:04 +01:00
NEZNAMY 3ad54d5f21 Merge pull request #414 from AlessioGr/v3
Further improve Width command
2021-11-25 10:56:38 +01:00
AlessioGr 6d81c37645 Further improve Width command
Signed-off-by: AlessioGr <alessio@gravili.de>
2021-11-25 10:50:53 +01:00
NEZNAMY da1c51eb5b Merge pull request #413 from AlessioGr/v3
Improve /tab width command
2021-11-25 10:18:26 +01:00
AlessioGr 70c37fb9f2 fix Codacy Static Code Analysis warning
Signed-off-by: AlessioGr <alessio@gravili.de>
2021-11-25 10:17:01 +01:00
AlessioGr 5e565be35b Improve /tab width command
Signed-off-by: AlessioGr <alessio@gravili.de>
2021-11-25 10:07:32 +01:00
NEZNAMY eeb39ca228 code style 2021-11-25 09:09:56 +01:00
NEZNAMY 2d5bc2bc52 on load as well 2021-11-24 15:08:47 +01:00
NEZNAMY 4fb517c8cb fix #412 2021-11-24 15:08:07 +01:00
NEZNAMY de376cd9f4 fix onServerChange not being called when it should be 2021-11-24 15:06:52 +01:00
NEZNAMY d939984f08 refresh animations at their original rate while keeping sync 2021-11-24 14:47:19 +01:00
NEZNAMY 89edcb7a38 fix %online_<server>% placeholders 2021-11-24 14:17:53 +01:00
NEZNAMY ac16a0fb26 set gradients first to fix issue from latest new format 2021-11-24 07:39:39 +01:00
NEZNAMY 9189fb2082 3.0.0-pre3 2021-11-23 00:03:38 +01:00
NEZNAMY a2e7670560 Merge branch 'v3' of https://github.com/NEZNAMY/TAB into v3 2021-11-22 23:13:55 +01:00
NEZNAMY 7c9f14b4d9 Merge pull request #411 from KryptonMC/v3
Added Java components for publishing and sources and javadoc jars
2021-11-22 23:13:29 +01:00
NEZNAMY f05849aada fix error on reload 2021-11-22 21:14:00 +01:00
NEZNAMY 66e91ee4e8 don't set numbers if disabled 2021-11-22 21:10:01 +01:00
NEZNAMY 015d8de101 fix error with static lines 2021-11-22 21:08:54 +01:00
Callum Seabrook 69e575e0ef Added Java components for publishing and sources and javadoc jars 2021-11-22 18:46:14 +00:00
NEZNAMY 6c84e49a7f improve default files 2021-11-22 10:01:37 +01:00
NEZNAMY f4e5e8fd72 fix startup error 2021-11-22 09:51:13 +01:00
NEZNAMY fe8c738196 only catch ClassNotFoundException in fabric check 2021-11-22 09:37:20 +01:00
NEZNAMY 665dfac5ea remove unnecessary String.valueOf 2021-11-21 21:50:33 +01:00
NEZNAMY 57f9806819 fix /tab reload breaking external placeholders 2021-11-21 21:32:44 +01:00
NEZNAMY 7874135014 update scoreboard scores when line hides/shows 2021-11-21 21:32:28 +01:00
NEZNAMY f86e7b17ef add another rgb format 2021-11-21 21:04:51 +01:00
NEZNAMY 3803173745 Merge branch 'v3' of https://github.com/NEZNAMY/TAB into v3 2021-11-21 13:31:56 +01:00
NEZNAMY 6af30bf6df improve placeholder registration at runtime 2021-11-21 13:31:43 +01:00
NEZNAMY 7bea6a214a Merge pull request #410 from KryptonMC/v3
Updated Krypton, added vehicle support, and fixed many features being non-functional
2021-11-21 13:30:51 +01:00
Callum Seabrook 9becc35fa1 Fixed many features in Krypton 2021-11-21 12:24:52 +00:00
NEZNAMY 7212a4cd7f round health up 2021-11-21 12:09:24 +01:00
NEZNAMY c604640ab9 fix placeholder registration at runtime 2021-11-21 11:23:13 +01:00
NEZNAMY 23fee2b7b7 fix LP suffix placeholder 2021-11-20 23:44:32 +01:00
NEZNAMY c3d521960e only call onDisable if placeholder was used 2021-11-20 23:09:44 +01:00
NEZNAMY 484396cce1 move %online% update to a better spot and fix NPE 2021-11-20 22:50:49 +01:00
NEZNAMY ce4dec6136 disable krypton compilation 2021-11-20 21:13:59 +01:00
NEZNAMY 67f42f518e implement trigger placeholders 2021-11-20 21:13:50 +01:00
Callum Seabrook 0a0e947282 Added option to specify the config name to use 2021-11-20 19:46:26 +00:00
Callum Seabrook 8a4127574a Fixed NPEs from packets and formatting on Spark placeholders 2021-11-20 18:33:20 +00:00
Callum Seabrook b29d3e5d6a Updated to Krypton 0.50 and made vehicle refresher actually work 2021-11-20 17:41:46 +00:00
NEZNAMY daaece8d36 Merge branch 'v3' of https://github.com/NEZNAMY/TAB into v3 2021-11-20 11:48:49 +01:00
NEZNAMY 0e5b1aaf0e obtain channel instance 2021-11-20 11:48:28 +01:00
NEZNAMY e672e49435 Merge pull request #409 from KryptonMC/v3
Updated Krypton to latest and added support for newest changes
2021-11-20 11:13:50 +01:00
NEZNAMY b9a38a486d make packetBuilder field editable 2021-11-20 10:59:21 +01:00
Callum Seabrook d34c46658d Added refresh display names to refresher constructors 2021-11-19 23:54:48 +00:00
Callum Seabrook e120b647ea Cleaned up Krypton platform and added support for new features 2021-11-19 23:52:46 +00:00
Callum Seabrook 936b8ae903 Updated to Krypton 0.48.1 2021-11-19 23:52:19 +00:00
NEZNAMY 147fe2c277 fix krypton 2021-11-20 00:14:06 +01:00
NEZNAMY 84413aa490 define refresh display name in super() call 2021-11-19 23:13:19 +01:00
NEZNAMY 3fea95f8c5 instance is never null 2021-11-19 22:51:53 +01:00
NEZNAMY b839bce010 change display name and split elsewhere in cpu output 2021-11-19 22:51:05 +01:00
NEZNAMY fc70c098a9 add "final" modifier to all fields possible 2021-11-18 23:00:09 +01:00
NEZNAMY 7b74d73a9a add getter for defined lines into API 2021-11-18 20:38:54 +01:00
NEZNAMY 44ee3bbdfe using shortcuts 2021-11-18 18:30:05 +01:00
NEZNAMY 673285baf8 copy files automatically in UTF-8 encoding 2021-11-18 15:47:10 +01:00
NEZNAMY 2b22e327e3 cache player name widths in aligned suffix
and maybe introduce new bugs, who knows
2021-11-18 15:20:25 +01:00
NEZNAMY 95d65236f6 in NPE 2021-11-18 14:11:02 +01:00
NEZNAMY 8971172444 fix typo in messages 2021-11-18 14:08:05 +01:00
NEZNAMY 6ff5836ca9 fix NPE on fabric 2021-11-18 12:01:47 +01:00
NEZNAMY 8e9a4e9601 use the other way of checking server minor version 2021-11-18 11:54:17 +01:00
NEZNAMY 1ce5c05622 use more universal code 2021-11-18 11:48:52 +01:00
NEZNAMY 7f83e83aed refresh boats in vehicle refresher as well 2021-11-18 11:33:37 +01:00
NEZNAMY e677e7345b remove vehicle on quit 2021-11-18 11:18:11 +01:00
NEZNAMY ae52aa2c55 instant vehicle enter teleport instead of an animation 2021-11-18 11:13:40 +01:00
NEZNAMY b83f6e93bf refreshing vehicles and preview using placeholder engine instead of refreshing task 2021-11-18 11:01:37 +01:00
NEZNAMY 3606ee6275 fix startup on fabric 2021-11-17 21:28:48 +01:00
NEZNAMY 70571cccfe replace stacked reflection exceptions with ReflectiveOperationException 2021-11-17 21:20:12 +01:00
NEZNAMY 87fe02b0b4 attempt to clean up NMSStorage class 2021-11-17 21:05:23 +01:00
NEZNAMY 8e48087f65 load config options in field declarations instead of constructors 2021-11-17 18:45:58 +01:00
NEZNAMY 4e7c3ee2f1 remove duplicated file 2021-11-17 13:33:17 +01:00
NEZNAMY 60a7549662 move constants 2021-11-17 13:32:51 +01:00
NEZNAMY fe7c9488d8 rework property API per-feature 2021-11-16 16:51:31 +01:00
NEZNAMY b7d39e55b6 send armor stand destroy without delay as well 2021-11-16 16:10:51 +01:00
NEZNAMY 805d8030b4 add option to disable unlimited nametags for specific player using API 2021-11-16 16:08:06 +01:00
NEZNAMY 4c6fc5d2d2 fix #408
caused by unregister-register operation on server switch being removed in v3 due to per-world/per-server scoreboards being removed
2021-11-16 12:18:30 +01:00
NEZNAMY 913b8ee238 avoid duplicating code 2021-11-16 11:49:54 +01:00
NEZNAMY 3688e4d938 Merge pull request #407 from KryptonMC/gradle
Gradle!
2021-11-15 21:58:41 +01:00
Callum Seabrook 03842db57f Removed SonarQube and updated workflow to match 2021-11-15 20:56:19 +00:00
Callum Seabrook 6f34157a84 Added inclusion for gradle wrapper 2021-11-15 20:56:19 +00:00
Callum Seabrook 86a82faa15 Fixed Krypton and Velocity annotation processors not working 2021-11-15 20:56:19 +00:00
Callum Seabrook 2e506b72a6 Fixed incorrect shading 2021-11-15 20:56:19 +00:00
Callum Seabrook d2ba0a22d5 These should be this 2021-11-15 20:56:19 +00:00
Callum Seabrook cfc3488a8c Switched build to Gradle 2021-11-15 20:56:17 +00:00
NEZNAMY 0463e82470 Merge pull request #406 from NEZNAMY/revert-405-v3
Revert "Made Krypton a separate JAR"
2021-11-15 18:12:08 +01:00
NEZNAMY 93b151b377 Revert "Made Krypton a separate JAR" 2021-11-15 18:11:47 +01:00
NEZNAMY 1c6fa28d87 Merge pull request #405 from KryptonMC/v3
Made Krypton a separate JAR
2021-11-15 18:06:23 +01:00
Callum Seabrook 71d01263b5 Made Krypton a separate JAR 2021-11-15 17:04:50 +00:00
NEZNAMY 23268907bd compile krypton with java 8 2021-11-15 17:22:43 +01:00
NEZNAMY 076e3061b3 fix pauseTeamHandling not disabling unlimited nametags 2021-11-15 17:15:33 +01:00
NEZNAMY d9f8fa2ed0 split feature elements in cpu output 2021-11-15 16:03:13 +01:00
NEZNAMY c33f9a6d61 drop latency refresher since it doesn't work with new change anymore 2021-11-15 15:49:57 +01:00
NEZNAMY 07f71f3d4d add support for CMI's {#RRGGBB<>} shortcut 2021-11-15 15:40:46 +01:00
NEZNAMY 48f8a4c718 fix spectators exposed for players who joined
caused by pipeline injection being late (async)
2021-11-15 15:03:33 +01:00
NEZNAMY ff29b1badf remove deleted options from conversion 2021-11-15 14:54:49 +01:00
NEZNAMY 05d3233c03 fix typo 2021-11-15 14:50:19 +01:00
NEZNAMY 203b5d925b fix wrong argument 2021-11-15 14:30:08 +01:00
NEZNAMY b2f6338b0b fix krypton 2021-11-15 14:12:32 +01:00
NEZNAMY 26e526d5fe create constants for permission checks 2021-11-15 13:55:03 +01:00
NEZNAMY 054d6c58cb rename class 2021-11-15 13:22:42 +01:00
NEZNAMY cc6b5ea0f5 add missing repository 2021-11-15 13:16:32 +01:00
NEZNAMY 495985ace8 Merge branch 'v3' of https://github.com/NEZNAMY/TAB into v3 2021-11-15 12:36:55 +01:00
NEZNAMY a304853a7b rework command output messages and rename file translation.yml -> messages.yml 2021-11-15 12:36:52 +01:00
NEZNAMY eb2c58f0e9 Merge pull request #404 from KryptonMC/feature/krypton
Added support for Krypton
2021-11-15 12:09:31 +01:00
NEZNAMY 125429bccd ignore case when getting player by name 2021-11-15 11:23:33 +01:00
Callum Seabrook c5bf1b65ba Added online placeholders and made spark placeholders server placeholders 2021-11-14 15:09:35 +00:00
Callum Seabrook 5286a018df Added support for Krypton 2021-11-14 15:09:34 +00:00
NEZNAMY c408744385 add back %% transforming into a single % 2021-11-14 14:19:05 +01:00
NEZNAMY 5efd5f310f change names of slots 2021-11-13 23:52:15 +01:00
NEZNAMY e35c14d8e3 measure NMS hook load time 2021-11-13 22:07:55 +01:00
NEZNAMY d49fcc2307 properly send action bar messages on velocity 2021-11-13 18:48:49 +01:00
NEZNAMY afc1dfcf10 remove redundant initialization 2021-11-13 14:49:17 +01:00
NEZNAMY 2dd06ed0c3 cleanup in placeholder registration 2021-11-13 13:35:28 +01:00
NEZNAMY 2ca223cd2c drop AntiAFKPlus hook 2021-11-13 13:24:29 +01:00
NEZNAMY f6cf018625 update supported versions 2021-11-13 13:18:45 +01:00
NEZNAMY 1d7806c96e fill exception message 2021-11-12 17:18:05 +01:00
NEZNAMY 650fd892f8 fix error when output is not a number 2021-11-12 16:52:52 +01:00
NEZNAMY 83710b14b1 add "me" player name completion to /tab parse 2021-11-12 16:47:49 +01:00
NEZNAMY 1eeb22f579 do not send score changes when player is not loaded yet 2021-11-12 16:47:31 +01:00
NEZNAMY 1d70e73106 add null check for redisbungee api instance 2021-11-12 13:57:37 +01:00
NEZNAMY 9d93b52be1 only process nicking once instead of for every online player 2021-11-12 13:21:52 +01:00
NEZNAMY 4431772007 create instance of CollisionManager on 1.8 to prevent NPEs 2021-11-12 13:15:14 +01:00
NEZNAMY f17fafbb48 shorter alternative 2021-11-11 22:41:31 +01:00
NEZNAMY 8d30399f33 initial support for nick plugins 2021-11-11 22:20:59 +01:00
NEZNAMY 5feb934a4a add space 2021-11-11 18:06:30 +01:00
NEZNAMY 9466b96f69 properly forward team flags in packets 2021-11-11 13:08:40 +01:00
NEZNAMY ad00d1b145 only start layout feature on 1.8+ 2021-11-11 13:08:06 +01:00
NEZNAMY 89ea9ba8a0 return empty list instead of null 2021-11-11 11:57:24 +01:00
NEZNAMY e08fb3eeb6 fix skin saving 2021-11-11 11:52:58 +01:00
NEZNAMY 5800c8910e split skinmanager class into multiple 2021-11-11 11:48:55 +01:00
NEZNAMY 1ec77cb0b5 don't refresh collision if no disguise plugin is available 2021-11-11 11:09:37 +01:00
NEZNAMY 3329514066 decrease default time to 10000 since it can't get higher than that anyway 2021-11-11 10:41:11 +01:00
NEZNAMY addc3f322f load feature after registering placeholders correctly to avoid wrong registration 2021-11-11 10:40:56 +01:00
NEZNAMY 79dcd16d37 only refresh visibility if 1.8.x clients are accepted 2021-11-11 10:09:58 +01:00
NEZNAMY 802c72a9aa don't refresh collision if it's disabled already 2021-11-10 22:53:01 +01:00
NEZNAMY bf96676df5 properly update collision on api call 2021-11-10 22:48:21 +01:00
NEZNAMY d245b93196 remove unnecessary this. 2021-11-10 21:51:59 +01:00
NEZNAMY 6f96b555e9 split collision management into separate class + placeholder based refreshing instead of repeating task 2021-11-10 21:47:48 +01:00
NEZNAMY 872700d1be create placeholder for visibility check instead of refreshing task 2021-11-10 21:01:07 +01:00
NEZNAMY 1ac08ee1f2 try/catch for more exception types 2021-11-10 20:34:06 +01:00
NEZNAMY ada433150c fix forceTeamName method not working 2021-11-10 13:58:02 +01:00
NEZNAMY ee40a69e57 use cleaner alternative 2021-11-10 13:57:37 +01:00
NEZNAMY d6fcaffa99 add team name changing support to redisbungee 2021-11-10 13:45:42 +01:00
NEZNAMY fe4bdda549 fix property name in debug output 2021-11-10 13:01:08 +01:00
NEZNAMY 6a1016a383 move &r 2021-11-10 12:59:14 +01:00
NEZNAMY c53f08d0a7 surround deserialize method with try/catch instead of throwing 2021-11-10 11:59:51 +01:00
NEZNAMY 2807ff30e6 fix premiumconfig not being deleted 2021-11-10 11:23:41 +01:00
NEZNAMY cf3b9c21dd apply rgb formats later so raw value returns actual raw value 2021-11-09 11:07:28 +01:00
NEZNAMY ee616412d6 simplify 2021-11-08 19:13:45 +01:00
NEZNAMY 341c6f8722 3.0.0-pre2 2021-11-07 15:27:25 +01:00
NEZNAMY 978df99e5c create dummy placeholder instead of thread for cpu stats reset 2021-11-06 19:19:03 +01:00
NEZNAMY a91e2a90b4 fix substring size 2021-11-06 15:25:44 +01:00
NEZNAMY 49c54c6a58 Merge pull request #402 from Tanguygab/v3
added texture skin type for Layout SkinManager
2021-11-04 12:17:38 +01:00
Tanguygab 6b72163dbe added texture: skin type 2021-11-04 12:09:14 +01:00
NEZNAMY 93a04c64d2 fix startup error with relational placeholders 2021-11-03 22:41:15 +01:00
NEZNAMY d01d814778 show configured fake ping instead of 0 2021-11-02 21:33:39 +01:00
NEZNAMY af15c256b9 use more accurate task name 2021-11-02 21:32:16 +01:00
NEZNAMY dde0056ba2 fix nested placeholders not working in replacements 2021-11-02 20:34:25 +01:00
NEZNAMY dede5b548c reduce memory allocations of property loading 2021-11-02 14:55:02 +01:00
NEZNAMY 7be0831e7c do not use split function if not needed 2021-11-02 14:33:54 +01:00
NEZNAMY 660275dc74 change List to array 2021-11-02 13:37:45 +01:00
NEZNAMY 957e01fbf2 dynamic placeholder refresh task interval based on fastest placeholder 2021-11-02 00:41:14 +01:00
NEZNAMY b01ffaf763 simplify 2021-11-02 00:00:54 +01:00
NEZNAMY 8d6d53a448 use stringbuilder 2021-11-01 22:34:45 +01:00
NEZNAMY 8f13bfcb4a merge ifs 2021-11-01 22:32:29 +01:00
NEZNAMY ddf45bf7a7 remove unnecessary {} 2021-11-01 22:31:36 +01:00
NEZNAMY 9fabeac7e1 remove redundant cast 2021-11-01 22:30:15 +01:00
NEZNAMY 758b1f9365 simplify return 2021-11-01 22:29:34 +01:00
NEZNAMY 0050d34d0e remove redundant check 2021-11-01 22:27:09 +01:00
NEZNAMY fd547383c4 remove unused methods 2021-11-01 22:02:35 +01:00
NEZNAMY edb640f496 add expected team name into logging 2021-11-01 21:38:35 +01:00
NEZNAMY 4569fa3e86 optimize method 2021-11-01 21:22:58 +01:00
NEZNAMY 33af012352 remove redundant call 2021-11-01 20:58:42 +01:00
NEZNAMY 5cc6688d9c optimize disabled world checking for unlimited nametags 2021-11-01 20:45:40 +01:00
NEZNAMY f8a5f610bb remove redundant null check 2021-11-01 18:57:12 +01:00
NEZNAMY 877ac8adc7 GroupManager refreshing engine change from repeating task to placeholder core 2021-11-01 18:22:36 +01:00
NEZNAMY 39040c263e refresh world on switch instead of periodically on proxy 2021-11-01 17:03:05 +01:00
NEZNAMY 08759762a1 fix global playerlist on velocity 2021-11-01 15:50:12 +01:00
NEZNAMY 7897fbcf36 fix tablist format on server switch on velocity 2021-11-01 15:45:09 +01:00
NEZNAMY ce93bb1afb fix NPE with component sent to console 2021-11-01 15:12:44 +01:00
NEZNAMY 3e8085f460 fix sorting startup with layout on proxy 2021-11-01 15:06:09 +01:00
NEZNAMY 2ab201d278 print LibsDisguises hook error once instead of spamming it 2021-11-01 14:42:09 +01:00
NEZNAMY ccdac844b9 move plugin info component to command class 2021-11-01 14:39:34 +01:00
NEZNAMY 4474939c51 small code structure change 2021-11-01 14:19:31 +01:00
NEZNAMY f32975ccb0 decrease wither distance to 60 blocks 2021-11-01 14:17:05 +01:00
NEZNAMY 4f92b22955 use placeholder refreshing engine for bossbar updating instead of repeating task
this will also reduce teleports if players don't move
2021-11-01 14:07:24 +01:00
NEZNAMY 1d8ac0ab45 warn in console about Tablisknu compatibility issue 2021-11-01 12:52:33 +01:00
NEZNAMY 4cfc5258b2 add separate cpu measuring of hasPermission method 2021-11-01 12:30:48 +01:00
NEZNAMY 14b7415005 cache floodgate presence 2021-11-01 00:29:48 +01:00
NEZNAMY f482b712ca save registered scoreboards in array to reduce allocations from iteration 2021-11-01 00:25:40 +01:00
NEZNAMY c40a5cbaaa changed parse command syntax to include player name 2021-11-01 00:13:14 +01:00
NEZNAMY 9d0efca1e5 avoid any possible double bossbar create 2021-10-29 13:03:37 +02:00
NEZNAMY cf4d76e9a4 make method synchronized to avoid rare error 2021-10-28 15:58:12 +02:00
NEZNAMY 56569509f9 use ConcurrentHashMap to avoid ConcurrentModificationException 2021-10-27 21:07:05 +02:00
NEZNAMY a0904be305 use more appropriate names for anonymous conditions 2021-10-26 21:15:14 +02:00
NEZNAMY 7d156fb47b fix rare NPE 2021-10-26 21:04:34 +02:00
NEZNAMY e1796d24ad fix mysql 2021-10-24 10:48:19 +02:00
NEZNAMY 2899b1f8eb add announcement-bar property instead of listing default-bars 2021-10-21 13:14:14 +02:00
NEZNAMY 335a033091 fix NPE 2021-10-21 09:24:22 +02:00
NEZNAMY 80aa2367b0 add back width command
as well as showing character sequence if a multi-character symbol is entered
2021-10-20 21:06:17 +02:00
NEZNAMY e6ca5884a3 only decrease interval instead of possibly increasing 2021-10-20 20:14:59 +02:00
NEZNAMY ef52c84e25 calculate condition refresh intervals based on fastest placeholder 2021-10-20 19:03:25 +02:00
NEZNAMY 478f2fc9ae add back support for ; and * for groups in per-world / per-server 2021-10-20 18:25:21 +02:00
NEZNAMY 98afededa6 create method to clean up code 2021-10-20 18:04:03 +02:00
NEZNAMY 7ad2ca9f16 add viaversion compatibility check 2021-10-20 18:02:13 +02:00
NEZNAMY 03ab379c63 remove default-scoreboard option when converting config 2021-10-20 17:51:38 +02:00
NEZNAMY bd71efd22b update readme to reflect this branch 2021-10-19 22:52:27 +02:00
NEZNAMY 87b7a1c759 initial RedisBungee support
this update was only slightly tested and may contain bugs, which will eventually be fixed
2021-10-19 22:49:40 +02:00
NEZNAMY 5c59c3b1b8 fix server switch listener on bungeecord 2021-10-19 21:18:08 +02:00
NEZNAMY bb98db4568 remove and rename placeholders 2021-10-19 20:42:23 +02:00
NEZNAMY 80f0afd600 disable layout by default 2021-10-19 14:17:56 +02:00
NEZNAMY 5bc37b51bb fix player initialization 2021-10-19 14:10:04 +02:00
NEZNAMY 0f68892d11 add sorting by player name to conversion 2021-10-18 18:23:50 +02:00
NEZNAMY 37e731c2fd fix typo 2021-10-18 14:10:06 +02:00
NEZNAMY 8312ae30f1 add getter for spyServers list 2021-10-18 13:58:50 +02:00
NEZNAMY 28ec42dddf improve parity between platforms 2021-10-17 20:45:25 +02:00
NEZNAMY d9f572188e bump YamlAssist version 2021-10-17 16:54:47 +02:00
NEZNAMY 720a95d472 3.0.0-pre1 2021-10-17 12:12:35 +02:00
NEZNAMY 74ba60f4f1 fix resetScoreboard not working 2021-10-16 21:35:52 +02:00
NEZNAMY e717473a21 code style 2021-10-16 00:39:26 +02:00
NEZNAMY aca1e26c3b attempt to fix concurrent modification 2021-10-15 21:27:18 +02:00
NEZNAMY 0b1bcebc72 move initialization 2021-10-15 21:07:16 +02:00
NEZNAMY 058a5dca17 fix NPE 2021-10-15 20:43:17 +02:00
NEZNAMY da21131f9c code style 2021-10-15 20:35:25 +02:00
NEZNAMY 30fd9f84e0 code style 2021-10-15 20:29:35 +02:00
NEZNAMY 291f881e61 remove unused import 2021-10-15 19:52:13 +02:00
NEZNAMY bdb465b54e change return type from Future<?> to Future<Void> 2021-10-15 19:46:26 +02:00
NEZNAMY e39a10da22 code style 2021-10-15 17:37:48 +02:00
NEZNAMY 8f4ab6a7f1 fix premiumconfig absence when using free version 2021-10-15 17:20:22 +02:00
NEZNAMY 3259fc1a52 improve console message 2021-10-15 17:16:32 +02:00
NEZNAMY 05d85a0dc1 rethrow exceptions 2021-10-15 17:05:24 +02:00
NEZNAMY e7c4658805 add missing collision option conversion 2021-10-15 17:02:14 +02:00
NEZNAMY 51220bcae6 fix startup when sorting placeholder is not valid 2021-10-15 17:01:47 +02:00
NEZNAMY e8ff42dd75 fix typos 2021-10-15 17:01:15 +02:00
NEZNAMY 6bd54ccf2b Merge pull request #393 from Tanguygab/v3
Added 2.9.2 -> 3.0 config converter
2021-10-15 16:42:54 +02:00
NEZNAMY c3bcaba61e reduce retry count and only print error if debug is enabled 2021-10-15 16:40:37 +02:00
Tanguygab 14693b4a6e converting _OTHER_ to _DEFAULT_ 2021-10-13 15:12:12 +02:00
Tanguygab b1a75df507 Merge remote-tracking branch 'upstream/v3' into v3 2021-10-13 14:58:57 +02:00
NEZNAMY 42d65cf0dd create a copy of map to avoid error on modification 2021-10-10 17:08:30 +02:00
NEZNAMY b18803e343 add null check 2021-10-10 17:00:15 +02:00
NEZNAMY a36a071dbe update sorting error message to match new config 2021-10-10 16:53:39 +02:00
NEZNAMY edc95e1fa0 create dummy entity to use in packet constructor instead of using first player
which randomly caused NoSuchElementException
2021-10-10 16:51:14 +02:00
NEZNAMY 11b3d3ef41 remove unnecessary null check from previous testing 2021-10-10 16:45:10 +02:00
NEZNAMY 64f339b1fa synchronize list to avoid rare toArray null element issue 2021-10-10 16:09:09 +02:00
Tanguygab a6eefa7afd using File.separator instead of \\ 2021-10-09 00:53:26 +02:00
Tanguygab 837d1fb43d check if legacy config 2021-10-09 00:44:56 +02:00
Tanguygab 0d190b4ade checking if file already exists 2021-10-09 00:30:25 +02:00
Tanguygab fbc7acea60 wrong config 2021-10-09 00:25:29 +02:00
Tanguygab e6676e1a05 added 2.9.2 -> 3.0 config conversion 2021-10-09 00:22:28 +02:00
Tanguygab b9a56c6c65 Intellij didn't recognize API's classes without that for some reasons 2021-10-09 00:21:42 +02:00
NEZNAMY 520c152cc6 add debug message when missing config option was added 2021-10-08 23:35:20 +02:00
NEZNAMY f7ddf6f872 add null check 2021-10-07 09:57:05 +02:00
NEZNAMY e6997d81c1 do not show layout to bedrock and 1.7 players 2021-10-06 09:57:16 +02:00
NEZNAMY 31923fc73c attempt to fix rare error 2021-10-03 23:30:33 +02:00
NEZNAMY 5dbfc97780 fix placeholders only used in tab expansion not refreshing 2021-10-03 23:30:11 +02:00
NEZNAMY da525fa1c8 no longer require nametag sorting feature for layout to work 2021-09-23 18:39:01 +02:00
NEZNAMY 372866ee95 fix typo 2021-09-23 14:41:10 +02:00
NEZNAMY d1e1df01c0 only recalculate used placeholders if changed 2021-09-23 11:53:20 +02:00
NEZNAMY b12d9f352b port changes from #389 2021-09-20 22:38:48 +02:00
NEZNAMY b3dc4b617b change lists back to sets to avoid duplicates and cpu leak 2021-09-20 20:18:54 +02:00
NEZNAMY 67e3ff368d create class for placeholder replacements and reduce memory allocations 2021-09-20 18:25:48 +02:00
NEZNAMY 569ad41894 separate groupmanager class and fix loading order 2021-09-19 00:42:55 +02:00
NEZNAMY bd5225967d replace all sets with lists 2021-09-15 18:14:45 +02:00
NEZNAMY 9c9df4ee3b pre-parse static numeric values in conditions for better performance and lower memory allocations 2021-09-13 21:26:10 +02:00
NEZNAMY a859a20062 fix API scoreboard overridden on world/server switch 2021-09-13 21:03:43 +02:00
NEZNAMY 4fd8e736f9 add option to disable remaining players text in layout 2021-09-13 20:56:46 +02:00
NEZNAMY 41fc9b329b improve placeholder exception catching 2021-09-12 13:37:29 +02:00
NEZNAMY 3ea9408103 optimize conditions using functions 2021-09-11 23:33:44 +02:00
NEZNAMY 589170ac8a catch specific exceptions and remove redundant catch 2021-09-11 23:29:26 +02:00
NEZNAMY 54bd6cd402 use more optimized check and avoid exception throwing 2021-09-11 22:41:35 +02:00
NEZNAMY 9374b56ec7 fix method not working correctly after recode 2021-09-11 22:39:36 +02:00
NEZNAMY f6a3ea79ef use Bukkit.getTPS() if possible 2021-09-11 19:25:23 +02:00
NEZNAMY 840e2610c5 remove unused field 2021-09-08 13:44:04 +02:00
NEZNAMY d673dbf1cc fix memory leak in layouts 2021-09-07 23:27:18 +02:00
NEZNAMY 26c5de3122 include layout name in fixed slot property name to fix clash 2021-09-07 22:59:55 +02:00
NEZNAMY 7c5d2647c8 fix NPE 2021-09-07 21:49:17 +02:00
NEZNAMY 3a6256179c code cleanup with shorter load alternative 2021-09-07 19:59:39 +02:00
NEZNAMY 1d4e5fbd70 share Yaml instance across configuration files 2021-09-07 19:24:32 +02:00
NEZNAMY a456fffe45 placeholder classes no longer need to be abstract 2021-09-07 18:55:12 +02:00
NEZNAMY 3240924b2c aligned playerlist class now extends playerlist 2021-09-07 18:20:09 +02:00
NEZNAMY 670406991c match _OTHER_ being renamed to _DEFAULT_ 2021-09-07 14:56:55 +02:00
NEZNAMY 839543bbdd fix memory leak 2021-09-07 01:09:45 +02:00
NEZNAMY 47511b33a3 remove placeholder refresh interval check 2021-09-07 01:09:38 +02:00
NEZNAMY 264fd0b3a4 merge methods 2021-09-06 20:41:25 +02:00
NEZNAMY f10af90c14 remove redundant check 2021-09-06 20:34:08 +02:00
NEZNAMY 782a82ea30 use essentials directly instead of reflection 2021-09-06 20:05:25 +02:00
NEZNAMY bc0d6bb09e drop AFK+ support since it has papi support 2021-09-06 19:39:44 +02:00
NEZNAMY 54fd9d9492 rethrow InterruptedException 2021-09-06 16:15:21 +02:00
NEZNAMY 59f804c96a replace lambdas with method references 2021-09-06 16:12:51 +02:00
NEZNAMY fba1325abe remove forgotten debug message 2021-09-06 16:06:53 +02:00
NEZNAMY 4b634ad67a add support for multiple layouts with conditions 2021-09-06 16:02:17 +02:00
NEZNAMY 3990ba055a use first color in case of 1 character gradient instead of middle color 2021-09-06 15:33:40 +02:00
NEZNAMY 48784a3d7a fix random NPE which should never be thrown 2021-09-06 15:09:24 +02:00
NEZNAMY 61e87718da avoid NPE caused by invalid data sent 2021-09-06 15:02:49 +02:00
NEZNAMY a55dd34eda initialize world on proxy to prevent NPE 2021-09-06 13:20:35 +02:00
NEZNAMY fc304e5dc7 fix string comparison 2021-09-06 11:26:13 +02:00
NEZNAMY 3870950e29 avoid duplicating code 2021-09-06 01:21:54 +02:00
NEZNAMY fc97830d22 change abstract class to interface and save as array to save memory when iterating 2021-09-06 00:45:35 +02:00
NEZNAMY c7579c259b cache property names 2021-09-06 00:19:52 +02:00
NEZNAMY 1272e09a73 fix sync placeholders registering non-sync version if they didn't parse 2021-09-05 20:19:10 +02:00
NEZNAMY 79b4cbe7f1 fix gradient if text is only 1 character long 2021-09-05 17:26:44 +02:00
NEZNAMY 9a000f7881 fix startup if injection is not enabled 2021-09-05 17:16:28 +02:00
NEZNAMY 30367ad328 fix tps placeholder in default configs 2021-09-05 17:12:15 +02:00
NEZNAMY d67b447895 include plugin message packets in packet count 2021-09-05 16:28:42 +02:00
NEZNAMY 0d9c727dde remove separate measurement of component conversion methods 2021-09-05 16:26:37 +02:00
NEZNAMY 321a56d5cf add override check to onQuit as well 2021-09-05 13:36:20 +02:00
NEZNAMY fbbc4ee864 change display name of cpu value 2021-09-05 00:21:03 +02:00
NEZNAMY 36f6e792db only refresh belowname in same world (and server) 2021-09-05 00:11:30 +02:00
NEZNAMY f71c7c5076 show N/A for %world% on proxy if bridge is missing 2021-09-04 23:49:16 +02:00
NEZNAMY 33ec5a5cce remove internal: prefix from vanish placeholder since literal output is not used directly and add it on bukkit as well 2021-09-04 23:43:16 +02:00
NEZNAMY bbcf0add3f don't deserialize bytebufs if no features use it 2021-09-04 23:40:02 +02:00
NEZNAMY 80aa041d1c fix desync between my workspace and github (2/2) 2021-09-04 20:27:33 +02:00
NEZNAMY 35617e97a5 fix desync between my workspace and github (1/2) 2021-09-04 20:26:07 +02:00
NEZNAMY 9a802c0db9 fix vanished player removal 2021-09-04 20:24:32 +02:00
NEZNAMY d588f2fdee new config example equal to purpur's tpsbar 2021-09-04 13:10:26 +02:00
NEZNAMY ad0424175d partially redocument api package 2021-09-02 21:35:35 +02:00
NEZNAMY 3bf9856c26 fix nearby players registration 2021-09-01 23:35:24 +02:00
NEZNAMY 2395ee05f9 save cached placeholder array in Placeholder type 2021-08-31 20:33:10 +02:00
NEZNAMY 2a5168e800 add API methods used by addon 2021-08-31 15:32:20 +02:00
NEZNAMY da861cc73c sorting by name is no longer forced and is configurable 2021-08-29 11:35:32 +02:00
NEZNAMY 4cd974cb0e ignore empty collections 2021-08-29 11:23:27 +02:00
NEZNAMY 14cb32fc58 don't start task if no permission plugin is found 2021-08-29 11:08:15 +02:00
NEZNAMY 3197671950 use placeholder refresh core to refresh team names instead of repeating task 2021-08-29 11:07:22 +02:00
NEZNAMY cd29baf9cc fix sync placeholders from v3 placeholder loading recode 2021-08-28 22:41:29 +02:00
NEZNAMY 03ca76e679 add config option to disable latency updating 2021-08-28 22:21:05 +02:00
NEZNAMY 933855baac add override check to all methods to not have cpu output spammed with 0s 2021-08-28 22:15:54 +02:00
NEZNAMY ee61259114 rework placeholder registration methods 2021-08-28 18:06:42 +02:00
NEZNAMY d26f88e0f1 add check which should not be necessary 2021-08-28 17:24:23 +02:00
NEZNAMY c8fc144b8a replace field with local variable 2021-08-28 17:07:49 +02:00
NEZNAMY d8ae647140 again 2021-08-28 16:59:01 +02:00
NEZNAMY ab5767bee8 move some methods around 2021-08-28 16:49:07 +02:00
NEZNAMY 7c63d3c176 nah 2021-08-28 16:27:50 +02:00
NEZNAMY d837dfdd77 remove duplication 2021-08-28 16:10:50 +02:00
NEZNAMY 31612a7cb1 refer to EnumChatFormat class for colorizing and color char 2021-08-28 16:04:26 +02:00
NEZNAMY 3d25ec32c0 create and use platform-specific config file 2021-08-28 15:06:03 +02:00
NEZNAMY e3cda07f0f fix NPE during startup 2021-08-28 14:54:11 +02:00
NEZNAMY 18762961e1 count cpu usage of LP event listener 2021-08-28 14:22:18 +02:00
NEZNAMY 9cc1112a3e use event listener for LP group refreshing instead of repeating task 2021-08-28 11:22:08 +02:00
NEZNAMY 2204a8437f remove method that is no longer used 2021-08-28 11:21:26 +02:00
NEZNAMY c37e0d2fab avoid NPE 2021-08-28 11:03:28 +02:00
NEZNAMY 4ce85692a7 fix method from recode 2021-08-28 11:00:43 +02:00
NEZNAMY 860658f367 move PermissionPlugin instance to GroupRefresher class 2021-08-27 21:29:49 +02:00
NEZNAMY 4310ce95ea increase refresh interval 2021-08-27 18:28:37 +02:00
NEZNAMY 66ae6b2a33 hook into LD directly instead of using reflection 2021-08-27 18:17:00 +02:00
NEZNAMY 5f45a38f08 save nearby players into array 2021-08-27 18:03:44 +02:00
NEZNAMY c26cd30dfd fix component cache between legacy and modern versions and cache raw strings for bungeecord as well 2021-08-27 16:32:24 +02:00
NEZNAMY 4b0fe94f34 handle 1.9 bossbar packet using VV API instead of directt packets 2021-08-27 15:52:15 +02:00
NEZNAMY 7fc80f8e10 fix bossbar load/unload on <1.9 2021-08-27 15:51:23 +02:00
NEZNAMY 2875676308 update URL 2021-08-27 14:50:17 +02:00
NEZNAMY 814726d545 fix startup on fabric 2021-08-27 13:18:28 +02:00
NEZNAMY 0ae60a0463 Update PipelineInjector.java 2021-08-27 12:33:16 +02:00
NEZNAMY c96bef9ac5 remove remove-strings array instead of list 2021-08-25 22:11:26 +02:00
NEZNAMY db9fd9e4d5 cache variables for %afk% placeholder 2021-08-25 21:55:12 +02:00
NEZNAMY 90ab2f0dbd remove redundant catch 2021-08-25 17:05:57 +02:00
NEZNAMY f8f6cb3cc2 simplify 2021-08-25 17:04:37 +02:00
NEZNAMY 72d741f795 move constructors 2021-08-25 16:56:29 +02:00
NEZNAMY e784f4bcf0 create constants instead of copying strings 2021-08-25 13:58:54 +02:00
NEZNAMY a50f34d2b4 merge calls 2021-08-25 01:22:11 +02:00
NEZNAMY dce58a7793 increase quit delay 2021-08-24 23:11:15 +02:00
NEZNAMY 5c9de8de7c fix placeholders only called through expansion not refreshing 2021-08-24 23:11:06 +02:00
NEZNAMY c1c2ceb33e no longer needed 2021-08-24 23:10:13 +02:00
NEZNAMY b39eca0e0e call placeholder directly since it's possible now 2021-08-24 23:07:53 +02:00
NEZNAMY cadcc69eef rename field 2021-08-24 18:55:18 +02:00
NEZNAMY 120f2b2d44 save bukkit bossbar style formats instead of replacing 2021-08-24 16:07:35 +02:00
NEZNAMY 495d7ecf19 save Formatter instance instead of creating new one every time 2021-08-24 15:47:38 +02:00
NEZNAMY 140a45a7cb cache enabled plugin booleans 2021-08-24 12:59:38 +02:00
NEZNAMY bd12ff73f8 cache created components to reduce memory allocations and speed up code 2021-08-23 18:33:24 +02:00
NEZNAMY 7b4182dce3 add floodgate hook to use numbered scoreboard for bedrock users 2021-08-23 17:36:45 +02:00
NEZNAMY f8098423a3 add header/footer API 2021-08-23 17:11:01 +02:00
NEZNAMY 9e1a8c29ac remove redundant .toString() call 2021-08-22 21:59:58 +02:00
NEZNAMY 157833d806 prevent NPE 2021-08-22 21:58:34 +02:00
NEZNAMY 91a61eb014 fix sorting not updating in layout 2021-08-22 18:29:39 +02:00
NEZNAMY 1f037dbda7 cache used placeholder keyset 2021-08-22 17:43:52 +02:00
NEZNAMY d9c68e7360 remove redundant check 2021-08-22 16:51:12 +02:00
NEZNAMY 51507d3905 use correct description 2021-08-22 16:50:34 +02:00
NEZNAMY 31e83ebbb5 use feature subcategories in sent packets in /tab cpu 2021-08-22 16:21:40 +02:00
NEZNAMY 3e2f1fb5a8 make layout display condition checking placeholder based instead of refreshing 2021-08-22 14:00:59 +02:00
NEZNAMY 5ad360eaf2 make bossbar display condition checking placeholder based instead of refreshing 2021-08-22 13:30:15 +02:00
NEZNAMY b7b8cd3fea make scoreboard display condition checking placeholder based instead of refreshing 2021-08-22 13:27:28 +02:00
NEZNAMY 243fccac9e make vanish status refreshing for global playerlist placeholder based 2021-08-22 13:07:01 +02:00
NEZNAMY 51b3035434 fix check 2021-08-21 22:10:54 +02:00
NEZNAMY be9fba23ac fix PLACEHOLDER sorting type requiring lowercase values 2021-08-21 19:00:36 +02:00
NEZNAMY 0ac9b703d5 remove redundant call 2021-08-21 17:40:02 +02:00
NEZNAMY 21c51ff074 remove debug message 2021-08-21 17:39:43 +02:00
NEZNAMY a735b2f0b0 split subfeatures for better cpu tracking 2021-08-21 17:31:56 +02:00
NEZNAMY 0baea2c5ea add remaining players text to layout 2021-08-21 17:14:53 +02:00
NEZNAMY ca2463567e bring fix from v2 2021-08-21 14:12:50 +02:00
NEZNAMY c950dc5f53 improve debug and fix sorting type name 2021-08-20 22:08:08 +02:00
NEZNAMY 5c6a29f2d7 colorize and use | instead of space for same priority 2021-08-20 22:07:33 +02:00
NEZNAMY 6e12a9d22e bring fix from v2 2021-08-20 16:51:13 +02:00
NEZNAMY df819853ef cache sorted players in layout 2021-08-20 10:56:12 +02:00
NEZNAMY d8c3fb4190 how did this get here 2021-08-20 09:55:28 +02:00
NEZNAMY 25e5ecfe61 disable belowname by default 2021-08-20 01:33:41 +02:00
NEZNAMY 809b5bbe18 cleaner check and return server version if hook failed 2021-08-19 14:54:48 +02:00
NEZNAMY 1ec9139307 remove one of 2 old methods 2021-08-18 23:13:21 +02:00
NEZNAMY 293ea1f6cf using strings instead of UsageType enum 2021-08-18 22:55:05 +02:00
NEZNAMY ed43a47ad7 added comment 2021-08-18 21:44:49 +02:00
NEZNAMY 82980639c8 drastically optimize unlimited nametags 2021-08-18 19:33:20 +02:00
NEZNAMY 01dd493475 fix inaccessible constructor 2021-08-17 20:39:33 +02:00
NEZNAMY 0b29c8c51b create and call method instead of copypasting 2021-08-17 19:35:34 +02:00
NEZNAMY 7c2f4277c3 small nms loading method changes 2021-08-17 19:31:03 +02:00
NEZNAMY 8c515f542c define all variables manually instead of using maps 2021-08-17 19:11:45 +02:00
NEZNAMY 73d80b136f fix NPE when disabled worlds/servers are not defined 2021-08-16 23:37:13 +02:00
NEZNAMY 93c5cf70a0 fix method name 2021-08-16 15:33:18 +02:00
NEZNAMY e2a098c3ff remove debug code 2021-08-16 15:32:13 +02:00
NEZNAMY c766048224 add fabric support via CardBoard 2021-08-16 13:45:06 +02:00
NEZNAMY 9eb87fae62 return methods by other parameters than name itself
let's see how many hotfixes will this require
2021-08-15 23:32:37 +02:00
NEZNAMY 7f2f4d8e3b easier way 2021-08-15 21:26:52 +02:00
NEZNAMY ce5f9c0f08 use existing field 2021-08-15 20:27:11 +02:00
NEZNAMY cf443ed217 create method instead of copypasting content 2021-08-15 20:25:17 +02:00
NEZNAMY bde582d8ff rename fields 2021-08-15 20:17:33 +02:00
NEZNAMY 0a00332580 implement /tab scoreboard show <name> [player] 2021-08-15 16:17:08 +02:00
NEZNAMY 137d7bf240 use scoreboard name in property names to avoid issues 2021-08-15 15:56:21 +02:00
NEZNAMY 302c7ef455 properly register and unregister lines when using via API 2021-08-15 15:50:34 +02:00
NEZNAMY 87b54a44c0 remove unused field 2021-08-15 15:29:52 +02:00
NEZNAMY f9eee0de93 improve tabcomplete 2021-08-15 15:18:22 +02:00
NEZNAMY 1114d2d30d register sorting placeholders for refreshing 2021-08-15 13:51:09 +02:00
NEZNAMY 65d50d046c mighty replace function 2021-08-14 12:03:57 +02:00
NEZNAMY b2ef957682 implement all data watcher registry values 2021-08-14 12:03:47 +02:00
NEZNAMY 56be23e304 specify placeholder in debug message 2021-08-14 00:03:27 +02:00
NEZNAMY 215869037b rename artifact 2021-08-13 23:54:28 +02:00
NEZNAMY f5d4581911 add and use custom packet classes for entity packets 2021-08-13 23:30:29 +02:00
NEZNAMY 5848efdf67 rename interface 2021-08-13 22:31:04 +02:00
NEZNAMY c79277afaf add &r after every sorting element 2021-08-13 21:59:42 +02:00
NEZNAMY 59c8e1ae1c increase access level 2021-08-12 20:10:21 +02:00
NEZNAMY d50678649a fix async event call 2021-08-12 15:28:32 +02:00
NEZNAMY c19f440094 add getter 2021-08-12 15:28:23 +02:00
NEZNAMY b60160f2b9 rename field 2021-08-12 13:33:37 +02:00
NEZNAMY e54c4ed435 use method reference instead 2021-08-12 13:32:47 +02:00
NEZNAMY 749774cd03 remove redundant throws 2021-08-12 13:31:13 +02:00
NEZNAMY 7cc609fdc3 remove wrong IF 2021-08-12 13:29:51 +02:00
NEZNAMY 2cc8bed203 apparently fix locale issue 2021-08-12 13:24:04 +02:00
NEZNAMY 175f02a1c3 fix forgotten change 2021-08-12 01:53:13 +02:00
NEZNAMY 8a8ac0ccde use default group name instead of null 2021-08-12 01:47:27 +02:00
NEZNAMY 168427f24e avoid code duplicates in pipeline injection 2021-08-12 01:13:36 +02:00
NEZNAMY 8338518405 armor stand API test 2021-08-12 00:49:24 +02:00
NEZNAMY 95783b7ff3 add, rename and repackage events 2021-08-12 00:14:34 +02:00
NEZNAMY f7a4f956d7 correctly update latency in global playerlist 2021-08-11 14:24:06 +02:00
NEZNAMY feea4d4785 not anymore 2021-08-11 13:00:42 +02:00
NEZNAMY e267623025 remove duplicated check 2021-08-11 12:59:57 +02:00
NEZNAMY 5c22583a52 correctly show arrays in output 2021-08-11 12:57:02 +02:00
NEZNAMY 7ba93c9742 rework scoreboard assign logic (simplify for users) 2021-08-11 12:53:05 +02:00
NEZNAMY b4b40bf82f remove unused parameter 2021-08-11 12:19:58 +02:00
NEZNAMY b96218f305 catch NoClassDefFoundError 2021-08-11 00:12:23 +02:00
NEZNAMY e4013a616f finish scoreboard line change API 2021-08-11 00:12:12 +02:00
NEZNAMY 6f3ab8f974 oops 2021-08-10 23:31:44 +02:00
NEZNAMY c47fc61b73 catch IllegalArgument 2021-08-10 23:27:09 +02:00
NEZNAMY 01042bbc54 api changes and stuff [buffering] 2021-08-10 20:53:55 +02:00
NEZNAMY e75f8b75c5 add catserver support 2021-08-09 00:10:15 +02:00
NEZNAMY ae5e77925a shorter code alternative 2021-08-08 23:33:26 +02:00
NEZNAMY b1f2a0e057 do not send bossbars if condition is not met 2021-08-08 22:13:38 +02:00
NEZNAMY 6f61d5aa11 drop direct per-world bossbar support (still doable with conditions) 2021-08-08 22:10:11 +02:00
NEZNAMY 9562f06fea remove warn 2021-08-08 21:49:17 +02:00
NEZNAMY c6eaf4ae03 do not show warning with default group 2021-08-08 20:47:19 +02:00
NEZNAMY 24c994dfb5 properly clone extra components 2021-08-07 19:16:55 +02:00
NEZNAMY f623e5d004 hexcode variable no longer uses # as prefix 2021-08-07 17:20:49 +02:00
NEZNAMY 9ac03a00d8 apply gradients in animations once instead of every refresh 2021-08-07 14:37:29 +02:00
NEZNAMY 52b819a1b7 use same feature name everywhere 2021-08-06 23:37:29 +02:00
NEZNAMY 3ad32e0fc7 iterating over arrays instead of lists where possible 2021-08-06 13:01:21 +02:00
NEZNAMY 18c4a55518 only initialize if used 2021-08-06 12:11:28 +02:00
NEZNAMY 0d8a889556 return if no rgb codes are used 2021-08-06 12:11:10 +02:00
NEZNAMY 25f180a297 change return type of nested placeholders to String[] 2021-08-06 12:01:29 +02:00
NEZNAMY ae2f2d8294 create string once instead of every refresh 2021-08-06 11:33:22 +02:00
NEZNAMY d3ac95d1f6 change return type of getOnlinePlayers to TabPlayer[] 2021-08-06 11:08:02 +02:00
NEZNAMY a138c4a1c7 significantly optimize PropertyImpl#update() method in specific cases 2021-08-06 01:31:57 +02:00
NEZNAMY 0f359e84d6 do not call parseFloat if not needed 2021-08-06 01:27:16 +02:00
NEZNAMY 49d73b7d4f simplify 2021-08-06 00:24:11 +02:00
NEZNAMY 33dc7b82ea do not warn about null group 2021-08-03 18:51:08 +02:00
NEZNAMY 4714ea6037 add back required checks until thread management code 2021-08-03 18:45:24 +02:00
NEZNAMY c2e5f241b0 give thread pool a custom name 2021-08-03 17:49:18 +02:00
NEZNAMY 7f0e299b74 getting my try/catch back 2021-08-03 17:06:43 +02:00
NEZNAMY e418ccf8e0 using StringBuilder 2021-08-03 16:54:32 +02:00
NEZNAMY 53e119c0ce only create a single instance of nms Scoreboard 2021-08-03 15:54:02 +02:00
NEZNAMY f934d3b7b1 display placeholderapi errors when debug is enabled 2021-08-03 15:53:21 +02:00
NEZNAMY 12d5b9f6f6 fix papi placeholder error causing last value to not apply 2021-08-03 14:05:48 +02:00
NEZNAMY 727a5cfbf5 remove unnecessary casts and calls 2021-08-03 13:40:26 +02:00
NEZNAMY 6345080769 initialize server placeholders on load and move task 2021-08-03 13:34:56 +02:00
NEZNAMY 928f3d32cd fix sorting by predefined placeholder 2021-08-03 13:08:35 +02:00
NEZNAMY 81fd2dc82f do not mass allocate memory (might break addon loading) 2021-08-03 01:50:37 +02:00
NEZNAMY 225918ac52 how did this even happen 2021-08-03 01:39:40 +02:00
NEZNAMY 796343bc5e cleanup and remove duplicated code 2021-08-03 01:39:00 +02:00
NEZNAMY cdb86f6c11 fix placeholder registration in anonymous conditions 2021-08-03 01:38:34 +02:00
NEZNAMY 625e26f01f change placeholder type to fix nested player placeholders 2021-08-03 01:05:54 +02:00
NEZNAMY 21f0429fd6 return type changes 2021-08-03 01:01:57 +02:00
NEZNAMY e7a30048cf replace Map with byte[] for better performance and memory 2021-08-02 23:04:44 +02:00
NEZNAMY ed952e19eb hopefully small optimizations with stringbuilder 2021-08-02 22:19:41 +02:00
NEZNAMY e4a7bdd0eb disable by default 2021-08-02 22:16:40 +02:00
NEZNAMY 13e394bbfe use arrays instead of lists 2021-08-02 21:40:05 +02:00
NEZNAMY a6b95064d9 optimize method's memory allocation 2021-08-02 21:33:17 +02:00
NEZNAMY c30a556bdc obviously update method names 2021-08-02 20:44:17 +02:00
NEZNAMY 2bebba740e fix NPE when player is not loaded 2021-08-02 20:26:33 +02:00
NEZNAMY 57dfb02689 fix false negative when nested placeholder changed value
also nested placeholders in conditions not being registered
2021-08-02 00:01:37 +02:00
NEZNAMY 7931d8b26e reformat 2021-08-01 14:50:43 +02:00
NEZNAMY 434d50b2d1 add skin support to layout 2021-08-01 14:44:05 +02:00
NEZNAMY fad905a426 simplify method 2021-08-01 01:01:55 +02:00
NEZNAMY 475c3b690b fix NPE when skin is null 2021-08-01 00:53:42 +02:00
NEZNAMY 88eae3cb9a fix NPE when placeholder returns null 2021-08-01 00:49:04 +02:00
NEZNAMY 0021c7233c fix placeholders used only in conditions not refreshing 2021-07-31 20:11:46 +02:00
NEZNAMY 725224b6c7 move method 2021-07-31 16:44:22 +02:00
NEZNAMY 28f399079d remove redundant check 2021-07-31 16:33:50 +02:00
NEZNAMY 3e0d594e29 remove unused code 2021-07-31 16:33:08 +02:00
NEZNAMY 9092b1f9b0 remove unused method 2021-07-31 16:21:10 +02:00
NEZNAMY 4ac30ff7b2 remove animation file conversion 2021-07-31 16:20:27 +02:00
NEZNAMY 803d3395d6 split method 2021-07-31 16:11:10 +02:00
NEZNAMY 51288231cd add displayname refreshing & aligned suffix support in layout 2021-07-31 15:25:09 +02:00
NEZNAMY a44cd528ef better YellowNumber integration with layout 2021-07-31 15:13:09 +02:00
NEZNAMY cfbe0b031e add way to not duplicate properties in layout 2021-07-31 14:57:34 +02:00
NEZNAMY bf7fb1620e use function that doesn't throw patern exception 2021-07-31 14:41:22 +02:00
NEZNAMY 50056fd301 implement backwards hoverable conversion 2021-07-30 22:23:15 +02:00
NEZNAMY 927b134996 move class to correct package 2021-07-29 23:35:40 +02:00
NEZNAMY 9d66619cda removed unnecessary cast 2021-07-29 23:25:39 +02:00
NEZNAMY c9670536cc fix conditions loading 2021-07-29 23:21:30 +02:00
NEZNAMY 731518a4fc implement chat hoverable conversion 2021-07-29 22:54:18 +02:00
NEZNAMY 764df316a7 fix startup 2021-07-29 16:29:13 +02:00
NEZNAMY 1ecfdafbe8 small fixes 2021-07-29 16:20:05 +02:00
NEZNAMY 4b09aeefd6 . 2021-07-29 16:11:09 +02:00
NEZNAMY 71e407c3a5 split IChatBaseComponent class 2021-07-29 15:14:30 +02:00
NEZNAMY 48c4e7432d . 2021-07-29 12:33:37 +02:00
NEZNAMY 202194c16f fix github compilation 2021-07-28 23:54:08 +02:00
NEZNAMY 0af5713483 more stuff 2021-07-28 23:51:08 +02:00
NEZNAMY 3b6a5c353c massively reduced memory allocations 2021-07-27 23:42:04 +02:00
NEZNAMY e6d8f34db0 more random things for code analysis websites 2021-07-26 16:42:50 +02:00
NEZNAMY ef97a0d184 . 2021-07-26 16:04:17 +02:00
NEZNAMY 40866754d1 . 2021-07-26 15:01:29 +02:00
NEZNAMY d5fb7d094c more random changes 2021-07-26 14:35:47 +02:00
NEZNAMY 48b861054c temporarily disable code 2021-07-26 13:07:04 +02:00
NEZNAMY 568b7541a4 random stuff 2021-07-26 13:05:19 +02:00
NEZNAMY 914a6e6a57 Update build.yml 2021-07-26 11:58:26 +02:00
NEZNAMY d1e737dc96 Update plugin.yml 2021-07-26 11:51:16 +02:00
NEZNAMY ae68a05f87 cpu boost and rip child groups 2021-07-26 02:11:27 +02:00
NEZNAMY 79e6f3ef1c further progress 2021-07-25 17:31:56 +02:00
NEZNAMY 5f137f4055 more api stuff 2021-07-24 23:31:14 +02:00
NEZNAMY 4f5215a312 more recoding and per-world support on bungee 2021-07-23 23:51:38 +02:00
NEZNAMY 06ea8f6cb1 initial mysql support 2021-07-15 21:54:03 +02:00
NEZNAMY 2e2890d8d3 config recode and more 2021-07-13 01:11:25 +02:00
NEZNAMY a07ef6c273 API & feature recode part 1 2021-07-12 00:11:01 +02:00
NEZNAMY a02acc9c67 remove file 2021-07-11 15:55:28 +02:00
NEZNAMY bc5e61b04b make conditional placeholders refresh intervals configurable 2021-07-11 15:43:41 +02:00
NEZNAMY 665036189d always show sync placeholders red 2021-07-11 15:34:36 +02:00
NEZNAMY 8fe72e7f2e remove cputest subcommand 2021-07-11 15:21:36 +02:00
NEZNAMY 4a373015de send different message when reload fails due to internal error 2021-07-11 15:17:56 +02:00
NEZNAMY 31ad540286 do not allow same bossbar announced multiple times at once 2021-07-11 15:07:01 +02:00
NEZNAMY 448faebfad ignore players who are not loaded
will fix double bossbar bug
2021-07-11 15:02:22 +02:00
NEZNAMY 3b7f25071e remove spigot link 2021-07-11 00:46:51 +02:00
NEZNAMY c661395bb0 Update README.md 2021-07-10 13:25:11 +02:00
NEZNAMY c231220b42 2.9.2 2021-07-10 13:01:29 +02:00
NEZNAMY 1c6e5bec73 fix IllegalArgument 2021-07-10 12:57:16 +02:00
NEZNAMY 8919aaad94 add missing config option 2021-07-09 16:42:10 +02:00
NEZNAMY ff6a2fe734 equals 2021-07-09 11:58:18 +02:00
NEZNAMY 5ca4f7e411 2.9.2-pre3 2021-07-07 17:13:01 +02:00
NEZNAMY 2c105718b0 1.17.1 support 2021-07-07 17:10:37 +02:00
NEZNAMY 9cc471f66f catch throwable in pipeline 2021-07-06 21:20:47 +02:00
NEZNAMY e18867c938 do not ignore Errors 2021-07-06 21:01:46 +02:00
NEZNAMY 27bd942c4c fix NoSuchFieldError on <1.11 2021-07-06 21:01:36 +02:00
NEZNAMY 234ca72e73 tab out stack traces 2021-07-06 21:01:17 +02:00
NEZNAMY f35a09a34d avoid rare NPE 2021-07-06 19:54:19 +02:00
NEZNAMY fa6d06a4ac 2.9.2-pre2 2021-07-06 09:50:48 +02:00
NEZNAMY ec6daeeadb colorize text immediately instead of in every refresh 2021-07-04 13:50:05 +02:00
NEZNAMY f24f25f071 apparently this method is required 2021-07-04 12:05:10 +02:00
NEZNAMY dbf0e3af9f small cpu and memory optimization in pet fix feature 2021-07-04 00:02:56 +02:00
NEZNAMY 6ecb607c0b add private constructor 2021-07-03 20:48:18 +02:00
NEZNAMY 1bf6b00be0 remove unnecessary code 2021-07-03 20:47:56 +02:00
NEZNAMY 4b4f52e39a use constants instead of literal strings 2021-07-03 20:35:50 +02:00
NEZNAMY 1170efbe02 cache disabled worlds 2021-07-03 19:52:42 +02:00
NEZNAMY 3e86e73fed refactor to avoid duplication 2021-07-03 16:51:49 +02:00
NEZNAMY dd43861572 cache methods for placeholders (mostly %afk%) 2021-07-03 16:32:37 +02:00
NEZNAMY 61a19ca9e0 Merge branch 'master' of https://github.com/NEZNAMY/TAB 2021-07-03 16:19:20 +02:00
NEZNAMY d02af31e7c Merge pull request #342 from etil2jz/patch-1
Update README.md
2021-07-03 16:16:38 +02:00
Arthur B ab7b88b67b Update README.md
Correct isPremium line
2021-07-03 16:13:52 +02:00
NEZNAMY b80c816c5a relocate json-simple 2021-07-01 18:56:51 +02:00
NEZNAMY c0ad6f49e7 minor changes 2021-07-01 18:53:24 +02:00
NEZNAMY 91a56a8c2c remove IllegalArgument throws forwarding 2021-07-01 12:09:09 +02:00
NEZNAMY 135a473dc5 more abstraction to remove duplications 2021-07-01 11:14:41 +02:00
NEZNAMY a8b53b07e4 increase delay and repeat times 2021-07-01 10:04:19 +02:00
NEZNAMY 171cbd4497 NPE fix when plugin is disabled and user does not have reload permission 2021-06-30 21:24:27 +02:00
NEZNAMY a1383612bc making code analysis websites happy part 6
+ switching to bukkit metrics shading instead of copying classes
2021-06-30 18:03:21 +02:00
NEZNAMY fe798c19f3 making code analysis websites happy part 5 2021-06-30 13:32:15 +02:00
NEZNAMY ead3add4cc making code analysis websites happy part 4 2021-06-30 11:54:14 +02:00
NEZNAMY db13c2d1c5 making code analysis websites happy part 3 2021-06-30 10:58:39 +02:00
NEZNAMY f2daab4b80 making code analysis websites happy part 2 2021-06-30 00:55:26 +02:00
NEZNAMY 6fd02c83ab attempt 2 2021-06-30 00:02:02 +02:00
NEZNAMY c288a0503a test 2021-06-29 23:54:12 +02:00
NEZNAMY 2e2b65a4bb making code analysis websites happy part 1 2021-06-29 23:48:23 +02:00
NEZNAMY 982d0a53f9 correctly set bossbar progress on add 2021-06-29 19:01:46 +02:00
NEZNAMY f89ecfb595 remove unused options 2021-06-29 14:10:42 +02:00
NEZNAMY bddb96a5fa increase default refresh 2021-06-29 14:05:57 +02:00
NEZNAMY 39b29d12e4 problem solved ez game ez life
referring to expansion download errors while jar file was modified such as https://paste.gg/p/anonymous/449c3eb326f34015993b4025002be355
2021-06-29 13:59:47 +02:00
NEZNAMY 6cb1e2c06d debug option is now public 2021-06-29 13:49:46 +02:00
NEZNAMY d932a9a862 add VV as softdepend to avoid troll console message 2021-06-29 13:29:19 +02:00
NEZNAMY 341b552d0b 2.9.2-pre1 2021-06-25 08:25:25 +02:00
NEZNAMY 1586bd9768 implement correct interface 2021-06-24 21:55:06 +02:00
NEZNAMY e8dde3a756 reuse the same instance 2021-06-24 21:51:37 +02:00
NEZNAMY bb591bf56d spigot fixed the bug 2021-06-24 20:18:07 +02:00
NEZNAMY 8cf83b276a fix the feature on 1.17 2021-06-23 21:59:24 +02:00
NEZNAMY a1547a7288 cleaner implementation of #322 2021-06-23 21:56:10 +02:00
NEZNAMY 0722403a23 remove duplicated line 2021-06-22 21:27:59 +02:00
NEZNAMY cd4a91d975 return afk if at least 1 plugin says player is afk 2021-06-22 20:42:26 +02:00
NEZNAMY c7870b4e9d fix NPE in API when feature is not enabled 2021-06-21 22:52:59 +02:00
NEZNAMY 239dae5a65 change reference type to player name 2021-06-21 22:43:47 +02:00
NEZNAMY 13c89d18d7 remove unused field since 1.17 support 2021-06-21 21:47:18 +02:00
NEZNAMY c5dc42eafe cleanup 2021-06-21 14:47:56 +02:00
NEZNAMY 59b3faab1e fix team name note message in console 2021-06-21 13:41:15 +02:00
NEZNAMY b88beb5002 added null check to placeholder registration 2021-06-21 12:58:46 +02:00
NEZNAMY 9fea35c25d retry viaversion call if it returned -1 2021-06-21 12:03:33 +02:00
NEZNAMY 372013bcc6 add online status into debug message 2021-06-21 11:07:21 +02:00
NEZNAMY 20ca58b570 fix NPE 2021-06-20 21:49:48 +02:00
NEZNAMY 9c4cca20fb just an attempt 2021-06-19 11:43:40 +02:00
NEZNAMY 6b8536a86e fix possible memory leak? 2021-06-19 11:41:46 +02:00
NEZNAMY 3b41857637 fixed NPE caused by misconfiguration 2021-06-19 09:27:33 +02:00
NEZNAMY fa78ac2157 fix it again? 2021-06-18 13:39:05 +02:00
NEZNAMY 0a0bb9c83c swap order to avoid NPE when player is not loaded 2021-06-18 12:28:19 +02:00
NEZNAMY 36834a039e 2.9.1 2021-06-17 18:43:34 +02:00
NEZNAMY 4960c898bb memory leak? 2021-06-17 18:35:35 +02:00
NEZNAMY af61edbc5c added replacements support to relational placeholders 2021-06-17 15:53:24 +02:00
NEZNAMY 237bfc08a1 forward raw packets instead, no idea why was it not working 2021-06-17 15:52:39 +02:00
NEZNAMY 032e9a089d bump supported versions 2021-06-17 12:50:37 +02:00
NEZNAMY ba83779dde create and use new field getter method 2021-06-16 21:51:51 +02:00
NEZNAMY 267d72f844 spacing 2021-06-16 21:38:24 +02:00
NEZNAMY b533cdb89f send deserialized packets instead of malformed bytebufs 2021-06-16 17:26:05 +02:00
NEZNAMY 3f118ac76b add option to define custom character widths 2021-06-16 16:24:08 +02:00
NEZNAMY 08a8f0097c fix wrong constructor taken on random 1.8.8 forks 2021-06-16 16:23:26 +02:00
NEZNAMY c7a3599e46 update maven repository 2021-06-16 14:22:45 +02:00
NEZNAMY 62f80baa69 version bump 2021-06-16 14:01:31 +02:00
NEZNAMY 09dc8cd437 version bump 2021-06-16 13:52:27 +02:00
NEZNAMY c613ba401b remove unnecessary this. 2021-06-16 13:03:52 +02:00
NEZNAMY 866df0b5cf remove duplicate content 2021-06-16 11:12:43 +02:00
NEZNAMY 8f2b56ba05 2.9.0 2021-06-16 10:09:20 +02:00
NEZNAMY 2049885f11 more accurate error message 2021-06-16 09:56:15 +02:00
NEZNAMY 4caef337d5 ANOTHER BOSSBAR API BUG IN ANOTHER PLATFORM HAHA LOL 2021-06-15 23:37:02 +02:00
NEZNAMY a644792bf6 simplify 2021-06-15 22:50:16 +02:00
NEZNAMY 54c7f8fc6a drop the rest of title packet 2021-06-15 22:49:23 +02:00
NEZNAMY 2e59b87bbe use getters instead of fields 2021-06-15 22:46:42 +02:00
NEZNAMY f89242ad8f add and use magic code Boolean getters 2021-06-15 22:40:02 +02:00
NEZNAMY 845903788c remove unused code 2021-06-15 22:39:32 +02:00
NEZNAMY 53a9047c20 fix conflict between hidden-by-default and remember-toggle-choice 2021-06-15 22:36:55 +02:00
NEZNAMY a2b74bbc30 correctly display used color codes in parse error messages 2021-06-15 22:36:31 +02:00
NEZNAMY 50ef93cc45 fix stack overflow and stretch with relational placeholders 2021-06-15 22:36:00 +02:00
NEZNAMY e2a5da9c14 deserialize other scoreboard packets as well 2021-06-15 22:35:24 +02:00
NEZNAMY bf31116d0d split method 2021-06-15 22:34:42 +02:00
NEZNAMY d79fa8c4f3 drop title packet 2021-06-15 22:34:31 +02:00
NEZNAMY 87e0a7bea3 remove unused fields 2021-06-15 22:33:33 +02:00
NEZNAMY b34cabd55c optimize check 2021-06-15 22:32:50 +02:00
NEZNAMY 704bd36c77 do not try to use rgb on <1.16 servers 2021-06-14 09:35:23 +02:00
NEZNAMY 5c2c4d0f4b improved error message 2021-06-14 08:43:36 +02:00
NEZNAMY 80cca5cb34 fix #329 2021-06-14 08:22:37 +02:00
NEZNAMY dcd603f2f5 null check to prevent errors 2021-06-13 22:10:30 +02:00
NEZNAMY 1bee3b49bf sending bossbar using bukkit api 2021-06-13 20:46:16 +02:00
NEZNAMY 11bcccb8f9 fix reload from previous commit 2021-06-13 20:24:39 +02:00
NEZNAMY 7425493706 initialization cleanup 2021-06-13 19:09:34 +02:00
NEZNAMY dca0cfd424 removed old value from config 2021-06-13 17:09:03 +02:00
NEZNAMY 21314def89 fix #328 2021-06-13 15:57:06 +02:00
NEZNAMY 90e544d279 option to take groups from backend servers 2021-06-13 11:54:03 +02:00
NEZNAMY 89e21558a1 2.8.11-pre19 2021-06-12 23:23:15 +02:00
NEZNAMY b28cc51457 spigot one dot god damn seventeen 2021-06-12 23:19:09 +02:00
NEZNAMY 2d0a203b5f increased initial delay 2021-06-12 14:28:44 +02:00
NEZNAMY 2948666c1d 2.8.11-pre18 2021-06-11 19:14:47 +02:00
NEZNAMY b2a2659546 added little comment 2021-06-11 17:14:03 +02:00
NEZNAMY e2eb7102c9 removed unnecessary 'throws' from methods 2021-06-10 21:22:15 +02:00
NEZNAMY 56301e653b splitting method into multiple 2021-06-10 21:13:40 +02:00
NEZNAMY 1d825e08d2 using correct uuid all the time 2021-06-10 19:38:46 +02:00
NEZNAMY c81a27709c 1.17 bungeecord 2021-06-10 17:22:58 +02:00
NEZNAMY 2b143172f8 spacing 2021-06-10 17:19:55 +02:00
NEZNAMY 84330ec6eb Merge branch 'master' of https://github.com/NEZNAMY/TAB 2021-06-10 17:19:25 +02:00
NEZNAMY 0bd703de7f Merge pull request #325 from Camotoy/viaversion4.0.0
Update to ViaVersion 4.0.0
2021-06-10 17:17:55 +02:00
Camotoy e6a55b7d5c Change packet ID if using 1.17 2021-06-10 11:13:45 -04:00
Camotoy b6ec7631d2 Update to ViaVersion 4.0.0
Tested on 1.17 and the bossbar showed up with no error in console.
2021-06-10 10:53:36 -04:00
NEZNAMY 5abbd00d63 fixed unloading when entering disabled world 2021-06-10 11:22:07 +02:00
NEZNAMY 515c94976e removed internal methods from TabPlayer API interface 2021-06-09 21:06:01 +02:00
NEZNAMY 912adad8f6 player 2021-06-09 20:08:36 +02:00
NEZNAMY 70fdd193a3 Merge branch 'master' of https://github.com/NEZNAMY/TAB 2021-06-09 19:43:08 +02:00
NEZNAMY 9d83e968fc Merge pull request #323 from Score2/bukkit-permission
Support to obtain bukkit permissions from bungee.
2021-06-09 19:42:35 +02:00
83669 04329da133 resolve. 2021-06-10 01:41:32 +08:00
83669 19ccfbb1a6 Merge branch 'master' of https://github.com/NEZNAMY/TAB into bukkit-permission
 Conflicts:
	velocity-1.1.0/src/main/resources/velocityconfig.yml
2021-06-10 01:29:02 +08:00
83669 c53ab09abc Support to obtain bukkit permissions from bungee. 2021-06-10 01:24:23 +08:00
NEZNAMY a4d8daac1d fixed wrong logic causing name formatting to not work 2021-06-09 16:12:33 +02:00
NEZNAMY 99d566d521 wrong action order 2021-06-09 16:05:08 +02:00
NEZNAMY aa37f73161 fixed wrong config option name 2021-06-09 15:54:12 +02:00
NEZNAMY 087518378d pom.xml cleanup 2021-06-09 15:39:57 +02:00
NEZNAMY 913d27929b shortcut and no longer requiring guava 2021-06-09 15:24:04 +02:00
NEZNAMY 530d39bec5 added property name into exception message 2021-06-09 10:47:42 +02:00
NEZNAMY cf70dc3845 fixed priorities (caused <= and >= to not work) 2021-06-08 23:17:31 +02:00
NEZNAMY d1421fee3f new colors 2021-06-08 21:58:18 +02:00
NEZNAMY 3ec490b36e only the the API now 2021-06-08 09:58:46 +02:00
NEZNAMY ee42685179 Added API to disable team handling of a player 2021-06-07 13:31:44 +02:00
NEZNAMY e02d687771 PingSpoof and SpectatorFix now properly load/unload 2021-06-06 14:55:47 +02:00
NEZNAMY dddb592253 update to default config comments 2021-06-05 20:22:20 +02:00
NEZNAMY d0ad88d317 fixed potential security issue when player is not loaded due to an error 2021-06-05 20:20:02 +02:00
NEZNAMY 3d3ce0151f added gamemode getter to TabPlayer 2021-06-05 19:56:37 +02:00
NEZNAMY f017b0e562 %canseeonline% now uses vanish detection from previous commits instead of PV API on bungeecord 2021-06-05 19:47:03 +02:00
NEZNAMY 4ba2bb669b added back 1.5 and 1.6 support 2021-06-05 16:26:32 +02:00
NEZNAMY 9fc2424736 Create FUNDING.yml 2021-06-03 16:55:26 +02:00
NEZNAMY 980c01ea70 this never happened 2021-06-01 13:25:01 +02:00
NEZNAMY 758edcaf5c fixed NPE in API usage 2021-05-30 20:48:49 +02:00
NEZNAMY 950f825e31 added unnecessary softdependency due to md5's troll console message 2021-05-30 20:47:48 +02:00
NEZNAMY 0a985f5c78 using method from component to save color codes due to limits 2021-05-28 11:43:17 +02:00
NEZNAMY 58353f4e6d wrong variable 2021-05-28 11:41:22 +02:00
NEZNAMY c3d2b5c4b0 fixed error in initialization 2021-05-28 11:19:45 +02:00
NEZNAMY c2764b4b8a removed redundant ; 2021-05-28 11:19:31 +02:00
NEZNAMY 9bc8ad0d23 typo 2021-05-28 09:47:02 +02:00
NEZNAMY 488c3540a8 using more reliable check 2021-05-27 19:58:17 +02:00
NEZNAMY 1d03950a64 removed technically useless check 2021-05-27 19:51:21 +02:00
NEZNAMY e24ea7df2e added null check, continuation of previous commit 2021-05-27 18:06:09 +02:00
NEZNAMY fe5e3d6405 better compatibility with forks that use "Unknown" server version
by using a minor version check which is more reliable
2021-05-27 16:20:08 +02:00
NEZNAMY db8584e40b correctly translating colors 2021-05-27 16:18:43 +02:00
NEZNAMY 2e4db38d1a properly compensating for the bug on all horse types 2021-05-25 14:31:44 +02:00
NEZNAMY f82470c1b1 2.8.11-pre17 2021-05-24 22:37:10 +02:00
NEZNAMY 650cc93fc0 fixed placeholders not refreshing when updating properties with API 2021-05-24 22:35:02 +02:00
NEZNAMY e61070307a fixed rare NPE 2021-05-23 23:27:56 +02:00
NEZNAMY 2fa46867e5 moved repeating task to separate method 2021-05-23 18:51:39 +02:00
NEZNAMY 636b2e760a fixed wrong check 2021-05-23 18:46:10 +02:00
NEZNAMY 8cecf46310 NPE fix 2021-05-23 00:38:16 +02:00
NEZNAMY a7bcda7eba fixed NPEs when running commands from console 2021-05-22 20:48:09 +02:00
NEZNAMY a610dd2c70 cleanup 2021-05-22 16:49:30 +02:00
NEZNAMY df98c77a48 java 8 shortcut 2021-05-22 16:48:01 +02:00
NEZNAMY 331dc33c86 removed redundant method 2021-05-22 16:46:56 +02:00
NEZNAMY 8493b37171 recoded feature to fix issues, worked 2021-05-22 16:41:56 +02:00
NEZNAMY 2449c46165 using default locale
https://support-system.xyz/redirect?link=https://cdn.discordapp.com/attachments/690574378454483034/845273706287988807/ticket-844852135032127489.html
2021-05-21 14:16:55 +02:00
NEZNAMY a642c2d344 moved code to new method to avoid duplication 2021-05-20 16:59:48 +02:00
NEZNAMY 88c7b988e7 not displaying the error message anymore 2021-05-19 20:40:07 +02:00
NEZNAMY 36651260c6 added debug messages 2021-05-19 18:10:54 +02:00
NEZNAMY 6c0072dc54 using new method (also supports essentials vanish now) 2021-05-18 21:12:54 +02:00
NEZNAMY e38f5a77c0 added support for bukkit vanish plugins into global playerlist via bridge 2021-05-18 21:11:41 +02:00
NEZNAMY 6443926a79 added a reminder since even I forgot 2021-05-18 19:55:36 +02:00
NEZNAMY 489deb9ee6 2.8.11-pre16 2021-05-16 22:06:22 +02:00
NEZNAMY a2039110e0 improved compatibility with vanish plugins 2021-05-16 22:01:25 +02:00
NEZNAMY f1666b64ee moved shared module to top to avoid compilation error on first compilation 2021-05-16 21:11:45 +02:00
NEZNAMY d7e419c88b added getters to bossbar interface 2021-05-16 21:10:01 +02:00
NEZNAMY de8f8053be recalculating more often, seems to have fixed the issue 2021-05-16 20:56:15 +02:00
NEZNAMY 7aadef5c21 resending packet with a delay when anti-override is disabled 2021-05-16 20:55:26 +02:00
NEZNAMY f8384dfbdf removed character ID from widths for lower file size & counting them internally while loading 2021-05-16 20:52:38 +02:00
NEZNAMY b91cbf827c removed redundant check 2021-05-16 20:51:46 +02:00
NEZNAMY 096619d9f7 moved teleport event back to packets to avoid various issues 2021-05-16 13:00:28 +02:00
NEZNAMY 7b8006406c should fix rare issue caused by multi-thread access 2021-05-16 12:58:48 +02:00
NEZNAMY 90483d549a removed width command & loading since the file is now complete 2021-05-15 21:26:16 +02:00
NEZNAMY 5473055c1c found a way to measure & added arabic characters 2021-05-15 21:23:41 +02:00
NEZNAMY f3b082b8e1 removed unnecessary cast 2021-05-15 19:57:04 +02:00
NEZNAMY 52fe99a080 fixed stack overflow on sync placeholders 2021-05-15 13:33:57 +02:00
NEZNAMY 68b1e941d1 correctly formatting tablist name in packets sent on world change 2021-05-13 18:51:15 +02:00
NEZNAMY 109fce9b1a updated line number reference 2021-05-13 18:50:45 +02:00
NEZNAMY 014d73dd3f ignoring info packet on <1.8 clients so nametag feature can display prefixes 2021-05-13 18:50:08 +02:00
NEZNAMY ad82744e91 added configuration simplification console message 2021-05-09 16:12:41 +02:00
NEZNAMY 638f66ade4 added catch for ArrayIndexOutOfBoundsException 2021-05-09 16:11:22 +02:00
NEZNAMY c190efa7c4 removed config conversion
users had enough time to update to 2.8.10 which converts everything, only keeping 2.8.10 ->2.9.0 changes
2021-05-09 12:35:17 +02:00
NEZNAMY b071eb3366 added purpur afk api support for %afk% 2021-05-08 18:03:57 +02:00
NEZNAMY a7c7a86a90 removed feature interface not used by the main plugin 2021-05-08 17:18:57 +02:00
NEZNAMY 0c21519cf6 listening to respawn event directly in features instead of globally and being unused for most servers 2021-05-08 00:45:33 +02:00
NEZNAMY d7f805b26e goodbye 2021-05-07 21:14:11 +02:00
NEZNAMY 4f702feab3 random feature request in my private messages 2021-05-07 20:24:52 +02:00
NEZNAMY 46175ceb1f fixed error on that platform made by a group of friendly and amazing people 2021-05-07 20:24:07 +02:00
NEZNAMY c206860736 removed redundant code 2021-05-02 22:20:09 +02:00
NEZNAMY b97c222490 remove modify-npc-names config option
all NPC plugins offer configuration of NPC names, modification can be performed by competent server owners there instead
2021-05-02 17:32:38 +02:00
NEZNAMY 53ad5e3cec added debug messages 2021-05-02 13:15:04 +02:00
NEZNAMY e67ce8dbf4 possible issue fix 2021-05-01 23:39:58 +02:00
NEZNAMY ac661be5c4 manually adding yes/no keys to replacements to compensate for snakeyaml conversion 2021-05-01 22:23:26 +02:00
NEZNAMY ab4e386491 small visual code update, functionality remains same 2021-05-01 22:11:32 +02:00
NEZNAMY aa125b535e Update README.md 2021-05-01 00:49:46 +02:00
NEZNAMY 29df3bb5e2 version bump 2021-04-30 15:36:14 +02:00
NEZNAMY 80ee30a532 map must be linked, found a way to do both synchronized and linked 2021-04-28 20:47:08 +02:00
NEZNAMY a20b1bcd89 added hidden config option to disable pipeline injection 2021-04-28 10:33:39 +02:00
NEZNAMY 4269abd2ca 2.8.11-pre15 2021-04-27 20:51:35 +02:00
NEZNAMY a73397065c added fix for rare NPE due to multi-thread access 2021-04-27 20:47:58 +02:00
NEZNAMY 5805a6c5a3 fixed rare concurrent modification 2021-04-27 17:43:30 +02:00
NEZNAMY e813077c92 check is no longer in constructor, must be added elsewhere 2021-04-27 17:38:27 +02:00
NEZNAMY b1ae68e8c2 not spamming class initializations and getting field values directly 2021-04-26 14:45:52 +02:00
NEZNAMY b6162b2d4a not refreshing header/footer on world switch if values did not change 2021-04-26 14:07:45 +02:00
NEZNAMY 0da7854f7f using concurrent hashmap to not need to copy value collection each time it's iterated 2021-04-26 14:00:41 +02:00
NEZNAMY a073747e66 added comment 2021-04-26 13:25:00 +02:00
NEZNAMY 0975e31371 better instance check 2021-04-26 13:23:25 +02:00
NEZNAMY a1231f1708 anti-override was removed already 2021-04-26 09:14:41 +02:00
NEZNAMY 3581da0fe7 only running toString once instead of every loop 2021-04-26 08:43:51 +02:00
NEZNAMY 531810e633 remake using switch 2021-04-25 13:53:16 +02:00
NEZNAMY 36a1db78e2 separate method to reduce complexity 2021-04-25 13:50:50 +02:00
NEZNAMY 0e58009ced starting tasks in separate methods 2021-04-25 13:48:18 +02:00
NEZNAMY ecdcc6894b fixed wrong cpu calculation 2021-04-25 00:16:19 +02:00
NEZNAMY 677a2f9396 reduced memory allocations 2021-04-25 00:14:53 +02:00
NEZNAMY b14f30d4d1 using isInstance instead of equals for better performance 2021-04-23 20:30:17 +02:00
NEZNAMY 4396df55ae updated dependency 2021-04-22 22:07:00 +02:00
NEZNAMY de6ce93a31 partially reverted pre6 recode + fixed disabled worlds not working
also deleted SneakEventListener class and replaced it with direct event lisener
2021-04-22 16:31:01 +02:00
NEZNAMY b449b7cdfc fixed errors on <1.16 2021-04-22 14:52:15 +02:00
NEZNAMY de4412fcff 2.8.11-pre14 2021-04-21 18:02:09 +02:00
NEZNAMY 8e9b34125d added placeholder value printing into team name note in debug 2021-04-21 17:45:57 +02:00
NEZNAMY 024b3175fa updated link 2021-04-20 19:48:33 +02:00
NEZNAMY 9fadc6df3b removed links 2021-04-20 19:47:48 +02:00
NEZNAMY f51f8f0f2d updated info 2021-04-20 15:51:48 +02:00
NEZNAMY d805df4887 no longer required 2021-04-20 15:50:41 +02:00
NEZNAMY d161c6c074 no need for reflection since jar is manual
also fixed title packet
2021-04-20 15:40:24 +02:00
NEZNAMY 6603c9e682 removed redundant file 2021-04-20 15:23:58 +02:00
NEZNAMY 157360c26c added dependency exclusions 2021-04-20 14:11:03 +02:00
NEZNAMY e16199b360 defined encoding to avoid warn in compilation 2021-04-20 11:58:13 +02:00
NEZNAMY df42424970 more cleanup 2021-04-20 11:42:30 +02:00
NEZNAMY 22ce6ce75e more cleanup 2021-04-20 11:36:55 +02:00
NEZNAMY e8dde142d2 another savestate before I break something 2021-04-20 11:25:05 +02:00
NEZNAMY 44fe272ce5 making another savestate of a working project 2021-04-20 11:23:41 +02:00
NEZNAMY 23a8f32910 pom.xml cleanup and resource fix 2021-04-20 11:12:04 +02:00
NEZNAMY d523c0408e Merge pull request #300 from A248/fix-modularization
Fix modularization
2021-04-20 01:51:37 +02:00
A248 0c2edba316 Add all resources and delete target folders 2021-04-19 19:49:47 -04:00
A248 7cfc643522 Add more to .gitignore 2021-04-19 19:42:32 -04:00
A248 98b446efd2 Shade all the modules into single jar + Fix filename of velocity 2
Changed velocity/2.0.0/libs/Velocity 2.0.0jar to Velocity-2.0.0.jar
2021-04-19 19:40:24 -04:00
NEZNAMY bbf9aaed64 initial modulatization 2021-04-20 01:11:57 +02:00
NEZNAMY 13d36457af repackage 2021-04-19 15:12:39 +02:00
NEZNAMY 4f850b0f2e it's shutdown 2021-04-18 21:45:42 +02:00
NEZNAMY 7118e0d9d3 fixed magic code error in gradients due to recent gradient apply changes 2021-04-18 20:59:35 +02:00
NEZNAMY 900edef407 fixed NPE when player is not loaded 2021-04-18 15:13:33 +02:00
NEZNAMY a7e4b99ce6 2.8.11-pre13 2021-04-18 12:27:12 +02:00
NEZNAMY 0463667270 Update README.md 2021-04-16 21:03:23 +02:00
NEZNAMY d179bc20ae now with link 2021-04-16 20:07:31 +02:00
NEZNAMY bc658a9223 Update README.md 2021-04-16 20:03:30 +02:00
NEZNAMY e32e3baf3a added anti-smartass message 2021-04-16 14:52:57 +02:00
NEZNAMY 4436f4cf42 new sorting type 2021-04-15 01:28:15 +02:00
NEZNAMY 1dc7b40ee9 found a workaround, works fine 2021-04-15 00:36:34 +02:00
NEZNAMY fb2221d281 removed unnecessary local variables 2021-04-15 00:36:09 +02:00
NEZNAMY b5a295970b correctly moving to the bottom even when more than 9 groups are defined 2021-04-15 00:02:38 +02:00
NEZNAMY 485a453b27 added misconfiguration check 2021-04-14 19:36:39 +02:00
NEZNAMY 03d9ba9579 removed debug message 2021-04-14 19:29:08 +02:00
NEZNAMY ead7adea31 increased delay because requested 2021-04-14 19:28:17 +02:00
NEZNAMY 9793fdfc06 added debug messages 2021-04-14 19:27:50 +02:00
NEZNAMY 60b73e5c0d fixed NPE when modifier is null 2021-04-13 17:37:01 +02:00
NEZNAMY ed374c83d1 moving to API methods where possible 2021-04-13 15:24:56 +02:00
NEZNAMY f53828e01a no longer needed after updating setBossbarVisible method 2021-04-13 14:04:55 +02:00
NEZNAMY 91ab50fa6a removed unused method 2021-04-13 13:22:24 +02:00
NEZNAMY bee0d9d086 fixed issue from previous commits 2021-04-13 01:36:15 +02:00
NEZNAMY b38f09f118 moved symbol into constructor 2021-04-13 01:17:30 +02:00
NEZNAMY 65f57e8bf1 wrote the method from scratch for better performance & memory 2021-04-13 01:13:02 +02:00
NEZNAMY e424e42e05 matching change made to TextColor constructor 2021-04-13 00:48:11 +02:00
NEZNAMY a22cd5338d initializing value only once instead of every time it's used 2021-04-13 00:35:54 +02:00
NEZNAMY f921737d1c converting color object instead of calling fromString(.toString()) 2021-04-13 00:28:37 +02:00
NEZNAMY 2f760afc70 the constructor expects # 2021-04-13 00:06:59 +02:00
NEZNAMY 4ce56433f9 fowarding StringBuilder 2021-04-12 16:57:22 +02:00
NEZNAMY f8ace5fbb5 merged ifs 2021-04-12 16:51:26 +02:00
NEZNAMY f89778e969 not initializing map when unused 2021-04-12 16:35:56 +02:00
NEZNAMY 99f74d3824 using String.valueOf for less allocations 2021-04-12 16:28:13 +02:00
NEZNAMY dec9c42edc shorter alternative 2021-04-12 16:05:06 +02:00
NEZNAMY 34365c13cb calling int method directly if possible for better performance & memory 2021-04-12 15:20:39 +02:00
NEZNAMY 8a4c780fb1 parsing gradients only once instead of every refresh 2021-04-12 14:39:53 +02:00
NEZNAMY bed49408da only checking plugin presence on startup 2021-04-12 13:12:24 +02:00
NEZNAMY 5dd400bdc5 only initializing once 2021-04-12 13:01:04 +02:00
NEZNAMY 07d5a03a95 using AtomicInteger to avoid internal Integer.valueOf(int) call 2021-04-12 12:44:19 +02:00
NEZNAMY d53e7665d7 only initializing hexcodes once instead of every time 2021-04-12 12:17:33 +02:00
NEZNAMY 4021d7cbac fix from previous commit 2021-04-12 12:16:44 +02:00
NEZNAMY 2634ca5f28 not initializing list if not needed 2021-04-11 23:24:02 +02:00
NEZNAMY aa887fe27b 2.8.11-pre12 2021-04-10 21:39:40 +02:00
NEZNAMY c9077e1254 removed header/footer anti-override entirely
it was rather useless and very resource intensive
2021-04-10 20:22:42 +02:00
NEZNAMY fcf5636d9a small optimization with StringBuilder and String.format 2021-04-10 20:16:33 +02:00
NEZNAMY 1c4713ef1a not initializing maps when not needed 2021-04-10 18:13:15 +02:00
NEZNAMY d48da82f55 removed unnecessary local variable 2021-04-10 18:12:54 +02:00
NEZNAMY 7128ab26d8 using AtomicLong to prevent Long.valueOf(long) spamming allocations 2021-04-10 15:31:05 +02:00
NEZNAMY 58155041d1 loading placeholder usage map only once (per hard refresh) instead of every loop 2021-04-10 15:05:49 +02:00
NEZNAMY e96453eac9 optimized check 2021-04-09 22:22:37 +02:00
NEZNAMY a1d98c54ad why is it /btab not /vtab? now it's both 2021-04-09 21:35:15 +02:00
NEZNAMY fd423481cb small memory optimization using StringBuilder 2021-04-09 20:14:00 +02:00
NEZNAMY 48da7d0c2e added cpu measuring of some methods 2021-04-09 17:49:03 +02:00
NEZNAMY 949577fb07 properly using color field to prevent white text in next line 2021-04-09 17:48:09 +02:00
NEZNAMY dc876efff8 changed placeholder display to top 5 2021-04-09 16:35:55 +02:00
NEZNAMY c39b650e9b found a way to keep code in the same thread without double cpu measuring 2021-04-09 15:56:22 +02:00
NEZNAMY 12c1cb871d various minor memory optimizations 2021-04-09 15:39:57 +02:00
NEZNAMY c75e86812d created Component convert methods for faster code & less memory allocations 2021-04-09 13:56:25 +02:00
NEZNAMY cc1fffbe8b missing changes from previous commit 2021-04-09 13:27:19 +02:00
NEZNAMY e6313a5e52 showing correct threshold 2021-04-09 01:25:08 +02:00
NEZNAMY 2a278dcff9 added custom line properties support to commands 2021-04-09 01:16:47 +02:00
NEZNAMY 8539529061 updated line numbers 2021-04-09 00:00:16 +02:00
NEZNAMY 5a4b7d93c0 reduced display threshold 2021-04-08 16:01:07 +02:00
NEZNAMY 5e459effc0 fixed &# RGB format issue from previous commits 2021-04-08 14:24:17 +02:00
NEZNAMY 5f0cf2ecb5 Update TAB.java 2021-04-08 01:04:40 +02:00
NEZNAMY 44c133a68c added requested method 2021-04-07 23:19:39 +02:00
NEZNAMY f842f15cd4 wrong color symbol 2021-04-07 11:17:47 +02:00
NEZNAMY 04c78a37d7 various random small memory and cpu improvements 2021-04-06 21:33:01 +02:00
NEZNAMY cba4dbdf84 2.8.11-pre11 2021-04-05 20:40:55 +02:00
NEZNAMY 2fbb162bbf fixed NPE when joining into disabled world with aligned tabsuffix enabled 2021-04-05 20:36:16 +02:00
NEZNAMY a1be962997 disabled by default 2021-04-05 20:34:04 +02:00
NEZNAMY a3c3f5d990 reverted broken commit 2021-04-05 19:20:55 +02:00
NEZNAMY c785d4fdca fixed #282 2021-04-05 16:21:33 +02:00
NEZNAMY 6b78707bd8 not overriding other plugins with delayed scoreboard 2021-04-05 00:23:57 +02:00
NEZNAMY a1565ed481 2.8.11-pre10 2021-04-04 15:09:19 +02:00
NEZNAMY ae056b312f put 0.5 for characters that wide and added some missing values 2021-04-04 13:39:52 +02:00
NEZNAMY b20c1158b0 allow decimal values (0.5) 2021-04-04 13:39:26 +02:00
NEZNAMY 210f567b74 added debug messages to loading widths 2021-04-04 13:12:09 +02:00
NEZNAMY 82b91c7bd9 added empty lines for missing chars 2021-04-04 12:55:21 +02:00
NEZNAMY 5168a99c3b Merge branch 'master' of https://github.com/NEZNAMY/TAB 2021-04-04 12:49:55 +02:00
NEZNAMY e437917841 added permission required to use tabcomplete #290 2021-04-04 12:49:47 +02:00
MrGraycat 6543440926 added 55001-60000
added 55001-60000
2021-04-04 09:03:14 +02:00
NEZNAMY 30c53c6048 fixed disabling in worlds not really working 2021-04-04 01:32:42 +02:00
NEZNAMY 87412eb4ff another attempt to avoid concurrent modification 2021-04-04 00:24:43 +02:00
NEZNAMY f1ad5fc57d restructure, cleanup 2021-04-03 22:50:37 +02:00
NEZNAMY dd3a457ec0 fixed tablist entries not getting shorter after maxPlayer quits 2021-04-03 22:50:14 +02:00
NEZNAMY 069f2aba8b updated info 2021-04-03 21:40:29 +02:00
NEZNAMY 9e19553150 added option to disable unlimited nametags in worlds 2021-04-03 17:26:24 +02:00
NEZNAMY 2d7b009442 no longer refreshing if value did not change 2021-04-03 16:42:59 +02:00
NEZNAMY 68817e3595 post-recode fix 2021-04-03 16:42:36 +02:00
NEZNAMY 3e229d6b82 do not refresh unused placeholders 2021-04-03 12:15:29 +02:00
NEZNAMY 5fce471577 fixed empty packets being sent causing white names with anti-override disabled 2021-04-01 22:58:55 +02:00
NEZNAMY 68b1e7cb16 nametag classes refactor, NameTag is base class which NameTagX extends if enabled
also made invisible-nametags public
2021-04-01 22:15:18 +02:00
NEZNAMY 761e02ff6e fixed unsupported operation from previous commit 2021-04-01 16:59:08 +02:00
NEZNAMY 5fe4408631 using in-built java function instead of google one 2021-04-01 16:05:27 +02:00
NEZNAMY bae0685ac1 added check for team name length 2021-04-01 11:32:31 +02:00
NEZNAMY 6322a0c045 fixed concurrent modification 2021-04-01 11:32:07 +02:00
NEZNAMY 0b89de905e added null check 2021-03-31 21:05:32 +02:00
NEZNAMY 49c4453678 removed unnecessary full path 2021-03-31 08:25:49 +02:00
NEZNAMY c056cafda6 fixed error when left side of condition was empty 2021-03-30 22:02:40 +02:00
NEZNAMY b375c24340 added API methods to force team name 2021-03-30 15:16:26 +02:00
NEZNAMY 5a76131f24 setBossbarVisible method now performs all actions 2021-03-30 15:12:27 +02:00
NEZNAMY 764769a6ca fixed startup error caused by misconfiguration 2021-03-30 11:20:02 +02:00
NEZNAMY b0226df3ab updated comments 2021-03-29 22:39:25 +02:00
NEZNAMY 8c86120b33 removed unused method 2021-03-29 22:01:58 +02:00
556 changed files with 95961 additions and 83813 deletions

No files matched your search

+7
View File
@@ -0,0 +1,7 @@
* text=auto
*.sh text eol=lf
gradlew text eol=lf
*.bat text eol=crlf
*.jar binary
-28
View File
@@ -1,28 +0,0 @@
---
name: Bug report
about: Report a bug
title: ''
labels: ''
assignees: ''
---
**Server version**
**Plugin version** ("latest" is not a version)
**Describe the bug**
**How to reproduce**
**Expected behavior**
**Actual behavior**
**Additional info** (errors, screenshots, ...)
+63
View File
@@ -0,0 +1,63 @@
name: Bug Report
description: Plugin does not work as described.
labels: ["Type: Bug"]
body:
- type: input
attributes:
label: Server version
description: Version and type of used server software where TAB is installed.
placeholder: Spigot 1.18.1
validations:
required: true
- type: input
attributes:
label: TAB version
description: Full version in numbers, "latest" is not a version.
placeholder: 3.0.2
validations:
required: true
- type: textarea
attributes:
label: Describe the bug
description: How the plugin behaves
validations:
required: true
- type: textarea
attributes:
label: Expected behavior
description: How the plugin is supposed to behave instead with your configuration.
validations:
required: true
- type: textarea
attributes:
label: Steps to reproduce
description: What to do in order to reproduce this issue
placeholder: |
Step 1: ..
Step 2: ..
validations:
required: true
- type: textarea
attributes:
label: Additional info
description: Anything else you want to provide that will help in resolving the issue faster, such as screenshots or videos.
validations:
required: false
- type: checkboxes
attributes:
label: Checklist
description: Let's make sure this report is valid
options:
- label: I am running latest version of the plugin
required: true
- label: I have read the wiki to make sure it's not an issue with configuration
required: true
- label: I ticked all of the boxes without actually reading them
required: false
- label: I have read the Compatibility wiki page and am not trying to run the plugin on an unsupported server version / platform
required: true
+57
View File
@@ -0,0 +1,57 @@
name: Error
description: Error message with a stack trace in console or error file.
labels: ["Type: Error"]
body:
- type: input
attributes:
label: Server version
description: Version and type of used server software where TAB is installed.
placeholder: Spigot 1.18.1
validations:
required: true
- type: input
attributes:
label: TAB version
description: Full version in numbers, "latest" is not a version.
placeholder: 3.0.2
validations:
required: true
- type: textarea
attributes:
label: Stack trace
description: The error message and stack trace you received in console or errors.log file.
validations:
required: true
- type: textarea
attributes:
label: Steps to reproduce (if known)
description: What to do in order to reproduce this issue
placeholder: |
Step 1: ..
Step 2: ..
validations:
required: false
- type: textarea
attributes:
label: Additional info
description: Any other info you want to provide.
validations:
required: false
- type: checkboxes
attributes:
label: Checklist
description: Let's make sure this report is valid
options:
- label: I am running latest version of the plugin
required: true
- label: I have included a paste of the error
required: true
- label: I ticked all of the boxes without actually reading them
required: false
- label: I have read the Compatibility wiki page and am not trying to run the plugin on an unsupported server version / platform
required: true
+56
View File
@@ -0,0 +1,56 @@
name: Memory leak
description: Memory leak caused by TAB.
labels: ["Type: Memory leak"]
body:
- type: input
attributes:
label: Server version
description: Version and type of used server software where TAB is installed.
placeholder: Spigot 1.18.1
validations:
required: true
- type: input
attributes:
label: TAB version
description: Full version in numbers, "latest" is not a version.
placeholder: 3.0.2
validations:
required: true
- type: textarea
attributes:
label: Heap dump
description: Link to uploaded memory dump which I can look into.
validations:
required: true
- type: textarea
attributes:
label: Uncleared object(s)
description: Objects you believe should have been removed from the memory but are not
placeholder: |
There is only 1 player online, but heap dump has 100 instances of TabPlayer
validations:
required: false
- type: textarea
attributes:
label: Additional info
description: Any other info you want to provide.
validations:
required: false
- type: checkboxes
attributes:
label: Checklist
description: Let's make sure this report is valid
options:
- label: I am running latest version of the plugin
required: true
- label: I have included download link of my heap dump
required: true
- label: I ticked all of the boxes without actually reading them
required: false
- label: I have explained what I believe is wrong with the heap dump
required: true
@@ -0,0 +1,55 @@
name: Performance issue
description: Performance issue in TAB or in server caused by TAB
labels: ["Type: Performance"]
body:
- type: input
attributes:
label: Server version
description: Version and type of used server software where TAB is installed.
placeholder: Spigot 1.18.1
validations:
required: true
- type: input
attributes:
label: TAB version
description: Full version in numbers, "latest" is not a version.
placeholder: 3.0.2
validations:
required: true
- type: textarea
attributes:
label: Evidence
description: Any evidence proving the performance issue, such as output of /tab cpu or timings.
validations:
required: true
- type: textarea
attributes:
label: Steps to reproduce (if known)
description: What to do in order to reproduce this issue
placeholder: |
Step 1: ..
Step 2: ..
validations:
required: false
- type: textarea
attributes:
label: Additional info
description: Any other info you want to provide.
validations:
required: false
- type: checkboxes
attributes:
label: Checklist
description: Let's make sure this report is valid
options:
- label: I am running latest version of the plugin
required: true
- label: I have included sufficient evidence of the issue
required: true
- label: I ticked all of the boxes without actually reading them
required: false
+29
View File
@@ -0,0 +1,29 @@
name: Wiki change
description: Change to text on a wiki page or adding a new section.
labels: ["Type: Wiki change"]
body:
- type: input
attributes:
label: Page link
description: Link to the page that should receive the change.
placeholder: https://github.com/NEZNAMY/TAB/wiki/Installation
validations:
required: true
- type: textarea
attributes:
label: Current text (if applicable)
description: Current version of the text (if modifying), ignore in case of new section.
placeholder: |
Installation on Bukkit/Spigot/Paper is as simple as it can be. Just put the plugin into plugins folder and restart the server. You can also run `/plugman load tab` to load the plugin while server is running.
validations:
required: false
- type: textarea
attributes:
label: New text
description: What the text should be changed to / how should new section look
placeholder: |
Put the plugin into plugins folder and restart the server. In case you don't want to restart your server, loading with plugins like PlugMan is supported.
validations:
required: true
+45
View File
@@ -0,0 +1,45 @@
name: Build
on:
push:
branches:
- master
- v4
pull_request:
types: [opened, synchronize, reopened]
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3.3.0 #https://github.com/actions/checkout/releases
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: Set up JDK 17
uses: actions/setup-java@v3.9.0 #https://github.com/actions/setup-java/releases
with:
distribution: 'temurin'
java-version: 17
- name: Cache SonarCloud packages
uses: actions/cache@v3.2.3 #https://github.com/actions/cache/releases
with:
path: ~/.sonar/cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar
- name: Cache Gradle
uses: actions/cache@v3.2.3 #https://github.com/actions/cache/releases
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: "${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}"
restore-keys: |
${{ runner.os }}-gradle-
- name: Build and analyze
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
run: ./gradlew clean build
- name: Upload a Build Artifact
uses: actions/upload-artifact@v3.1.2 #https://github.com/actions/upload-artifact/releases
with:
name: Jar
path: jar/build/libs/TAB-**.jar
+10 -6
View File
@@ -1,8 +1,7 @@
# Compiled class file
*.class
/bin/
/target/
/src/test/
bin/
target/
# Log file
*.log
@@ -31,8 +30,13 @@ hs_err_pid*
.project
# intellij
/.idea/
.idea/
# other
.gitattributes
*.iml
*.iml
run/
# Gradle
.gradle/
build/
!gradle/wrapper/gradle-wrapper.jar
+9
View File
@@ -0,0 +1,9 @@
If this plugin has helped you in any way, and you would like to return something back
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.
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.
+1 -28
View File
@@ -1,4 +1,4 @@
Apache License
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
@@ -172,30 +172,3 @@ Apache License
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+21 -47
View File
@@ -1,49 +1,23 @@
## Introduction
Here it is. After countless requests to go opensource, I did it to make those people quiet. It worked.
It's already been a year and I still can't see any positives of it. This way I just made it easier for everyone to make a plugin as good, so people can stop using it and switch to something better.
## Compiling
Plugin can be compiled using maven.
# About
TAB aims to be a superior all-in-one minecraft plugin for displaying information that outperforms all
similar plugins in terms of features, performance and compatibility.
More information can be found at [Why TAB?](https://github.com/NEZNAMY/TAB/wiki/Why-TAB%3F) wiki page.
## Premium code
The source contains content of premium version as well. However, this must be activated by setting [this line to return true](https://github.com/NEZNAMY/TAB/blob/master/src/main/java/me/neznamy/tab/shared/TAB.java#L79).
## Links
Free version
    Spigot (releases): https://www.spigotmc.org/resources/57806/
    Pre-releases https://github.com/NEZNAMY/TAB/releases
Premium version
    Polymart (releases): https://polymart.org/resource/484
    MC-Market (releases): https://www.mc-market.org/resources/14009/
    Pre-releases on discord for verified buyers
Bukkit bridge https://www.spigotmc.org/resources/83966/
Wiki https://github.com/NEZNAMY/TAB/wiki
Discord invite link: https://discord.gg/EaSvdk6
## Downloads
Official release: https://www.spigotmc.org/resources/57806/
Pre-releases: https://github.com/NEZNAMY/TAB/releases
## Maven Repository
```
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
# Compiling
Compilation requires JDK 17 and up.
To compile the plugin, run `./gradlew build` from the terminal.
Once the plugin compiles, grab the jar from `/jar/build/libs/` folder.
The universal jar contains all modules for all supported platforms.
<dependencies>
<!-- TAB -->
<dependency>
<groupId>com.github.NEZNAMY</groupId>
<artifactId>TAB-API</artifactId>
<version>2.8.10</version>
</dependency>
</dependencies>
```
# Documentation
You can find everything about the plugin on the [Wiki](https://github.com/NEZNAMY/TAB/wiki). This includes a detailed description
of all features, as well as information regarding compatibility or limitations of each feature.
# Issues
The [Issues](https://github.com/NEZNAMY/TAB/issues) section is an issue tracker for all the kind of problems covered in issue templates.
Please refrain from attempting to use it to receive help with your server, such issues will be closed immediately.
When opening an issue, provide as much information as possible. The difference between a bug getting fixed in 1 week vs 1 hour
is in quality of the report. Bug reports where steps to reproduce are "idk" have no value and will not help to get the bug fixed at all.
# Contributing
See [CONTRIBUTING.md](https://github.com/NEZNAMY/TAB/blob/master/CONTRIBUTING.md)
+2
View File
@@ -0,0 +1,2 @@
# Security Policy
If you found a security issue, send me a private message anywhere.
+7
View File
@@ -0,0 +1,7 @@
dependencies {
compileOnlyApi("org.jetbrains:annotations:24.0.1")
}
tasks.javadoc {
enabled = project.hasProperty("enable-javadoc")
}
@@ -0,0 +1,135 @@
package me.neznamy.tab.api;
import java.util.UUID;
import lombok.NonNull;
import lombok.Setter;
import me.neznamy.tab.api.bossbar.BossBarManager;
import me.neznamy.tab.api.event.EventBus;
import me.neznamy.tab.api.placeholder.PlaceholderManager;
import me.neznamy.tab.api.scoreboard.ScoreboardManager;
import me.neznamy.tab.api.tablist.SortingManager;
import me.neznamy.tab.api.tablist.HeaderFooterManager;
import me.neznamy.tab.api.tablist.TabListFormatManager;
import me.neznamy.tab.api.nametag.NameTagManager;
import me.neznamy.tab.api.tablist.layout.LayoutManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* The primary API class to get instances of other API classes
*/
public abstract class TabAPI {
/** Instance of the API */
@Setter private static TabAPI instance;
/**
* Returns API instance. If instance was not set by the plugin, throws
* {@code IllegalStateException}. This is usually caused by shading the API
* into own project, which is not allowed. Another option is calling the method
* before plugin was able to load.
*
* @return API instance
* @throws IllegalStateException
* If instance is {@code null}
*/
public static @NotNull TabAPI getInstance() {
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 soft depend 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;
}
/**
* Returns player object from given UUID
*
* @param id
* Player UUID
* @return player object from given UUID
*/
public abstract @Nullable TabPlayer getPlayer(@NonNull UUID id);
/**
* Returns player object from given name
*
* @param name
* Player name
* @return player object from given name
*/
public abstract @Nullable TabPlayer getPlayer(@NonNull String name);
/**
* Returns collection of all online players. Will return empty list if plugin is disabled (due to a broken configuration file for example).
*
* @return collection of online players
*/
public abstract @NotNull TabPlayer[] getOnlinePlayers();
/**
* Return BossBar manager instance if the feature is enabled. If not, returns {@code null}.
*
* @return BossBar manager
*/
public abstract @Nullable BossBarManager getBossBarManager();
/**
* Returns scoreboard manager instance if the feature is enabled. If not, returns {@code null}.
*
* @return scoreboard manager
*/
public abstract @Nullable ScoreboardManager getScoreboardManager();
/**
* Returns team manager instance if the feature is enabled. If not, returns {@code null}.
*
* @return team manager
*/
public abstract @Nullable NameTagManager getNameTagManager();
/**
* Returns header/footer manager instance if the feature is enabled. If not, returns {@code null}.
*
* @return Header/footer manager
*/
public abstract @Nullable HeaderFooterManager getHeaderFooterManager();
/**
* Returns PlaceholderManager instance
*
* @return PlaceholderManager instance
*/
public abstract @NotNull PlaceholderManager getPlaceholderManager();
/**
* Returns TabList name format manager instance if the feature is enabled. If not, returns {@code null}.
*
* @return TabList name format manager
*/
public abstract @Nullable TabListFormatManager getTabListFormatManager();
/**
* Returns Layout manager instance if the feature is enabled. If not, returns {@code null}.
*
* @return Layout manager
*/
public abstract @Nullable LayoutManager getLayoutManager();
/**
* Returns Sorting manager instance if at least one feature capable of sorting players is enabled.
* If not, returns {@code null}.
*
* @return Sorting manager
*/
public abstract @Nullable SortingManager getSortingManager();
/**
* Gets the event bus for registering listeners for TAB events.
*
* @return the event bus
*/
public abstract @Nullable EventBus getEventBus();
}
@@ -0,0 +1,69 @@
package me.neznamy.tab.api;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.UUID;
/**
* An interface representing a player
*/
public interface TabPlayer {
/**
* Returns player's name
*
* @return Player's name
*/
@NotNull String getName();
/**
* Returns player's UUID
*
* @return Player's UUID
*/
@NotNull UUID getUniqueId();
/**
* Returns platform-specific entity
*
* @return an instance of bukkit/bungee player depending on platform
*/
@NotNull Object getPlayer();
/**
* Returns true once the player is successfully loaded (onJoin method ran through all methods)
*
* @return {@code true} if player is fully loaded, {@code false} otherwise
*/
boolean isLoaded();
/**
* Returns player's primary permission group. If group has been changed using
* {@link #setTemporaryGroup(String)}, returns that value. Otherwise, returns group
* detected by standard group assign logic
*
* @return player's primary permission group
*/
@NotNull String getGroup();
/**
* Temporarily overrides player's group and applies all changes coming from new group.
* This includes all properties and sorting, if used.
* Set to {@code null} to reset back.
*
* @param group
* New group to use
* @see #hasTemporaryGroup()
*/
void setTemporaryGroup(@Nullable String group);
/**
* Returns {@code true} if a temporary group was applied to the player using {@link #setTemporaryGroup(String)}.
* If no group was set, returns {@code false}
*
* @return {@code true} if group is set, {@code false} if not
* @see #setTemporaryGroup(String)
*/
boolean hasTemporaryGroup();
}
@@ -0,0 +1,9 @@
package me.neznamy.tab.api.bossbar;
/**
* An enum representing all available BossBar colors.
* Calling ordinal() will return color's network ID.
*/
public enum BarColor {
PINK, BLUE, RED, GREEN, YELLOW, PURPLE, WHITE
}
@@ -0,0 +1,22 @@
package me.neznamy.tab.api.bossbar;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* An enum representing all available BossBar styles.
* Calling ordinal() will return style's network ID.
* Style names are equal to NMS names.
*/
@AllArgsConstructor
public enum BarStyle {
PROGRESS("SOLID"),
NOTCHED_6("SEGMENTED_6"),
NOTCHED_10("SEGMENTED_10"),
NOTCHED_12("SEGMENTED_12"),
NOTCHED_20("SEGMENTED_20");
/** Style's name used in Bukkit API */
@Getter private final String bukkitName;
}
@@ -0,0 +1,203 @@
package me.neznamy.tab.api.bossbar;
import java.util.List;
import java.util.UUID;
import lombok.NonNull;
import me.neznamy.tab.api.TabPlayer;
import org.jetbrains.annotations.NotNull;
/**
* An interface representing a BossBar line.
* <p>
* For clients 1.8 and lower it uses wither, which only allows 1 bar
* to be displayed at a time. Entity packets are not available on BungeeCord,
* where nothing will be displayed for these players.
* <p>
* For 1.9+ it uses the new BossBar feature, allowing configurable styles
* and colors, as well as display several bars at once. Limit of maximum
* displayed BossBars depends on client resolution and GUI scale, up to
* 9 concurrent BossBars displayed at once.
*/
public interface BossBar {
/**
* Returns name of this BossBar. If it was defined in config, returns
* the name specified in config. If it was made using the API, returns
* randomly generated ID given to this BossBar when creating.
*
* @return name of BossBar
*/
@NotNull String getName();
/**
* Returns randomly generated uuid of this BossBar used internally to match
* the BossBar in client with packets or with Bukkit API BossBar instances.
*
* @return uuid of this BossBar
*/
@NotNull UUID getUniqueId();
/**
* Changes BossBar title to specified string, supporting placeholders.
* <p>
* If title contains new placeholders not used before, they are registered using
* standard registration logic and refreshed periodically. No need to call
* this method to try to keep placeholder values up to date.
* <p>
* If specified title is equal to the current one, nothing happens.
*
* @param title
* New title to display in this BossBar
*/
void setTitle(@NonNull String title);
/**
* Changes BossBar progress to specified string, supporting placeholders.
* The string must be a string version of a float value, or a placeholder that
* outputs a float value with range 0-100.
* <p>
* If progress contains new placeholders not used before, they are registered using
* standard registration logic and refreshed periodically. No need to call
* this method to try to keep placeholder values up to date.
* <p>
* If specified progress is equal to the current one, nothing happens.
*
* @param progress
* New progress to use in this BossBar
*/
void setProgress(@NonNull String progress);
/**
* Changes BossBar progress to specified value ranging from 0 to 100.
* <p>
* If specified progress is equal to the current one, nothing happens.
*
* @param progress
* New progress to use in this BossBar
*/
void setProgress(float progress);
/**
* Changes BossBar color to specified string, supporting placeholders.
* The string must be a string version of one of the supported values,
* or a placeholder that outputs one of them.
* <p>
* If color contains new placeholders not used before, they are registered using
* standard registration logic and refreshed periodically. No need to call
* this method to try to keep placeholder values up to date.
* <p>
* If specified color is equal to the current one, nothing happens.
*
* @param color
* New color to use in this BossBar
*/
void setColor(@NonNull String color);
/**
* Changes BossBar color to specified enum constant.
* <p>
* If specified color is equal to the current one, nothing happens.
*
* @param color
* New color to use in this BossBar
*/
void setColor(@NonNull BarColor color);
/**
* Changes BossBar style to specified string, supporting placeholders.
* The string must be a string version of one of the supported values,
* or a placeholder that outputs one of them.
* <p>
* If style contains new placeholders not used before, they are registered using
* standard registration logic and refreshed periodically. No need to call
* this method to try to keep placeholder values up to date.
* <p>
* If specified style is equal to the current one, nothing happens.
*
* @param style
* New style to use in this BossBar
*/
void setStyle(@NonNull String style);
/**
* Changes BossBar style to specified enum constant.
* <p>
* If specified style is equal to the current one, nothing happens.
*
* @param style
* New style to use in this BossBar
*/
void setStyle(@NonNull BarStyle style);
/**
* Returns current title of the BossBar in raw format. If it contains placeholders,
* their raw identifiers are used in the result.
*
* @return title of the BossBar
*/
@NotNull String getTitle();
/**
* Returns progress of the BossBar as a string, which is either entered string
* containing placeholders or entered number converted to string
*
* @return entered progress as a string
*/
@NotNull String getProgress();
/**
* Returns color of the BossBar as a string, which is either entered string
* containing placeholders or entered enum value converted to string
*
* @return entered color as a string
*/
@NotNull String getColor();
/**
* Returns style of the BossBar as a string, which is either entered string
* containing placeholders or entered enum value converted to string
*
* @return entered style as a string
*/
@NotNull String getStyle();
/**
* Registers this BossBar to specified player.
* <p>
* If the player already sees this BossBar, nothing happens.
*
* @param player
* Player to register this BossBar to
*/
void addPlayer(@NonNull TabPlayer player);
/**
* Unregisters this BossBar from specified player.
* <p>
* If the player does not see this BossBar, nothing happens.
*
* @param player
* Player to unregister this BossBar from
*/
void removePlayer(@NonNull TabPlayer player);
/**
* Returns list of players who can see this BossBar.
* <p>
* The returned list can only be used to read. Writing
* will not work properly. For adding/removing players see {@link #addPlayer(TabPlayer)}
* and {@link #removePlayer(TabPlayer)}.
*
* @return List of players seeing this BossBar
*/
@NotNull List<TabPlayer> getPlayers();
/**
* Returns {@code true} if this boss bar is configured as announcement-only bar,
* {@code false} if not.
*
* @return {@code true} if bar is announcement only, {@code false} if not
*/
boolean isAnnouncementBar();
}
@@ -0,0 +1,156 @@
package me.neznamy.tab.api.bossbar;
import java.util.List;
import java.util.Map;
import lombok.NonNull;
import me.neznamy.tab.api.TabAPI;
import me.neznamy.tab.api.TabPlayer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* An interface allowing work with BossBars such as creating, sending
* and toggling.
* <p>
* Instance can be obtained using {@link TabAPI#getBossBarManager()}.
* This requires the BossBar feature to be enabled in config, otherwise the method will
* return {@code null}.
*/
public interface BossBarManager {
/**
* Creates BossBar with specified parameters and registers it to BossBar manager,
* allowing to retrieve it later.
*
* @param title
* Title to display, supports placeholders
* @param progress
* Progress to use. Must be between 0 and 100
* @param color
* Color to use
* @param style
* Style to use
* @return The newly created BossBar
*/
@NotNull BossBar createBossBar(@NonNull String title, float progress, @NonNull BarColor color, @NonNull BarStyle style);
/**
* Creates BossBar with specified parameters and registers it to BossBar manager,
* allowing to retrieve it later.
*
* @param title
* Title to display, supports placeholders
* @param progress
* Progress to use. Must be a string version of a number, or
* a placeholder that returns a number
* @param color
* Color to use. Must be a string version of one of enum constants, or
* a placeholder that returns one of them
* @param style
* Style to use. Must be a string version of one of enum constants, or
* a placeholder that returns one of them
* @return The newly created BossBar
*/
@NotNull BossBar createBossBar(@NonNull String title, @NonNull String progress, @NonNull String color, @NonNull String style);
/**
* Returns registered BossBar with given name. For BossBars from config it is the name
* they were created with, for API BossBars their randomly generated name, which can be
* retrieved using {@link me.neznamy.tab.api.bossbar.BossBar#getName()}.
* Returns {@code null} if no such BossBar exists.
*
* @param name
* Name of registered BossBar
* @return BossBar with specified name
*/
@Nullable BossBar getBossBar(@NonNull String name);
/**
* Returns a map of all registered BossBars. This includes both BossBars from config
* and those registered via API.
* <p>
* Map key is BossBar's name available in {@link me.neznamy.tab.api.bossbar.BossBar#getName()},
* map value is the BossBar interface.
*
* @return all registered BossBars
*/
@NotNull Map<String, BossBar> getRegisteredBossBars();
/**
* Toggles BossBar for this player and sends toggle message if {@code sendToggleMessage} is true.
*
* @param player
* Player to toggle BossBar for
* @param sendToggleMessage
* {@code true} if toggle message should be sent, {@code false} if not
* @see #hasBossBarVisible(TabPlayer)
* @see #setBossBarVisible(TabPlayer, boolean, boolean)
*/
void toggleBossBar(@NonNull TabPlayer player, boolean sendToggleMessage);
/**
* Returns true if player can see BossBars, false if toggled via command or API.
*
* @param player
* Player to check toggle status of
* @return {@code true} if visible, {@code false} if disabled (toggled)
* @see #toggleBossBar(TabPlayer, boolean)
* @see #setBossBarVisible(TabPlayer, boolean, boolean)
*/
boolean hasBossBarVisible(@NonNull TabPlayer player);
/**
* Sets BossBar visibility of player to set value. If value did not change, nothing happens.
* If visibility changed, toggle message is sent if {@code sendToggleMessage} is {@code true}.
*
* @param player
* Player to set BossBar visibility of
* @param visible
* {@code true} if BossBar should be visible, {@code false} if not
* @param sendToggleMessage
* {@code true} if toggle message should be sent if value changed, {@code false} if not
* @see #toggleBossBar(TabPlayer, boolean)
* @see #hasBossBarVisible(TabPlayer)
*/
void setBossBarVisible(@NonNull TabPlayer player, boolean visible, boolean sendToggleMessage);
/**
* Temporarily displays registered BossBar to player for specified amount of time in milliseconds.
*
* @param player
* Player to show BossBar to
* @param bossBar
* Name of registered BossBar to show
* @param duration
* In milliseconds for how long should BossBar be displayed
* @throws IllegalArgumentException
* if no BossBar with specified name exists
* @see #announceBossBar(String, int)
* @see #getAnnouncedBossBars()
*/
void sendBossBarTemporarily(@NonNull TabPlayer player, @NonNull String bossBar, int duration);
/**
* Temporarily displays registered BossBar to all players for specified amount of time in milliseconds.
*
* @param bossBar
* Name of registered BossBar to show
* @param duration
* In milliseconds for how long should BossBar be displayed
* @throws IllegalArgumentException
* if no BossBar with specified name exists
* @see #sendBossBarTemporarily(TabPlayer, String, int)
* @see #getAnnouncedBossBars()
*/
void announceBossBar(@NonNull String bossBar, int duration);
/**
* Returns list of BossBars which are currently being announced.
*
* @return list of currently active BossBar announcements
* @see #sendBossBarTemporarily(TabPlayer, String, int)
* @see #announceBossBar(String, int)
*/
@NotNull List<BossBar> getAnnouncedBossBars();
}
@@ -0,0 +1,55 @@
package me.neznamy.tab.api.event;
import lombok.NonNull;
/**
* The event bus. This is used to register event listeners/handlers for
* handling events that may be fired by TAB.
*/
public interface EventBus {
/**
* Scans the given listener for any method that is annotated with
* {@link Subscribe} and registers it as a listener to this event bus.
*
* <p>All methods in this class that are annotated with {@link Subscribe}
* must meet the following criteria:
* <ul>
* <li>It must be <strong>public</strong>.</li>
* <li>It must <strong>not</strong> be abstract.</li>
* <li>It must have exactly <strong>one</strong> parameter.</li>
* <li>Its single parameter must be <strong>an event</strong>.</li>
* </ul>
* If a method does not meet the above criteria, an exception <strong>will</strong>
* be thrown.
*
* @param listener the listener to register
* @throws RuntimeException if a method does not meet the criteria
*/
void register(@NonNull Object listener);
/**
* Registers the given handler to this event bus.
*
* @param type the class type of the event
* @param handler the handler to register
* @param <E> the type of the event
*/
<E extends TabEvent> void register(@NonNull Class<E> type, @NonNull EventHandler<E> handler);
/**
* Scans the given listener for any method that is annotated with
* {@link Subscribe} and unregisters it from this event bus.
*
* @param listener the listener to unregister
*/
void unregister(@NonNull Object listener);
/**
* Unregisters the given handler from this event bus.
*
* @param handler the handler to unregister
* @param <E> the type of the event
*/
<E extends TabEvent> void unregister(@NonNull EventHandler<E> handler);
}
@@ -0,0 +1,18 @@
package me.neznamy.tab.api.event;
/**
* A handler for an event. This allows listening for events in a more
* functional style.
*
* @param <E> the type of event this handler handles
*/
@FunctionalInterface
public interface EventHandler<E> {
/**
* Called when the given event is fired from an event bus.
*
* @param event the event to handle
*/
void handle(E event);
}
@@ -0,0 +1,14 @@
package me.neznamy.tab.api.event;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Subscribes to a {@link TabEvent}.
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Subscribe {
}
@@ -0,0 +1,10 @@
package me.neznamy.tab.api.event;
/**
* An event that may be fired by TAB when something occurs.
*
* <p>This is a marker interface. All events <strong>must</strong> implement this
* interface.
*/
public interface TabEvent {
}
@@ -0,0 +1,26 @@
package me.neznamy.tab.api.event.player;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.api.event.TabEvent;
import org.jetbrains.annotations.NotNull;
/**
* Called when the player has been fully loaded by TAB.
*/
public interface PlayerLoadEvent extends TabEvent {
/**
* Gets the player that was loaded.
*
* @return the player that was loaded
*/
@NotNull TabPlayer getPlayer();
/**
* Returns {@code true} if player was loaded because they joined,
* {@code false} if the player was loaded because tab reload command was executed
*
* @return {@code true} if player joined, {@code false} if plugin was reloaded
*/
boolean isJoin();
}
@@ -0,0 +1,48 @@
package me.neznamy.tab.api.event.plugin;
import lombok.NonNull;
import me.neznamy.tab.api.TabPlayer;
import me.neznamy.tab.api.event.TabEvent;
import org.jetbrains.annotations.NotNull;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
/**
* Called when an unknown placeholder is about to be registered.
* It defaults to a PlaceholderAPI implementation, but can be overridden.
*/
public interface PlaceholderRegisterEvent extends TabEvent {
/**
* Returns placeholder identifier starting and ending with {@code %}
*
* @return placeholder identifier starting and ending with {@code %}
*/
@NotNull String getIdentifier();
/**
* Sets placeholder to specified server placeholder implementation.
*
* @param supplier
* Placeholder replacer
*/
void setServerPlaceholder(@NonNull Supplier<Object> supplier);
/**
* Sets placeholder to specified player placeholder implementation.
*
* @param function
* Placeholder replacer
*/
void setPlayerPlaceholder(@NonNull Function<TabPlayer, Object> function);
/**
* Sets placeholder to specified relational placeholder implementation.
*
* @param function
* Placeholder replacer
*/
void setRelationalPlaceholder(@NonNull BiFunction<TabPlayer, TabPlayer, Object> function);
}
@@ -0,0 +1,9 @@
package me.neznamy.tab.api.event.plugin;
import me.neznamy.tab.api.event.TabEvent;
/**
* Called when TAB is fully loaded.
*/
public interface TabLoadEvent extends TabEvent {
}
@@ -0,0 +1,183 @@
package me.neznamy.tab.api.nametag;
import lombok.NonNull;
import me.neznamy.tab.api.TabAPI;
import me.neznamy.tab.api.TabPlayer;
import org.jetbrains.annotations.Nullable;
/**
* Interface for manipulating player name tags.
* <p>
* Instance can be obtained using {@link TabAPI#getNameTagManager()}.
* This requires the Team feature to be enabled in config, otherwise the method will
* return {@code null}.
*/
public interface NameTagManager {
/**
* Makes player's NameTag globally invisible
*
* @param player
* player to hide name tag of
* @see #showNameTag(TabPlayer)
* @see #hasHiddenNameTag(TabPlayer)
*/
void hideNameTag(@NonNull TabPlayer player);
/**
* Hides player's NameTag for specified player until it's shown again
*
* @param player
* player to hide name tag of
* @param viewer
* player to hide name tag for
*/
void hideNameTag(@NonNull TabPlayer player, @NonNull TabPlayer viewer);
/**
* Makes player's NameTag visible again
*
* @param player
* player to show name tag of
* @see #hideNameTag(TabPlayer)
* @see #hasHiddenNameTag(TabPlayer)
*/
void showNameTag(@NonNull TabPlayer player);
/**
* Shows player's NameTag for specified viewer if it was hidden before
*
* @param player
* player to show name tag of
* @param viewer
* player to show NameTag back for
*/
void showNameTag(@NonNull TabPlayer player, @NonNull TabPlayer viewer);
/**
* Return whether player has hidden NameTag or not
*
* @param player
* player to check name tag visibility status of
* @return Whether player has hidden NameTag or not
* @see #hideNameTag(TabPlayer)
* @see #showNameTag(TabPlayer)
*/
boolean hasHiddenNameTag(@NonNull TabPlayer player);
/**
* Returns true if NameTag is hidden for specified viewer, false if not
*
* @param player
* player to check visibility status of
* @param viewer
* player to check visibility status for
* @return true if hidden, false if not
*/
boolean hasHiddenNameTag(@NonNull TabPlayer player, @NonNull TabPlayer viewer);
/**
* Unregisters player's team and no longer handles it, as well as disables anti-override for teams.
* This can be resumed using resumeTeamHandling(). If team handling was paused already, nothing happens.
*
* @param player
* player to pause team handling of
*/
void pauseTeamHandling(@NonNull TabPlayer player);
/**
* Resumes team handling if it was before paused using pauseTeamHandling(), if not, nothing happens
*
* @param player
* player to resume team handling of
*/
void resumeTeamHandling(@NonNull TabPlayer player);
/**
* Returns true if team handling is paused for this player using pauseTeamHandling(), false if not, or
* it was resumed already using resumeTeamHandling
*
* @param player
* player to check handling status of
* @return true if paused, false if not
*/
boolean hasTeamHandlingPaused(@NonNull TabPlayer player);
/**
* Forces collision rule for the player. Setting it to null will remove forced value
*
* @param player
* player to set collision rule of
* @param collision
* forced collision rule
*/
void setCollisionRule(@NonNull TabPlayer player, @Nullable Boolean collision);
/**
* Returns forced collision rule or null if collision is not forced using setCollisionRule
*
* @param player
* player to get forced collision of
* @return forced value or null if not forced
*/
@Nullable Boolean getCollisionRule(@NonNull TabPlayer player);
/**
* Changes player's prefix to provided value. Supports placeholders,
* as well as any supported RGB formats. Use {@code null} to reset
* value back to original.
*
* @param player
* player to change prefix of
* @param prefix
* new prefix value
* @see #getCustomPrefix(TabPlayer)
* @see #getOriginalPrefix(TabPlayer)
*/
void setPrefix(@NonNull TabPlayer player, @Nullable String prefix);
/**
* Changes player's suffix to provided value. Supports placeholders,
* as well as any supported RGB formats. Use {@code null} to reset
* value back to original.
*
* @param player
* player to change prefix of
* @param suffix
* new suffix value
* @see #getCustomSuffix(TabPlayer)
* @see #getOriginalSuffix(TabPlayer)
*/
void setSuffix(@NonNull TabPlayer player, @Nullable String suffix);
@Nullable String getCustomPrefix(@NonNull TabPlayer player);
@Nullable String getCustomSuffix(@NonNull TabPlayer player);
@NonNull String getOriginalPrefix(@NonNull TabPlayer player);
@NonNull String getOriginalSuffix(@NonNull TabPlayer player);
/**
* Toggles name tag visibility view on all players for specified player.
* On first call, name tags of all players will become invisible for specified
* player. On second call, they will become visible again.
*
* @param player
* player to toggle name tag visibility view for
* @param sendToggleMessage
* {@code true} if configured toggle message should be sent, {@code false} if not
*/
void toggleNameTagVisibilityView(@NonNull TabPlayer player, boolean sendToggleMessage);
/**
* Returns {@code true} if player has hidden name tags by either calling
* {@link #toggleNameTagVisibilityView(TabPlayer, boolean)} or using a command,
* {@code false} if not.
*
* @param player
* player to check
* @return {@code true} if hidden, {@code false} if not
*/
boolean hasHiddenNameTagVisibilityView(@NonNull TabPlayer player);
}
@@ -0,0 +1,128 @@
package me.neznamy.tab.api.nametag;
import java.util.List;
import lombok.NonNull;
import me.neznamy.tab.api.TabAPI;
import me.neznamy.tab.api.TabPlayer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Interface for manipulating player name tags.
* <p>
* Instance can be obtained using {@link TabAPI#getNameTagManager()} and then casting it.
* This requires both Team and Unlimited name tag features to be enabled in config, otherwise the method will
* return {@code null} or not be an instance of this class.
*/
public interface UnlimitedNameTagManager extends NameTagManager {
/**
* Disables armor stands of specified player and displays vanilla name tags instead.
*
* @param player
* Player to disable armor stands of
* @see #enableArmorStands(TabPlayer)
* @see #hasDisabledArmorStands(TabPlayer)
*/
void disableArmorStands(@NonNull TabPlayer player);
/**
* Enabled back armor stands of player, who was disabled previously using
* {@link #disableArmorStands(TabPlayer)}.
*
* @param player
* Player to enable back
* @see #disableArmorStands(TabPlayer)
* @see #hasDisabledArmorStands(TabPlayer)
*/
void enableArmorStands(@NonNull TabPlayer player);
/**
* Returns {@code true} if player has armor stands disabled using
* {@link #disableArmorStands(TabPlayer)}, {@code false} otherwise.
*
* @param player
* Player to check
* @return {@code true} if disabled, {@code false} if not.
* @see #disableArmorStands(TabPlayer)
* @see #enableArmorStands(TabPlayer)
*/
boolean hasDisabledArmorStands(@NonNull TabPlayer player);
/**
* Changes name to specified value. Set to {@code null} to
* reset back to original value.
*
* @param player
* Player to change name of
* @param customName
* New name, or {@code null} to reset to original value
*/
void setName(@NonNull TabPlayer player, @Nullable String customName);
/**
* Changes line to specified value. Set to {@code null} to reset back to original value.
*
* @param player
* Player to change line of
* @param line
* Name of defined line
* @param value
* Value to use, or {@code null} to reset back to original value
* @see #getDefinedLines()
*/
void setLine(@NonNull TabPlayer player, @NonNull String line, @Nullable String value);
/**
* Returns custom name value set using {@link #setName(TabPlayer, String)}.
*
* @param player
* Player to check
* @return Custom name set previously or {@code null} if not set
* @see #setName(TabPlayer, String)
*/
@Nullable String getCustomName(@NonNull TabPlayer player);
/**
* Returns custom line value set using {@link #setLine(TabPlayer, String, String)}.
*
* @param player
* Player to check
* @param line
* Defined line
* @return Custom name set previously or {@code null} if not set
* @see #setName(TabPlayer, String)
* @see #getDefinedLines()
*/
@Nullable String getCustomLineValue(@NonNull TabPlayer player, @NonNull String line);
/**
* Returns original name value configured in files.
*
* @param player
* Player to check
* @return Original configured name
* @see #setName(TabPlayer, String)
*/
@NotNull String getOriginalName(@NonNull TabPlayer player);
/**
* Returns original line value configured in files.
*
* @param player
* Player to check
* @param line
* Line name
* @return Original configured line
* @see #setLine(TabPlayer, String, String)
*/
@NotNull String getOriginalLineValue(@NonNull TabPlayer player, @NonNull String line);
/**
* Returns list of all defined lines in config, both static and dynamic lines.
*
* @return List of all defined lines in config
*/
@NotNull List<String> getDefinedLines();
}
@@ -0,0 +1,23 @@
package me.neznamy.tab.api.placeholder;
import org.jetbrains.annotations.NotNull;
/**
* An interface representing some kind of placeholder
*/
public interface Placeholder {
/**
* Returns refresh interval of this placeholder
*
* @return refresh interval of this placeholder
*/
int getRefresh();
/**
* Returns placeholder's identifier
*
* @return placeholder's identifier
*/
@NotNull String getIdentifier();
}
@@ -0,0 +1,92 @@
package me.neznamy.tab.api.placeholder;
import lombok.NonNull;
import me.neznamy.tab.api.TabAPI;
import me.neznamy.tab.api.TabPlayer;
import org.jetbrains.annotations.NotNull;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
/**
* An interface allowing placeholder registration. Instance can be
* obtained using {@link TabAPI#getPlaceholderManager()}
*/
public interface PlaceholderManager {
/**
* Registers a server placeholder (placeholder with same output for all players)
*
* @param identifier
* Placeholder identifier
* @param refresh
* Refresh interval
* @param supplier
* Supplier for placeholder output
* @return Registered placeholder for further use
* @throws IllegalArgumentException
* If {@code identifier} does not start and end with {@code %} or
* {@code refresh} is not divisible by 50
*/
@NotNull ServerPlaceholder registerServerPlaceholder(@NonNull String identifier, int refresh, @NonNull Supplier<Object> supplier);
/**
* Registers a player placeholder (placeholder different output per player)
*
* @param identifier
* Placeholder identifier
* @param refresh
* Refresh interval
* @param function
* Function for placeholder output
* @return Registered placeholder for further use
* @throws IllegalArgumentException
* If {@code identifier} does not start and end with {@code %} or
* {@code refresh} is not divisible by 50
*/
@NotNull PlayerPlaceholder registerPlayerPlaceholder(@NonNull String identifier, int refresh, @NonNull Function<TabPlayer, Object> function);
/**
* Registers a relational placeholder (placeholder with output different for each player duo)
*
* @param identifier
* Placeholder identifier
* @param refresh
* Refresh interval
* @param function
* Function for placeholder output
* @return Registered placeholder for further use
* @throws IllegalArgumentException
* If {@code identifier} does not start and end with {@code %},
* does not start with {@code %rel_} or
* {@code refresh} is not divisible by 50
*/
@NotNull RelationalPlaceholder registerRelationalPlaceholder(@NonNull String identifier, int refresh, @NonNull BiFunction<TabPlayer, TabPlayer, Object> function);
/**
* Returns placeholder from specified identifier. If it does not exist, it is registered
* as a PlaceholderAPI placeholder and returned.
*
* @param identifier
* Placeholder identifier
* @return Placeholder with specified identifier
*/
@NotNull Placeholder getPlaceholder(@NonNull String identifier);
/**
* Unregisters placeholder and makes plugin no longer refresh it.
*
* @param placeholder
* Placeholder to unregister
*/
void unregisterPlaceholder(@NonNull Placeholder placeholder);
/**
* Unregisters placeholder and makes plugin no longer refresh it.
*
* @param identifier
* identifier of placeholder to unregister
*/
void unregisterPlaceholder(@NonNull String identifier);
}
@@ -0,0 +1,30 @@
package me.neznamy.tab.api.placeholder;
import lombok.NonNull;
import me.neznamy.tab.api.TabPlayer;
/**
* Interface for player placeholders (placeholders returning different value for each player)
*/
public interface PlayerPlaceholder extends Placeholder {
/**
* Force-updates placeholder value. It will still be overridden by periodic refresh later,
* so this is (only) useful for force an update when value is supposed to change, and you have
* a high refresh interval set.
*
* @param player
* Player to update value for
* @param value
* New value
*/
void updateValue(@NonNull TabPlayer player, @NonNull Object value);
/**
* Force-updates placeholder value using previously provided update function.
*
* @param player
* Player to update value for
*/
void update(@NonNull TabPlayer player);
}
@@ -0,0 +1,34 @@
package me.neznamy.tab.api.placeholder;
import lombok.NonNull;
import me.neznamy.tab.api.TabPlayer;
/**
* An interface for relational placeholders (returning different value for each player duo)
*/
public interface RelationalPlaceholder extends Placeholder {
/**
* Force-updates placeholder value. It will still be overridden by periodic refresh later,
* so this is (only) useful for force an update when value is supposed to change, and you have
* a high refresh interval set.
*
* @param viewer
* Placeholder viewer
* @param target
* Placeholder target
* @param value
* New value
*/
void updateValue(@NonNull TabPlayer viewer, @NonNull TabPlayer target, @NonNull Object value);
/**
* Force-updates placeholder value using previously provided update function.
*
* @param viewer
* Placeholder viewer
* @param target
* Placeholder target
*/
void update(@NonNull TabPlayer viewer, @NonNull TabPlayer target);
}
@@ -0,0 +1,24 @@
package me.neznamy.tab.api.placeholder;
import lombok.NonNull;
/**
* An interface for server placeholders (returning same value for all players)
*/
public interface ServerPlaceholder extends Placeholder {
/**
* Force-updates placeholder value. It will still be overridden by periodic refresh later,
* so this is (only) useful for force an update when value is supposed to change, and you have
* a high refresh interval set.
*
* @param value
* New value
*/
void updateValue(@NonNull Object value);
/**
* Force-updates placeholder value using previously provided update function.
*/
void update();
}
@@ -0,0 +1,32 @@
package me.neznamy.tab.api.scoreboard;
import lombok.NonNull;
import org.jetbrains.annotations.NotNull;
/**
* An interface allowing to work with a line of
* text in scoreboard.
*
*/
public interface Line {
/**
* Returns configured raw text of this line. Placeholders
* remain in raw format.
*
* @return raw text of this line
*/
@NotNull String getText();
/**
* Changes text to new value. Supports placeholders, which are
* automatically registered if needed and refreshed periodically
* based on configuration. No need to call this method to try to
* keep placeholders up to date. If value is identical to previous
* one, nothing happens.
*
* @param text
* Raw text to display in the line
*/
void setText(@NonNull String text);
}
@@ -0,0 +1,90 @@
package me.neznamy.tab.api.scoreboard;
import lombok.NonNull;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* An interface allowing to work with scoreboard, such as adding players,
* removing players and changing lines. New instance can be created using
* {@link ScoreboardManager#createScoreboard(String, String, List)},
* for scoreboards from config {@link ScoreboardManager#getRegisteredScoreboards()}.
*/
public interface Scoreboard {
/**
* Returns internal name of this scoreboard. Name is defined in registration,
* scoreboards from config use name they were defined with. This value is
* used internally and in /tab announce scoreboard command.
*
* @return custom name of this scoreboard
*/
@NotNull String getName();
/**
* Returns raw title of this scoreboard. Placeholders stay in their
* raw format.
*
* @return scoreboard title
* @see #setTitle(String)
*/
@NotNull String getTitle();
/**
* Sets title to specified value. Placeholders are refreshed automatically
* with refresh intervals defined in config. No need to call this method
* to try to keep placeholders up to date. Supports RGB codes using any of
* the supported formats.
* <p>
* Length is limited to 32 characters on &lt;1.13. If the limit is exceeded,
* text will be cut to 32 characters.
* <p>
* Calling this method with same title as before will not do anything.
*
* @param title
* New title to use with placeholder support
* @see #getTitle()
*/
void setTitle(@NonNull String title);
/**
* Returns list of lines in this scoreboard in the order they appear
* in game (first line is on top). This list should only be used for reading,
* for adding/removing lines see {@link #addLine(String)} and {@link #removeLine(int)}.
*
* @return list of lines in this scoreboard
* @see #addLine(String)
* @see #removeLine(int)
*/
@NotNull List<Line> getLines();
/**
* Adds line with specified text on the bottom of scoreboard. Supports
* placeholders, which will automatically be refreshed.
*
* @param text
* Text to display
* @see #getLines()
* @see #removeLine(int)
*/
void addLine(@NonNull String text);
/**
* Removes line with specified index. Index starts at {@code 0} and ends at
* {@link #getLines()}.size()-1.
*
* @param index
* Index of line to remove, starting at 0
* @throws IndexOutOfBoundsException
* if the index is out of range (index &lt; 0 || index &gt;= {@link #getLines()}.size())
* @see #getLines()
* @see #addLine(String)
*/
void removeLine(int index);
/**
* Unregisters this scoreboard from all players who can see it.
*/
void unregister();
}
@@ -0,0 +1,168 @@
package me.neznamy.tab.api.scoreboard;
import java.util.List;
import java.util.Map;
import lombok.NonNull;
import me.neznamy.tab.api.TabPlayer;
import org.jetbrains.annotations.NotNull;
/**
* Interface allowing work with scoreboards, such as creating,
* sending, toggling and modifying.
* <p>
* Instance can be obtained using {@link me.neznamy.tab.api.TabAPI#getScoreboardManager()}.
* This requires the scoreboard feature to be enabled in config,
* the method will return {@code null} otherwise.
*/
public interface ScoreboardManager {
/**
* Creates new scoreboard, registers and returns it. {@code name}
* is internal name of the scoreboard, which it will be registered
* with and further work where scoreboard name is used allowed.
* <p>
* Scoreboard {@code title} is limited to 32 characters on &lt;1.13. If needed,
* it will be cut to 32 character for those players (after replacing
* placeholders). RGB is supported using any of the supported formats.
* Placeholders are supported.
* <p>
* {@code lines} will display in the same order as contained in the list.
* Client can only see up to 15 lines at a time, however you can define
* more, if some of them only consist of placeholder that might be empty.
*
* @param name
* Internal name of the scoreboard
* @param title
* The scoreboard title
* @param lines
* Lines of text in scoreboard (supports placeholders)
* @return The new scoreboard with given parameters
* @throws NullPointerException
* if {@code name} or {@code lines} is {@code null}
*/
@NotNull Scoreboard createScoreboard(@NonNull String name, @NonNull String title, @NonNull List<String> lines);
/**
* Returns map of registered scoreboards via config and API.
* Map key is name of scoreboard, which is defined either in config
* or using {@link #createScoreboard(String, String, List)}.
* Map value is reference to the actual scoreboard.
*
* @return map of registered scoreboards
*/
@NotNull Map<String, Scoreboard> getRegisteredScoreboards();
/**
* Displays scoreboard to defined player. This will disable all display
* condition checks until the scoreboard is unregistered using
* {@link #resetScoreboard(TabPlayer)}. If the player already sees
* this scoreboard, nothing will happen.
*
* @param player
* Player to send scoreboard to
* @param scoreboard
* Scoreboard to display
* @throws NullPointerException
* if {@code player} or {@code scoreboard} is {@code null}
* @see #hasCustomScoreboard(TabPlayer)
* @see #resetScoreboard(TabPlayer)
*/
void showScoreboard(@NonNull TabPlayer player, @NonNull Scoreboard scoreboard);
/**
* Returns {@code true} if player has custom scoreboard set using
* {@link #showScoreboard(TabPlayer, Scoreboard)}, {@code false} if not.
*
* @param player
* Player to check
* @return {@code true} if player has custom scoreboard set using API,
* {@code false} if not
* @see #showScoreboard(TabPlayer, Scoreboard)
* @see #resetScoreboard(TabPlayer)
*/
boolean hasCustomScoreboard(@NonNull TabPlayer player);
/**
* Hides custom scoreboard sent using {@link #showScoreboard(TabPlayer, Scoreboard)}
* and re-enables internal display logic with conditions. If player does not
* have any forced scoreboard, nothing happens.
*
* @param player
* Player to hide custom scoreboard from
* @see #showScoreboard(TabPlayer, Scoreboard)
* @see #hasCustomScoreboard(TabPlayer)
*/
void resetScoreboard(@NonNull TabPlayer player);
/**
* Returns {@code true} if player has scoreboard enabled, {@code false}
* if disabled (toggled) using either toggle command,
* {@link #toggleScoreboard(TabPlayer, boolean)} or
* {@link #setScoreboardVisible(TabPlayer, boolean, boolean)}.
*
* @param player
* Player to get visibility status of
* @return {@code true} if visible, {@code false} if disabled
* @see #setScoreboardVisible(TabPlayer, boolean, boolean)
* @see #toggleScoreboard(TabPlayer, boolean)
*/
boolean hasScoreboardVisible(@NonNull TabPlayer player);
/**
* Sets scoreboard visibility of player to defined value. If visibility status
* is same as player had before, nothing happens. If this call changes
* visibility, scoreboard is toggled. If {@code sendToggleMessage} is {@code true},
* toggle message defined in configuration is sent.
*
* @param player
* Player to set visibility for
* @param visible
* New visibility status
* @param sendToggleMessage
* whether to send toggle message if status changed or not
* @see #toggleScoreboard(TabPlayer, boolean)
* @see #hasScoreboardVisible(TabPlayer)
*/
void setScoreboardVisible(@NonNull TabPlayer player, boolean visible, boolean sendToggleMessage);
/**
* Toggles scoreboard for specified player. If player had scoreboard visible,
* hides it. If hidden, shows it. If {@code sendToggleMessage} is {@code true},
* toggle message defined in configuration is sent.
*
* @param player
* Player to toggle scoreboard for
* @param sendToggleMessage
* Whether to send toggle message or not
* @see #hasScoreboardVisible(TabPlayer)
* @see #setScoreboardVisible(TabPlayer, boolean, boolean)
*/
void toggleScoreboard(@NonNull TabPlayer player, boolean sendToggleMessage);
/**
* Temporarily displays scoreboard to all players for specified amount of
* time (in milliseconds). Scoreboard name is either defined in config, or
* through API in {@link #createScoreboard(String, String, List)}.
*
* @param scoreboard
* Scoreboard from config or registered via API
* @param duration
* Duration in milliseconds
* @throws IllegalArgumentException
* if no scoreboard was found with such name or {@code duration}
* is &lt; 0.
*/
void announceScoreboard(@NonNull String scoreboard, int duration);
/**
* Returns player's currently displayed scoreboard. This can be either with
* configuration, overridden with commands or the API. Will return {@code null}
* if player does not see any scoreboard due to not meeting any display condition.
*
* @param player
* player to get active scoreboard of
* @return player's active scoreboard or {@code null} if player has no scoreboard
*/
@NotNull Scoreboard getActiveScoreboard(@NonNull TabPlayer player);
}
@@ -0,0 +1,57 @@
package me.neznamy.tab.api.tablist;
import lombok.NonNull;
import me.neznamy.tab.api.TabAPI;
import me.neznamy.tab.api.TabPlayer;
import org.jetbrains.annotations.Nullable;
/**
* Interface allowing to send header/footer to players.
* <p>
* Instance can be obtained using {@link TabAPI#getHeaderFooterManager()}.
* This requires the Header/footer feature to be enabled in config, otherwise
* the method will return {@code null}.
*/
public interface HeaderFooterManager {
/**
* Sets raw value of header to specified value. This overrides plugin
* configuration until reset is called. Has full placeholder support
* and will send update packet whenever a placeholder used inside
* changes its value. Use {@code null} to reset value back to original.
*
* @param player
* Player to set header for
* @param header
* Raw header value
*/
void setHeader(@NonNull TabPlayer player, @Nullable String header);
/**
* Sets raw value of footer to specified value. This overrides plugin
* configuration until reset is called. Has full placeholder support
* and will send update packet whenever a placeholder used inside
* changes its value. Use {@code null} to reset value back to original.
*
* @param player
* Player to set header for
* @param footer
* Raw footer value
*/
void setFooter(@NonNull TabPlayer player, @Nullable String footer);
/**
* Sets raw value of header and footer to specified values. This overrides plugin
* configuration until reset is called. Has full placeholder support
* and will send update packet whenever a placeholder used inside
* changes its value. Use {@code null} to reset value back to original.
*
* @param player
* Player to set header for
* @param header
* Raw header value
* @param footer
* Raw footer value
*/
void setHeaderAndFooter(@NonNull TabPlayer player, @Nullable String header, @Nullable String footer);
}
@@ -0,0 +1,38 @@
package me.neznamy.tab.api.tablist;
import lombok.NonNull;
import me.neznamy.tab.api.TabPlayer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public interface SortingManager {
/**
* Forces new team name for the player until this method is called again with null argument and
* performs all actions to change player's team name
*
* @param player
* player to set team name of
* @param teamName
* forced team name
*/
void forceTeamName(@NonNull TabPlayer player, @Nullable String teamName);
/**
* Returns forced team name of player or null if not forced
*
* @param player
* player to check forced team name of
* @return forced team name of player or null if not forced
*/
@Nullable String getForcedTeamName(@NonNull TabPlayer player);
/**
* Returns original team name of the player set by the plugin.
*
* @param player
* Player to get team name of
* @return Player's team name based on configuration.
*/
@NotNull String getOriginalTeamName(@NonNull TabPlayer player);
}
@@ -0,0 +1,132 @@
package me.neznamy.tab.api.tablist;
import lombok.NonNull;
import me.neznamy.tab.api.TabAPI;
import me.neznamy.tab.api.TabPlayer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* An interface allowing to modify TabList display names
* of players.
* <p>
* Instance can be obtained using {@link TabAPI#getTabListFormatManager()}.
* This requires the feature to be enabled in config, otherwise the method will
* return {@code null}.
*/
public interface TabListFormatManager {
/**
* Changes player's prefix to provided value. Supports placeholders,
* as well as any supported RGB formats. Use {@code null} to reset
* value back to original.
*
* @param player
* player to change prefix of
* @param prefix
* new prefix value
* @see #getCustomPrefix(TabPlayer)
* @see #getOriginalPrefix(TabPlayer)
*/
void setPrefix(@NonNull TabPlayer player, @Nullable String prefix);
/**
* Changes player's name to provided value. Supports placeholders,
* as well as any supported RGB formats. Use {@code null} to reset
* value back to original.
*
* @param player
* player to change prefix of
* @param customName
* new customName value
* @see #getCustomName(TabPlayer)
* @see #getOriginalName(TabPlayer)
*/
void setName(@NonNull TabPlayer player, @Nullable String customName);
/**
* Changes player's suffix to provided value. Supports placeholders,
* as well as any supported RGB formats. Use {@code null} to reset
* value back to original.
*
* @param player
* player to change prefix of
* @param suffix
* new suffix value
* @see #getCustomSuffix(TabPlayer)
* @see #getOriginalSuffix(TabPlayer)
*/
void setSuffix(@NonNull TabPlayer player, @Nullable String suffix);
/**
* Returns prefix assigned using {@link #setPrefix(TabPlayer, String)} method.
* If the method was not used, {@code null} is returned.
*
* @param player
* player to get custom prefix of
* @return player's custom prefix or {@code null} if not defined
* @see #setPrefix(TabPlayer, String)
* @see #getOriginalPrefix(TabPlayer)
*/
@Nullable String getCustomPrefix(@NonNull TabPlayer player);
/**
* Returns custom name assigned using {@link #setName(TabPlayer, String)} method.
* If the method was not used, {@code null} is returned.
*
* @param player
* player to get custom name of
* @return player's custom name or {@code null} if not defined
* @see #setName(TabPlayer, String)
* @see #getOriginalName(TabPlayer)
*/
@Nullable String getCustomName(@NonNull TabPlayer player);
/**
* Returns suffix assigned using {@link #setSuffix(TabPlayer, String)} method.
* If the method was not used, {@code null} is returned.
*
* @param player
* player to get custom suffix of
* @return player's custom suffix or {@code null} if not defined
* @see #setSuffix(TabPlayer, String)
* @see #getOriginalSuffix(TabPlayer)
*/
@Nullable String getCustomSuffix(@NonNull TabPlayer player);
/**
* Returns player's original prefix applied using plugin's internal logic.
* This value is not affected by API calls in any way.
*
* @param player
* player to get original prefix of
* @return player's original prefix
* @see #setPrefix(TabPlayer, String)
* @see #getCustomPrefix(TabPlayer)
*/
@NotNull String getOriginalPrefix(@NonNull TabPlayer player);
/**
* Returns player's original name applied using plugin's internal logic.
* This value is not affected by API calls in any way.
*
* @param player
* player to get original name of
* @return player's original name
* @see #setName(TabPlayer, String)
* @see #getCustomName(TabPlayer)
*/
@NotNull String getOriginalName(@NonNull TabPlayer player);
/**
* Returns player's original suffix applied using plugin's internal logic.
* This value is not affected by API calls in any way.
*
* @param player
* player to get original suffix of
* @return player's original suffix
* @see #setSuffix(TabPlayer, String)
* @see #getCustomSuffix(TabPlayer)
*/
@NotNull String getOriginalSuffix(@NonNull TabPlayer player);
}
@@ -0,0 +1,78 @@
package me.neznamy.tab.api.tablist.layout;
import lombok.NonNull;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Interface representing a layout.
*/
public interface Layout {
/**
* Returns name of the layout.
*
* @return name of the layout
*/
@NotNull String getName();
/**
* Adds fixed slot with specified parameters
*
* @param slot
* Slot (1-80)
* @param text
* Text to display
*/
void addFixedSlot(int slot, @NonNull String text);
/**
* Adds fixed slot with specified parameters
*
* @param slot
* Slot (1-80)
* @param text
* Text to display
* @param skin
* Skin definition like in config
*/
void addFixedSlot(int slot, @NonNull String text, @NonNull String skin);
/**
* Adds fixed slot with specified parameters
*
* @param slot
* Slot (1-80)
* @param text
* Text to display
* @param ping
* Slot's ping
*/
void addFixedSlot(int slot, @NonNull String text, int ping);
/**
* Adds fixed slot with specified parameters
*
* @param slot
* Slot (1-80)
* @param text
* Text to display
* @param skin
* Skin definition like in config
* @param ping
* Slot's ping
*/
void addFixedSlot(int slot, @NonNull String text, @NonNull String skin, int ping);
/**
* Adds a player group.
*
* @param condition
* Condition that must be met for player to appear in the group.
* May be null for no requirement. Syntax is like in config -
* either condition name or short format.
* @param slots
* Slots for this player group
*/
void addGroup(@Nullable String condition, int[] slots);
}
@@ -0,0 +1,44 @@
package me.neznamy.tab.api.tablist.layout;
import lombok.NonNull;
import me.neznamy.tab.api.TabAPI;
import me.neznamy.tab.api.TabPlayer;
import org.jetbrains.annotations.Nullable;
/**
* Interface for working with layouts. Instance can be obtained using
* {@link TabAPI#getLayoutManager()}. If the feature is disabled in
* config, it will return {@code null}.
*/
public interface LayoutManager {
/**
* Creates new layout
*
* @param name
* Unique layout name
* @return Created layout
*/
Layout createNewLayout(String name);
/**
* Sends layout to player. Set to {@code null} to make player not see
* any layout, but default TabList instead.
*
* @param player
* Player to send layout to
* @param layout
* Layout to send
* @see #resetLayout(TabPlayer)
*/
void sendLayout(@NonNull TabPlayer player, @Nullable Layout layout);
/**
* Reset layout back to original one based on configuration.
*
* @param player
* Player to reset layout for
* @see #sendLayout(TabPlayer, Layout)
*/
void resetLayout(@NonNull TabPlayer player);
}
+9
View File
@@ -0,0 +1,9 @@
plugins {
`kotlin-dsl`
}
dependencies {
implementation("com.github.johnrengelman:shadow:8.1.1")
implementation("io.freefair.gradle:lombok-plugin:8.0.1")
implementation("fabric-loom:fabric-loom.gradle.plugin:1.1-SNAPSHOT")
}
+9
View File
@@ -0,0 +1,9 @@
rootProject.name = "build-logic"
dependencyResolutionManagement {
repositories {
maven("https://maven.fabricmc.net/")
gradlePluginPortal()
mavenCentral()
}
}
@@ -0,0 +1,36 @@
import org.apache.tools.ant.filters.ReplaceTokens
plugins {
`java-library`
id("io.freefair.lombok")
}
tasks {
processResources {
filter<ReplaceTokens>("tokens" to mapOf(
"id" to rootProject.ext.get("id")!!.toString(),
"name" to rootProject.name,
"version" to project.version,
"description" to project.description,
"website" to rootProject.ext.get("website")!!.toString(),
"author" to rootProject.ext.get("author")!!.toString()
))
}
javadoc {
// This saves a decent bit of processing power on slow machines
enabled = false
options.encoding = Charsets.UTF_8.name()
(options as StandardJavadocDocletOptions).addStringOption("Xdoclint:none", "-quiet")
}
compileJava {
options.encoding = Charsets.UTF_8.name()
options.release.set(8)
options.compilerArgs.addAll(listOf("-nowarn", "-Xlint:-unchecked", "-Xlint:-deprecation"))
}
}
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(17))
}
}
Whitespace-only changes.
@@ -0,0 +1,15 @@
plugins {
id("tab.standard-conventions")
id("com.github.johnrengelman.shadow")
}
tasks {
shadowJar {
archiveFileName.set("TAB-${project.name}-${project.version}.jar")
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.me.neznamy.yamlassist")
relocate("org.yaml.snakeyaml", "me.neznamy.tab.libs.org.yaml.snakeyaml")
}
}
@@ -0,0 +1,25 @@
plugins {
id("tab.base-conventions")
`maven-publish`
}
java {
withSourcesJar()
withJavadocJar()
}
publishing {
repositories {
maven {
name = "krypton"
url = uri("https://repo.kryptonmc.org/releases")
credentials(PasswordCredentials::class)
}
}
publications.create<MavenPublication>("mavenJava") {
groupId = rootProject.group as String
artifactId = "tab-${project.name}"
version = rootProject.version as String
from(components["java"])
}
}
+36
View File
@@ -0,0 +1,36 @@
plugins {
id("tab.parent")
}
allprojects {
group = "me.neznamy"
version = "4.0.3-SNAPSHOT"
description = "An all-in-one solution that works"
ext.set("id", "tab")
ext.set("website", "https://github.com/NEZNAMY/TAB")
ext.set("author", "NEZNAMY")
}
val platforms = setOf(
projects.bukkit,
projects.bungeecord,
projects.krypton,
projects.velocity,
projects.sponge7,
projects.sponge8,
projects.fabric
).map { it.dependencyProject }
val special = setOf(
projects.api,
projects.shared
).map { it.dependencyProject }
subprojects {
when (this) {
in platforms -> plugins.apply("tab.platform-conventions")
in special -> plugins.apply("tab.standard-conventions")
else -> plugins.apply("tab.base-conventions")
}
}
+8
View File
@@ -0,0 +1,8 @@
dependencies {
implementation(projects.shared)
implementation("org.bstats:bstats-bukkit:3.0.1")
compileOnly("org.purpurmc.purpur:purpur-api:1.16.5-R0.1-SNAPSHOT")
compileOnly("me.clip:placeholderapi:2.11.2")
compileOnly("com.mojang:authlib:1.5.25")
compileOnly("com.github.MilkBowl:VaultAPI:1.7")
}
@@ -0,0 +1,43 @@
package me.neznamy.tab.platforms.bukkit;
import me.neznamy.tab.shared.platform.EventListener;
import me.neznamy.tab.shared.platform.TabPlayer;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerChangedWorldEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
/**
* The core for bukkit forwarding events into all enabled features
*/
public class BukkitEventListener extends EventListener<Player> implements Listener {
@EventHandler(priority = EventPriority.HIGHEST)
public void onQuit(PlayerQuitEvent e) {
quit(e.getPlayer().getUniqueId());
}
@EventHandler(priority = EventPriority.LOW)
public void onJoin(PlayerJoinEvent e) {
join(e.getPlayer());
}
@EventHandler(priority = EventPriority.LOWEST)
public void onWorldChange(PlayerChangedWorldEvent e) {
worldChange(e.getPlayer().getUniqueId(), e.getPlayer().getWorld().getName());
}
@EventHandler
public void onCommand(PlayerCommandPreprocessEvent e) {
if (command(e.getPlayer().getUniqueId(), e.getMessage())) e.setCancelled(true);
}
@Override
public TabPlayer createPlayer(Player player) {
return new BukkitTabPlayer(player);
}
}
@@ -0,0 +1,153 @@
package me.neznamy.tab.platforms.bukkit;
import com.mojang.authlib.GameProfile;
import io.netty.channel.Channel;
import lombok.SneakyThrows;
import me.neznamy.tab.platforms.bukkit.scoreboard.PacketScoreboard;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.shared.features.nametags.NameTag;
import me.neznamy.tab.shared.platform.TabList;
import me.neznamy.tab.shared.platform.TabPlayer;
import me.neznamy.tab.shared.chat.IChatBaseComponent;
import me.neznamy.tab.platforms.bukkit.nms.storage.nms.NMSStorage;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.features.injection.NettyPipelineInjector;
import me.neznamy.tab.shared.features.sorting.Sorting;
import org.jetbrains.annotations.NotNull;
import java.util.*;
import java.util.stream.Collectors;
/**
* Pipeline injection for bukkit
*/
public class BukkitPipelineInjector extends NettyPipelineInjector {
/**
* Constructs new instance
*/
public BukkitPipelineInjector() {
super("packet_handler");
}
@Override
protected Channel getChannel(@NotNull TabPlayer player) {
BukkitTabPlayer bukkit = (BukkitTabPlayer) player;
NMSStorage nms = NMSStorage.getInstance();
try {
if (nms.CHANNEL != null) return (Channel) nms.CHANNEL.get(nms.NETWORK_MANAGER.get(bukkit.getPlayerConnection()));
} catch (IllegalAccessException exception) {
TAB.getInstance().getErrorManager().printError("Failed to get channel of " + bukkit.getName(), exception);
}
return null;
}
@Override
@SneakyThrows
public void onDisplayObjective(@NotNull TabPlayer player, @NotNull Object packet) {
TAB.getInstance().getFeatureManager().onDisplayObjective(player,
PacketScoreboard.DisplayObjective_POSITION.getInt(packet),
(String) PacketScoreboard.DisplayObjective_OBJECTIVE_NAME.get(packet));
}
@Override
@SneakyThrows
public void onObjective(@NotNull TabPlayer player, @NotNull Object packet) {
TAB.getInstance().getFeatureManager().onObjective(player,
PacketScoreboard.Objective_METHOD.getInt(packet),
(String) PacketScoreboard.Objective_OBJECTIVE_NAME.get(packet));
}
@Override
public boolean isDisplayObjective(@NotNull Object packet) {
return PacketScoreboard.DisplayObjectiveClass.isInstance(packet);
}
@Override
public boolean isObjective(@NotNull Object packet) {
return PacketScoreboard.ObjectivePacketClass.isInstance(packet);
}
@Override
public boolean isTeam(@NotNull Object packet) {
return PacketScoreboard.TeamPacketClass.isInstance(packet);
}
@Override
public boolean isPlayerInfo(@NotNull Object packet) {
return BukkitTabList.PacketPlayOutPlayerInfoClass.isInstance(packet);
}
@Override
@SneakyThrows
public void onPlayerInfo(@NotNull TabPlayer receiver, @NotNull Object packet) {
NMSStorage nms = NMSStorage.getInstance();
List<String> actions;
if (BukkitTabList.ClientboundPlayerInfoRemovePacket != null) {
//1.19.3+
actions = ((EnumSet<?>)BukkitTabList.ACTION.get(packet)).stream().map(Enum::name).collect(Collectors.toList());
} else {
//1.19.2-
actions = Collections.singletonList(BukkitTabList.ACTION.get(packet).toString());
}
List<Object> updatedList = new ArrayList<>();
for (Object nmsData : (List<?>) BukkitTabList.PLAYERS.get(packet)) {
GameProfile profile = (GameProfile) BukkitTabList.PlayerInfoData_getProfile.invoke(nmsData);
Object displayName = null;
if (actions.contains(TabList.Action.UPDATE_DISPLAY_NAME.name()) || actions.contains(TabList.Action.ADD_PLAYER.name())) {
displayName = BukkitTabList.PlayerInfoData_DisplayName.get(nmsData);
IChatBaseComponent newDisplayName = TAB.getInstance().getFeatureManager().onDisplayNameChange(receiver, profile.getId());
if (newDisplayName != null) displayName = nms.toNMSComponent(newDisplayName, receiver.getVersion());
if (!nms.is1_19_3Plus()) BukkitTabList.PlayerInfoData_DisplayName.set(nmsData, displayName);
}
if (nms.is1_19_3Plus()) {
// 1.19.3 is using records, which do not allow changing final fields, need to rewrite the list entirely
updatedList.add(BukkitTabList.newPlayerInfoData.newInstance(
profile.getId(),
profile,
BukkitTabList.PlayerInfoData_Listed.getBoolean(nmsData),
BukkitTabList.PlayerInfoData_Latency.getInt(nmsData),
BukkitTabList.PlayerInfoData_GameMode.get(nmsData),
displayName,
BukkitTabList.PlayerInfoData_RemoteChatSession.get(nmsData)));
}
}
if (nms.is1_19_3Plus()) {
BukkitTabList.PLAYERS.set(packet, updatedList);
}
}
@SuppressWarnings("unchecked")
@Override
@SneakyThrows
public void modifyPlayers(@NotNull Object packetPlayOutScoreboardTeam) {
if (TAB.getInstance().getNameTagManager() == null) return;
int action = PacketScoreboard.TeamPacket_ACTION.getInt(packetPlayOutScoreboardTeam);
if (action == 1 || action == 2 || action == 4) return;
Collection<String> players = (Collection<String>) PacketScoreboard.TeamPacket_PLAYERS.get(packetPlayOutScoreboardTeam);
String teamName = (String) PacketScoreboard.TeamPacket_NAME.get(packetPlayOutScoreboardTeam);
if (players == null) return;
//creating a new list to prevent NoSuchFieldException in minecraft packet encoder when a player is removed
Collection<String> newList = new ArrayList<>();
for (String entry : players) {
TabPlayer p = TAB.getInstance().getPlayer(entry);
if (p == null) {
newList.add(entry);
continue;
}
Sorting sorting = TAB.getInstance().getFeatureManager().getFeature(TabConstants.Feature.SORTING);
String expectedTeam = sorting.getShortTeamName(p);
if (expectedTeam == null) {
newList.add(entry);
continue;
}
if (!((NameTag)TAB.getInstance().getNameTagManager()).getDisableChecker().isDisabledPlayer(p) &&
!TAB.getInstance().getNameTagManager().hasTeamHandlingPaused(p) && !teamName.equals(expectedTeam)) {
logTeamOverride(teamName, p.getName(), expectedTeam);
} else {
newList.add(entry);
}
}
PacketScoreboard.TeamPacket_PLAYERS.set(packetPlayOutScoreboardTeam, newList);
}
}
@@ -0,0 +1,82 @@
package me.neznamy.tab.platforms.bukkit;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.api.placeholder.PlaceholderManager;
import me.neznamy.tab.shared.placeholders.UniversalPlaceholderRegistry;
import net.milkbowl.vault.chat.Chat;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* Bukkit registry to register bukkit-only and universal placeholders
*/
public class BukkitPlaceholderRegistry extends UniversalPlaceholderRegistry {
private Chat chat;
/** NMS server to get TPS from on spigot */
private Object server;
/** TPS field*/
private Field recentTps;
/** Detection for presence of Paper's TPS getter */
private Method paperTps;
/** Detection for presence of Paper's MSPT getter */
private Method paperMspt;
/**
* Constructs new instance and loads hooks
*/
public BukkitPlaceholderRegistry() {
try {
server = Bukkit.getServer().getClass().getMethod("getServer").invoke(Bukkit.getServer());
recentTps = server.getClass().getField("recentTps");
} catch (ReflectiveOperationException e) {
//not spigot
}
try { paperTps = Bukkit.class.getMethod("getTPS"); } catch (NoSuchMethodException ignored) {}
try { paperMspt = Bukkit.class.getMethod("getAverageTickTime"); } catch (NoSuchMethodException ignored) {}
if (Bukkit.getPluginManager().isPluginEnabled("Vault")) {
RegisteredServiceProvider<Chat> rspChat = Bukkit.getServicesManager().getRegistration(Chat.class);
if (rspChat != null) chat = rspChat.getProvider();
}
}
@SuppressWarnings("deprecation")
@Override
public void registerPlaceholders(@NotNull PlaceholderManager manager) {
manager.registerPlayerPlaceholder(TabConstants.Placeholder.DISPLAY_NAME, 500, p -> ((Player) p.getPlayer()).getDisplayName());
if (paperTps != null) {
manager.registerServerPlaceholder(TabConstants.Placeholder.TPS, 1000, () -> formatTPS(Bukkit.getTPS()[0]));
} else if (recentTps != null) {
manager.registerServerPlaceholder(TabConstants.Placeholder.TPS, 1000, () -> {
try {
return formatTPS(((double[]) recentTps.get(server))[0]);
} catch (IllegalAccessException e) {
return -1;
}
});
} else {
manager.registerServerPlaceholder(TabConstants.Placeholder.TPS, -1, () -> -1);
}
if (paperMspt != null) {
manager.registerServerPlaceholder(TabConstants.Placeholder.MSPT, 1000, () -> format(Bukkit.getAverageTickTime()));
}
manager.registerPlayerPlaceholder(TabConstants.Placeholder.HEALTH, 100, p -> (int) Math.ceil(((Player) p.getPlayer()).getHealth()));
if (chat != null) {
manager.registerPlayerPlaceholder("%vault-prefix%", 1000, p -> chat.getPlayerPrefix((Player) p.getPlayer()));
manager.registerPlayerPlaceholder("%vault-suffix%", 1000, p -> chat.getPlayerSuffix((Player) p.getPlayer()));
} else {
manager.registerServerPlaceholder("%vault-prefix%", -1, () -> "");
manager.registerServerPlaceholder("%vault-suffix%", -1, () -> "");
}
super.registerPlaceholders(manager);
}
}
@@ -0,0 +1,84 @@
package me.neznamy.tab.platforms.bukkit;
import me.neznamy.tab.platforms.bukkit.platform.BukkitPlatform;
import me.neznamy.tab.platforms.bukkit.platform.FoliaPlatform;
import me.neznamy.tab.shared.ProtocolVersion;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.shared.chat.EnumChatFormat;
import me.neznamy.tab.platforms.bukkit.nms.storage.nms.*;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.util.ReflectionUtils;
import org.bstats.bukkit.Metrics;
import org.bstats.charts.SimplePie;
import org.bukkit.Bukkit;
import org.bukkit.command.*;
import org.bukkit.plugin.java.JavaPlugin;
/**
* Main class for Bukkit platform
*/
public class BukkitTAB extends JavaPlugin {
@Override
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()) {
Bukkit.getPluginManager().disablePlugin(this);
return;
}
BukkitPlatform platform = ReflectionUtils.classExists("io.papermc.paper.threadedregions.RegionizedServer") ?
new FoliaPlatform(this) : new BukkitPlatform(this);
TAB.setInstance(new TAB(platform, ProtocolVersion.fromFriendlyName(version), getDataFolder()));
if (TAB.getInstance().getServerVersion() == ProtocolVersion.UNKNOWN_SERVER_VERSION) {
Bukkit.getConsoleSender().sendMessage(EnumChatFormat.color("&c[TAB] Unknown server version: " + Bukkit.getBukkitVersion() + "! Plugin may not work correctly."));
}
Bukkit.getPluginManager().registerEvents(new BukkitEventListener(), this);
TAB.getInstance().load();
Metrics metrics = new Metrics(this, 5304);
metrics.addCustomChart(new SimplePie(TabConstants.MetricsChart.UNLIMITED_NAME_TAG_MODE_ENABLED, () -> TAB.getInstance().getFeatureManager().isFeatureEnabled(TabConstants.Feature.UNLIMITED_NAME_TAGS) ? "Yes" : "No"));
metrics.addCustomChart(new SimplePie(TabConstants.MetricsChart.PLACEHOLDER_API, () -> platform.isPlaceholderAPI() ? "Yes" : "No"));
metrics.addCustomChart(new SimplePie(TabConstants.MetricsChart.PERMISSION_SYSTEM, () -> TAB.getInstance().getGroupManager().getPermissionPlugin()));
metrics.addCustomChart(new SimplePie(TabConstants.MetricsChart.SERVER_VERSION, () -> "1." + TAB.getInstance().getServerVersion().getMinorVersion() + ".x"));
PluginCommand cmd = Bukkit.getPluginCommand(TabConstants.COMMAND_BACKEND);
if (cmd == null) return;
BukkitTabCommand command = new BukkitTabCommand();
cmd.setExecutor(command);
cmd.setTabCompleter(command);
}
@Override
public void onDisable() {
//null check due to compatibility check making instance not get set on unsupported versions
if (TAB.getInstance() != null) TAB.getInstance().unload();
}
/**
* Initializes all used NMS classes, constructors, fields and methods.
* Returns {@code true} if everything went successfully,
* {@code false} if anything went wrong.
*
* @return {@code true} if server version is compatible, {@code false} if not
*/
private boolean isVersionSupported() {
try {
long time = System.currentTimeMillis();
String serverPackage = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
int minorVersion = Integer.parseInt(serverPackage.split("_")[1]);
NMSStorage.setInstance(minorVersion >= 17 ? new BukkitModernNMSStorage() : new BukkitLegacyNMSStorage());
Bukkit.getConsoleSender().sendMessage(EnumChatFormat.color("[TAB] Loaded NMS hook in " + (System.currentTimeMillis()-time) + "ms"));
return true;
} catch (Exception ex) {
if (ProtocolVersion.fromFriendlyName(Bukkit.getBukkitVersion().split("-")[0]) == ProtocolVersion.UNKNOWN_SERVER_VERSION) {
Bukkit.getConsoleSender().sendMessage(EnumChatFormat.color("&c[TAB] Your server version is not compatible. " +
"This plugin version was made for " + ProtocolVersion.values()[ProtocolVersion.values().length-1].getFriendlyName() +
" - " + ProtocolVersion.values()[3].getFriendlyName() + ". Disabling."));
} else {
Bukkit.getConsoleSender().sendMessage(EnumChatFormat.color("&c[TAB] A compatibility issue " +
"with your server was found. Unless you are running some really weird server software, this is a bug."));
}
return false;
}
}
}
@@ -0,0 +1,48 @@
package me.neznamy.tab.platforms.bukkit;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.shared.chat.EnumChatFormat;
import me.neznamy.tab.shared.platform.TabPlayer;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
/**
* Command handler for /tab command
*/
public class BukkitTabCommand implements CommandExecutor, TabCompleter {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) {
if (TAB.getInstance().isPluginDisabled()) {
for (String message : TAB.getInstance().getDisabledCommand().execute(args, sender.hasPermission(TabConstants.Permission.COMMAND_RELOAD), sender.hasPermission(TabConstants.Permission.COMMAND_ALL))) {
sender.sendMessage(EnumChatFormat.color(message));
}
} else {
TabPlayer p = null;
if (sender instanceof Player) {
p = TAB.getInstance().getPlayer(((Player)sender).getUniqueId());
if (p == null) return true; //player not loaded correctly
}
TAB.getInstance().getCommand().execute(p, args);
}
return false;
}
@Override
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, String[] args) {
TabPlayer p = null;
if (sender instanceof Player) {
p = TAB.getInstance().getPlayer(((Player)sender).getUniqueId());
if (p == null) return new ArrayList<>(); //player not loaded correctly
}
return TAB.getInstance().getCommand().complete(p, args);
}
}
@@ -0,0 +1,201 @@
package me.neznamy.tab.platforms.bukkit;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import me.neznamy.tab.platforms.bukkit.nms.storage.nms.NMSStorage;
import me.neznamy.tab.shared.ProtocolVersion;
import me.neznamy.tab.shared.chat.IChatBaseComponent;
import me.neznamy.tab.shared.platform.TabList;
import me.neznamy.tab.shared.util.ReflectionUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
/**
* TabList which support modifying many entries at once
* for significantly better performance. For 1.7 players,
* ViaVersion properly splits the packet into multiple, so
* we don't need to worry about that here.
* <p>
* This class does not support server versions of 1.7 and
* below, because of the massive differences in tab list
* and packet fields.
*/
@RequiredArgsConstructor
@SuppressWarnings({"unchecked", "rawtypes"})
public class BukkitTabList implements TabList {
// NMS Fields
public static Class<?> PacketPlayOutPlayerListHeaderFooterClass;
public static Constructor<?> newPacketPlayOutPlayerListHeaderFooter;
public static Field HEADER;
public static Field FOOTER;
public static Class<?> PacketPlayOutPlayerInfoClass;
public static Constructor<?> newPacketPlayOutPlayerInfo;
public static Field ACTION;
public static Field PLAYERS;
public static Class<Enum> EnumPlayerInfoActionClass;
public static Class<Enum> EnumGamemodeClass;
public static Class<?> ClientboundPlayerInfoRemovePacket;
public static Class<?> RemoteChatSession$Data;
public static Constructor<?> newClientboundPlayerInfoRemovePacket;
public static Class<?> PlayerInfoDataClass;
public static Constructor<?> newPlayerInfoData;
public static Method PlayerInfoData_getProfile;
public static Field PlayerInfoData_Latency;
public static Field PlayerInfoData_GameMode;
public static Field PlayerInfoData_DisplayName;
public static Field PlayerInfoData_Listed;
public static Field PlayerInfoData_RemoteChatSession;
/** Player this TabList belongs to */
private final BukkitTabPlayer player;
public static void load(NMSStorage nms) throws NoSuchMethodException {
if (nms.getMinorVersion() >= 17) {
newPacketPlayOutPlayerListHeaderFooter = PacketPlayOutPlayerListHeaderFooterClass.getConstructor(nms.IChatBaseComponent, nms.IChatBaseComponent);
} else {
newPacketPlayOutPlayerListHeaderFooter = PacketPlayOutPlayerListHeaderFooterClass.getConstructor();
HEADER = ReflectionUtils.getFields(PacketPlayOutPlayerListHeaderFooterClass, nms.IChatBaseComponent).get(0);
FOOTER = ReflectionUtils.getFields(PacketPlayOutPlayerListHeaderFooterClass, nms.IChatBaseComponent).get(1);
}
if (nms.is1_19_3Plus()) {
newClientboundPlayerInfoRemovePacket = ClientboundPlayerInfoRemovePacket.getConstructor(List.class);
newPacketPlayOutPlayerInfo = PacketPlayOutPlayerInfoClass.getConstructor(EnumSet.class, Collection.class);
ACTION = ReflectionUtils.getOnlyField(PacketPlayOutPlayerInfoClass, EnumSet.class);
} else {
newPacketPlayOutPlayerInfo = PacketPlayOutPlayerInfoClass.getConstructor(EnumPlayerInfoActionClass, Array.newInstance(nms.EntityPlayer, 0).getClass());
ACTION = ReflectionUtils.getOnlyField(PacketPlayOutPlayerInfoClass, EnumPlayerInfoActionClass);
}
PLAYERS = ReflectionUtils.getOnlyField(PacketPlayOutPlayerInfoClass, List.class);
newPlayerInfoData = ReflectionUtils.getOnlyConstructor(PlayerInfoDataClass);
PlayerInfoData_getProfile = ReflectionUtils.getOnlyMethod(PlayerInfoDataClass, GameProfile.class);
PlayerInfoData_Latency = ReflectionUtils.getOnlyField(PlayerInfoDataClass, int.class);
PlayerInfoData_GameMode = ReflectionUtils.getOnlyField(PlayerInfoDataClass, EnumGamemodeClass);
PlayerInfoData_DisplayName = ReflectionUtils.getOnlyField(PlayerInfoDataClass, nms.IChatBaseComponent);
if (nms.is1_19_3Plus()) {
PlayerInfoData_Listed = ReflectionUtils.getOnlyField(PlayerInfoDataClass, boolean.class);
PlayerInfoData_RemoteChatSession = ReflectionUtils.getOnlyField(PlayerInfoDataClass, RemoteChatSession$Data);
}
}
@Override
@SneakyThrows
public void removeEntry(@NotNull UUID entry) {
if (ClientboundPlayerInfoRemovePacket != null) {
//1.19.3+
player.sendPacket(newClientboundPlayerInfoRemovePacket.newInstance(Collections.singletonList(entry)));
} else {
//1.19.2-
player.sendPacket(createPacket(Action.REMOVE_PLAYER, new Entry.Builder(entry).build(), player.getVersion()));
}
}
@Override
public void updateDisplayName(@NotNull UUID entry, @Nullable IChatBaseComponent displayName) {
player.sendPacket(createPacket(Action.UPDATE_DISPLAY_NAME,
new Entry.Builder(entry).displayName(displayName).build(), player.getVersion())
);
}
@Override
public void updateLatency(@NotNull UUID entry, int latency) {
player.sendPacket(createPacket(Action.UPDATE_LATENCY,
new Entry.Builder(entry).latency(latency).build(), player.getVersion())
);
}
@Override
public void updateGameMode(@NotNull UUID entry, int gameMode) {
player.sendPacket(createPacket(Action.UPDATE_GAME_MODE,
new Entry.Builder(entry).gameMode(gameMode).build(), player.getVersion())
);
}
@Override
public void addEntry(@NotNull Entry entry) {
player.sendPacket(createPacket(Action.ADD_PLAYER, entry, player.getVersion()));
}
@Override
@SneakyThrows
public void setPlayerListHeaderFooter(@NotNull IChatBaseComponent header, @NotNull IChatBaseComponent footer) {
if (PacketPlayOutPlayerListHeaderFooterClass == null) return;
NMSStorage nms = NMSStorage.getInstance();
Object packet;
if (nms.getMinorVersion() >= 17) {
packet = newPacketPlayOutPlayerListHeaderFooter.newInstance(
nms.toNMSComponent(header, player.getVersion()), nms.toNMSComponent(footer, player.getVersion()));
} else {
packet = newPacketPlayOutPlayerListHeaderFooter.newInstance();
HEADER.set(packet, nms.toNMSComponent(header, player.getVersion()));
FOOTER.set(packet, nms.toNMSComponent(footer, player.getVersion()));
}
player.sendPacket(packet);
}
@SneakyThrows
private Object createPacket(TabList.Action action, TabList.Entry entry, ProtocolVersion clientVersion) {
NMSStorage nms = NMSStorage.getInstance();
if (nms.getMinorVersion() < 8) return null;
Object packet;
List<Object> players = new ArrayList<>();
if (NMSStorage.getInstance().is1_19_3Plus()) {
EnumSet<?> actions;
if (action == TabList.Action.ADD_PLAYER) {
actions = EnumSet.allOf(EnumPlayerInfoActionClass);
} else {
actions = EnumSet.of(Enum.valueOf(EnumPlayerInfoActionClass, action.name()));
}
packet = newPacketPlayOutPlayerInfo.newInstance(actions, Collections.emptyList());
GameProfile profile = new GameProfile(entry.getUniqueId(), entry.getName());
if (entry.getSkin() != null) profile.getProperties().put(TabList.TEXTURES_PROPERTY,
new Property(TabList.TEXTURES_PROPERTY, entry.getSkin().getValue(), entry.getSkin().getSignature()));
players.add(newPlayerInfoData.newInstance(
entry.getUniqueId(),
profile,
true,
entry.getLatency(),
int2GameMode(entry.getGameMode()),
entry.getDisplayName() == null ? null : nms.toNMSComponent(entry.getDisplayName(), clientVersion),
null
));
} else {
packet = newPacketPlayOutPlayerInfo.newInstance(Enum.valueOf(EnumPlayerInfoActionClass, action.name()),
Array.newInstance(NMSStorage.getInstance().EntityPlayer, 0));
GameProfile profile = new GameProfile(entry.getUniqueId(), entry.getName());
if (entry.getSkin() != null) profile.getProperties().put(TabList.TEXTURES_PROPERTY,
new Property(TabList.TEXTURES_PROPERTY, entry.getSkin().getValue(), entry.getSkin().getSignature()));
List<Object> parameters = new ArrayList<>();
if (newPlayerInfoData.getParameterTypes()[0] == PacketPlayOutPlayerInfoClass) {
parameters.add(packet);
}
parameters.add(profile);
parameters.add(entry.getLatency());
parameters.add(int2GameMode(entry.getGameMode()));
parameters.add(entry.getDisplayName() == null ? null : nms.toNMSComponent(entry.getDisplayName(), clientVersion));
if (nms.getMinorVersion() >= 19) parameters.add(null);
players.add(newPlayerInfoData.newInstance(parameters.toArray()));
}
PLAYERS.set(packet, players);
return packet;
}
private Object int2GameMode(int gameMode) {
switch (gameMode) {
case 1: return Enum.valueOf(EnumGamemodeClass, "CREATIVE");
case 2: return Enum.valueOf(EnumGamemodeClass, "ADVENTURE");
case 3: return Enum.valueOf(EnumGamemodeClass, "SPECTATOR");
default: return Enum.valueOf(EnumGamemodeClass, "SURVIVAL");
}
}
}
@@ -0,0 +1,179 @@
package me.neznamy.tab.platforms.bukkit;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import lombok.Getter;
import lombok.SneakyThrows;
import me.neznamy.tab.platforms.bukkit.platform.BukkitPlatform;
import me.neznamy.tab.platforms.bukkit.scoreboard.PacketScoreboard;
import me.neznamy.tab.shared.chat.rgb.RGBUtils;
import me.neznamy.tab.shared.hook.ViaVersionHook;
import me.neznamy.tab.shared.platform.bossbar.BossBar;
import me.neznamy.tab.shared.chat.IChatBaseComponent;
import me.neznamy.tab.shared.platform.TabList;
import me.neznamy.tab.platforms.bukkit.bossbar.EntityBossBar;
import me.neznamy.tab.platforms.bukkit.bossbar.BukkitBossBar;
import me.neznamy.tab.platforms.bukkit.bossbar.ViaBossBar;
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcher;
import me.neznamy.tab.platforms.bukkit.nms.storage.nms.NMSStorage;
import me.neznamy.tab.platforms.bukkit.nms.storage.packet.*;
import me.neznamy.tab.shared.platform.Scoreboard;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.backend.BackendTabPlayer;
import me.neznamy.tab.shared.backend.EntityData;
import me.neznamy.tab.shared.backend.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.metadata.MetadataValue;
import org.bukkit.potion.PotionEffectType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.UUID;
/**
* TabPlayer implementation for Bukkit platform
*/
@SuppressWarnings("deprecation")
@Getter
public class BukkitTabPlayer extends BackendTabPlayer {
/** Player's NMS handle (EntityPlayer), preloading for speed */
private final Object handle;
/** Player's connection for sending packets, preloading for speed */
private final Object playerConnection;
private final Scoreboard<BukkitTabPlayer> scoreboard = new PacketScoreboard(this);
private final TabList tabList = new BukkitTabList(this);
private final BossBar bossBar = TAB.getInstance().getServerVersion().getMinorVersion() >= 9 ?
new BukkitBossBar(this) : getVersion().getMinorVersion() >= 9 ? new ViaBossBar(this) : new EntityBossBar(this);
/**
* Constructs new instance with given bukkit player and protocol version
*
* @param p
* bukkit player
*/
@SneakyThrows
public BukkitTabPlayer(Player p) {
super(p, p.getUniqueId(), p.getName(), TAB.getInstance().getConfiguration().getServerName(),
p.getWorld().getName(), ViaVersionHook.getInstance().getPlayerVersion(p.getUniqueId(), p.getName()));
handle = NMSStorage.getInstance().getHandle.invoke(player);
playerConnection = NMSStorage.getInstance().PLAYER_CONNECTION.get(handle);
}
@Override
public boolean hasPermission(@NotNull String permission) {
return getPlayer().hasPermission(permission);
}
@Override
public int getPing() {
if (TAB.getInstance().getServerVersion().getMinorVersion() >= 17) {
return getPlayer().getPing();
}
try {
return NMSStorage.getInstance().PING.getInt(handle);
} catch (IllegalAccessException e) {
return -1;
}
}
@SneakyThrows
public void sendPacket(@Nullable Object nmsPacket) {
if (nmsPacket == null || !getPlayer().isOnline()) return;
NMSStorage.getInstance().sendPacket.invoke(playerConnection, nmsPacket);
}
@Override
public void sendMessage(@NotNull IChatBaseComponent message) {
getPlayer().sendMessage(RGBUtils.getInstance().convertToBukkitFormat(message.toFlatText(),
getVersion().getMinorVersion() >= 16 && TAB.getInstance().getServerVersion().getMinorVersion() >= 16));
}
@Override
public boolean hasInvisibilityPotion() {
return getPlayer().hasPotionEffect(PotionEffectType.INVISIBILITY);
}
@Override
public boolean isDisguised() {
try {
if (!((BukkitPlatform)TAB.getInstance().getPlatform()).isLibsDisguisesEnabled()) return false;
return (boolean) Class.forName("me.libraryaddict.disguise.DisguiseAPI").getMethod("isDisguised", Entity.class).invoke(null, getPlayer());
} catch (LinkageError | ReflectiveOperationException e) {
//java.lang.NoClassDefFoundError: Could not initialize class me.libraryaddict.disguise.DisguiseAPI
TAB.getInstance().getErrorManager().printError("Failed to check disguise status using LibsDisguises", e);
((BukkitPlatform)TAB.getInstance().getPlatform()).setLibsDisguisesEnabled(false);
return false;
}
}
@Override
@SneakyThrows
public TabList.Skin getSkin() {
Collection<Property> col = ((GameProfile)NMSStorage.getInstance().getProfile.invoke(handle)).getProperties().get(TabList.TEXTURES_PROPERTY);
if (col.isEmpty()) return null; //offline mode
Property property = col.iterator().next();
return new TabList.Skin(property.getValue(), property.getSignature());
}
@Override
public @NotNull Player getPlayer() {
return (Player) player;
}
@Override
public boolean isOnline() {
return getPlayer().isOnline();
}
@Override
public boolean isVanished() {
return getPlayer().getMetadata("vanished").stream().anyMatch(MetadataValue::asBoolean);
}
@Override
public int getGamemode() {
return getPlayer().getGameMode().getValue();
}
@Override
public void spawnEntity(int entityId, @NotNull UUID id, @NotNull Object entityType, @NotNull Location location, @NotNull EntityData data) {
sendPacket(PacketPlayOutSpawnEntityLivingStorage.build(entityId, id, entityType, location, data));
if (TAB.getInstance().getServerVersion().getMinorVersion() >= 15) {
updateEntityMetadata(entityId, data);
}
}
@Override
@SneakyThrows
public void updateEntityMetadata(int entityId, @NotNull EntityData data) {
if (PacketPlayOutEntityMetadataStorage.CONSTRUCTOR.getParameterCount() == 2) {
//1.19.3+
sendPacket(PacketPlayOutEntityMetadataStorage.CONSTRUCTOR.newInstance(entityId, DataWatcher.packDirty.invoke(data.build())));
} else {
sendPacket(PacketPlayOutEntityMetadataStorage.CONSTRUCTOR.newInstance(entityId, data.build(), true));
}
}
@Override
public void teleportEntity(int entityId, @NotNull Location location) {
sendPacket(PacketPlayOutEntityTeleportStorage.build(entityId, location));
}
@Override
@SneakyThrows
public void destroyEntities(int... entities) {
if (PacketPlayOutEntityDestroyStorage.CONSTRUCTOR.getParameterTypes()[0] != int.class) {
sendPacket(PacketPlayOutEntityDestroyStorage.CONSTRUCTOR.newInstance(new Object[]{entities}));
} else {
//1.17.0 Mojank
for (int entity : entities) {
sendPacket(PacketPlayOutEntityDestroyStorage.CONSTRUCTOR.newInstance(entity));
}
}
}
}
@@ -0,0 +1,68 @@
package me.neznamy.tab.platforms.bukkit.bossbar;
import lombok.RequiredArgsConstructor;
import me.neznamy.tab.api.bossbar.BarColor;
import me.neznamy.tab.api.bossbar.BarStyle;
import me.neznamy.tab.shared.platform.bossbar.BossBar;
import me.neznamy.tab.shared.chat.rgb.RGBUtils;
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
import me.neznamy.tab.shared.TAB;
import org.bukkit.Bukkit;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* BossBar for 1.9+ servers where Bukkit API is used. If ViaVersion is used
* to allow 1.8 players, it will handle the entity and teleporting by itself.
*/
@RequiredArgsConstructor
public class BukkitBossBar implements BossBar {
/** Player this handler belongs to */
private final BukkitTabPlayer player;
/** Bukkit BossBars the player can currently see */
private final Map<UUID, org.bukkit.boss.BossBar> bossBars = new HashMap<>();
@Override
public void create(@NotNull UUID id, @NotNull String title, float progress, @NotNull BarColor color, @NotNull BarStyle style) {
if (bossBars.containsKey(id)) return;
org.bukkit.boss.BossBar bar = Bukkit.createBossBar(
RGBUtils.getInstance().convertToBukkitFormat(title,
player.getVersion().getMinorVersion() >= 16 && TAB.getInstance().getServerVersion().getMinorVersion() >= 16),
org.bukkit.boss.BarColor.valueOf(color.name()),
org.bukkit.boss.BarStyle.valueOf(style.getBukkitName()));
bar.setProgress(progress);
bar.addPlayer(player.getPlayer());
bossBars.put(id, bar);
}
@Override
public void update(@NotNull UUID id, @NotNull String title) {
bossBars.get(id).setTitle(RGBUtils.getInstance().convertToBukkitFormat(title,
player.getVersion().getMinorVersion() >= 16 && TAB.getInstance().getServerVersion().getMinorVersion() >= 16));
}
@Override
public void update(@NotNull UUID id, float progress) {
bossBars.get(id).setProgress(progress);
}
@Override
public void update(@NotNull UUID id, @NotNull BarStyle style) {
bossBars.get(id).setStyle(org.bukkit.boss.BarStyle.valueOf(style.getBukkitName()));
}
@Override
public void update(@NotNull UUID id, @NotNull BarColor color) {
bossBars.get(id).setColor(org.bukkit.boss.BarColor.valueOf(color.name()));
}
@Override
public void remove(@NotNull UUID id) {
bossBars.remove(id).removePlayer(player.getPlayer());
}
}
@@ -0,0 +1,64 @@
package me.neznamy.tab.platforms.bukkit.bossbar;
import lombok.RequiredArgsConstructor;
import me.neznamy.tab.shared.platform.bossbar.BossBar;
import me.neznamy.tab.api.bossbar.BarColor;
import me.neznamy.tab.api.bossbar.BarStyle;
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcher;
import me.neznamy.tab.shared.backend.Location;
import org.bukkit.entity.EntityType;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
/**
* BossBar using wither entity for <1.9 players on <1.9 servers.
* Additional logic, such as teleporting the entity must be done
* separately, as this class does not handle it.
*/
@RequiredArgsConstructor
public class EntityBossBar implements BossBar {
/** Player this handler belongs to */
private final BukkitTabPlayer player;
@Override
public void create(@NotNull UUID id, @NotNull String title, float progress, @NotNull BarColor color, @NotNull BarStyle style) {
DataWatcher w = new DataWatcher();
float health = 300*progress;
if (health == 0) health = 1;
w.getHelper().setHealth(health);
w.getHelper().setCustomName(title, player.getVersion());
w.getHelper().setEntityFlags((byte) 32);
w.getHelper().setWitherInvulnerableTime(880); // Magic number
player.spawnEntity(id.hashCode(), new UUID(0, 0), EntityType.WITHER, new Location(0, 0, 0, 0, 0), w);
}
@Override
public void update(@NotNull UUID id, @NotNull String title) {
DataWatcher w = new DataWatcher();
w.getHelper().setCustomName(title, player.getVersion());
player.updateEntityMetadata(id.hashCode(), w);
}
@Override
public void update(@NotNull UUID id, float progress) {
DataWatcher w = new DataWatcher();
float health = 300*progress;
if (health == 0) health = 1;
w.getHelper().setHealth(health);
player.updateEntityMetadata(id.hashCode(), w);
}
@Override
public void update(@NotNull UUID id, @NotNull BarStyle style) {/*Added in 1.9*/}
@Override
public void update(@NotNull UUID id, @NotNull BarColor color) {/*Added in 1.9*/}
@Override
public void remove(@NotNull UUID id) {
player.destroyEntities(id.hashCode());
}
}
@@ -0,0 +1,67 @@
package me.neznamy.tab.platforms.bukkit.bossbar;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.legacy.bossbar.BossColor;
import com.viaversion.viaversion.api.legacy.bossbar.BossStyle;
import lombok.RequiredArgsConstructor;
import me.neznamy.tab.shared.platform.bossbar.BossBar;
import me.neznamy.tab.api.bossbar.BarColor;
import me.neznamy.tab.api.bossbar.BarStyle;
import me.neznamy.tab.shared.chat.rgb.RGBUtils;
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* Handler for 1.9+ players on 1.8 server using ViaVersion API.
*/
@RequiredArgsConstructor
public class ViaBossBar implements BossBar {
/** Player this handler belongs to */
private final BukkitTabPlayer player;
/** ViaVersion BossBars this 1.9+ player can see on 1.8 server */
private final Map<UUID, com.viaversion.viaversion.api.legacy.bossbar.BossBar> viaBossBars = new HashMap<>();
@Override
public void create(@NotNull UUID id, @NotNull String title, float progress, @NotNull BarColor color, @NotNull BarStyle style) {
if (viaBossBars.containsKey(id)) return;
com.viaversion.viaversion.api.legacy.bossbar.BossBar bar = Via.getAPI().legacyAPI().createLegacyBossBar(
RGBUtils.getInstance().convertToBukkitFormat(title, player.getVersion().getMinorVersion() >= 16),
progress,
BossColor.valueOf(color.name()),
BossStyle.valueOf(style.getBukkitName()));
viaBossBars.put(id, bar);
bar.addPlayer(player.getPlayer().getUniqueId());
}
@Override
public void update(@NotNull UUID id, @NotNull String title) {
viaBossBars.get(id).setTitle(RGBUtils.getInstance().convertToBukkitFormat(title,
player.getVersion().getMinorVersion() >= 16));
}
@Override
public void update(@NotNull UUID id, float progress) {
viaBossBars.get(id).setHealth(progress);
}
@Override
public void update(@NotNull UUID id, @NotNull BarStyle style) {
viaBossBars.get(id).setStyle(BossStyle.valueOf(style.getBukkitName()));
}
@Override
public void update(@NotNull UUID id, @NotNull BarColor color) {
viaBossBars.get(id).setColor(BossColor.valueOf(color.name()));
}
@Override
public void remove(@NotNull UUID id) {
viaBossBars.remove(id).removePlayer(player.getPlayer().getUniqueId());
}
}
@@ -0,0 +1,199 @@
package me.neznamy.tab.platforms.bukkit.features;
import lombok.SneakyThrows;
import me.neznamy.tab.platforms.bukkit.platform.BukkitPlatform;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.shared.platform.TabPlayer;
import me.neznamy.tab.shared.features.types.PacketSendListener;
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcher;
import me.neznamy.tab.platforms.bukkit.nms.storage.nms.NMSStorage;
import me.neznamy.tab.platforms.bukkit.nms.storage.packet.PacketPlayOutEntityDestroyStorage;
import me.neznamy.tab.platforms.bukkit.nms.storage.packet.PacketPlayOutEntityTeleportStorage;
import me.neznamy.tab.shared.backend.BackendTabPlayer;
import me.neznamy.tab.shared.backend.EntityData;
import me.neznamy.tab.shared.backend.features.unlimitedtags.BackendNameTagX;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.entity.Pose;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.event.player.PlayerToggleSneakEvent;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/**
* The core class for unlimited NameTag mode on Bukkit
*/
public class BukkitNameTagX extends BackendNameTagX implements Listener, PacketSendListener {
/** Reference to NMS storage for quick access */
private final NMSStorage nms = NMSStorage.getInstance();
public BukkitNameTagX(@NotNull JavaPlugin plugin) {
Bukkit.getPluginManager().registerEvents(this, plugin);
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onSneak(PlayerToggleSneakEvent e) {
TabPlayer p = TAB.getInstance().getPlayer(e.getPlayer().getUniqueId());
if (p == null || isPlayerDisabled(p)) return;
TAB.getInstance().getCPUManager().runMeasuredTask(featureName, TabConstants.CpuUsageCategory.PLAYER_SNEAK,
() -> getArmorStandManager(p).sneak(e.isSneaking()));
}
@EventHandler
public void onRespawn(PlayerRespawnEvent e) {
TabPlayer respawned = TAB.getInstance().getPlayer(e.getPlayer().getUniqueId());
if (respawned == null || isPlayerDisabled(respawned)) return;
TAB.getInstance().getCPUManager().runMeasuredTask(featureName, TabConstants.CpuUsageCategory.PLAYER_RESPAWN,
() -> getArmorStandManager(respawned).teleport());
}
@SuppressWarnings("unchecked")
@Override
@SneakyThrows
public void onPacketSend(@NotNull TabPlayer receiver, @NotNull Object packet) {
if (receiver.getVersion().getMinorVersion() < 8) return;
if (!receiver.isLoaded() || getDisableChecker().isDisabledPlayer(receiver) || getUnlimitedDisableChecker().isDisabledPlayer(receiver)) return;
if (nms.PacketPlayOutEntity.isInstance(packet) && !nms.PacketPlayOutEntityLook.isInstance(packet)) { //ignoring head rotation only packets
packetListener.onEntityMove((BackendTabPlayer) receiver, nms.PacketPlayOutEntity_ENTITYID.getInt(packet));
} else if (PacketPlayOutEntityTeleportStorage.CLASS.isInstance(packet)) {
packetListener.onEntityMove((BackendTabPlayer) receiver, PacketPlayOutEntityTeleportStorage.ENTITY_ID.getInt(packet));
} else if (nms.PacketPlayOutNamedEntitySpawn.isInstance(packet)) {
packetListener.onEntitySpawn((BackendTabPlayer) receiver, nms.PacketPlayOutNamedEntitySpawn_ENTITYID.getInt(packet));
} else if (PacketPlayOutEntityDestroyStorage.CLASS.isInstance(packet)) {
if (nms.getMinorVersion() >= 17) {
Object entities = PacketPlayOutEntityDestroyStorage.ENTITIES.get(packet);
if (entities instanceof List) {
packetListener.onEntityDestroy((BackendTabPlayer) receiver, (List<Integer>) entities);
} else {
//1.17.0
packetListener.onEntityDestroy((BackendTabPlayer) receiver, (int) entities);
}
} else {
packetListener.onEntityDestroy((BackendTabPlayer) receiver, (int[]) PacketPlayOutEntityDestroyStorage.ENTITIES.get(packet));
}
}
}
@Override
public double getDistance(@NotNull TabPlayer player1, @NotNull TabPlayer player2) {
Location loc1 = ((Player) player1.getPlayer()).getLocation();
Location loc2 = ((Player) player2.getPlayer()).getLocation();
return Math.sqrt(Math.pow(loc1.getX()-loc2.getX(), 2) + Math.pow(loc1.getZ()-loc2.getZ(), 2));
}
@Override
public boolean areInSameWorld(@NotNull TabPlayer player1, @NotNull TabPlayer player2) {
return ((Player) player1.getPlayer()).getWorld() == ((Player) player2.getPlayer()).getWorld();
}
@Override
public boolean canSee(@NotNull TabPlayer viewer, @NotNull TabPlayer target) {
return ((Player)viewer.getPlayer()).canSee((Player) target.getPlayer());
}
@Override
public void unregisterListener() {
HandlerList.unregisterAll(this);
}
@SuppressWarnings("deprecation")
@Override
public @NotNull List<Integer> getPassengers(@NotNull Object entity) {
Entity vehicle = (Entity) entity;
if (TAB.getInstance().getServerVersion().getMinorVersion() >= 11) {
return vehicle.getPassengers().stream().map(Entity::getEntityId).collect(Collectors.toList());
} else {
if (vehicle.getPassenger() != null) {
return Collections.singletonList(vehicle.getPassenger().getEntityId());
} else {
return Collections.emptyList();
}
}
}
@Override
public @Nullable Object getVehicle(@NotNull TabPlayer player) {
return ((Player)player.getPlayer()).getVehicle();
}
@Override
public int getEntityId(@NotNull Object entity) {
return ((Entity)entity).getEntityId();
}
@Override
public @NotNull String getEntityType(@NotNull Object entity) {
return ((Entity) entity).getType().toString().toLowerCase();
}
@Override
public boolean isSneaking(@NotNull TabPlayer player) {
return ((Player)player.getPlayer()).isSneaking();
}
@Override
public boolean isSwimming(@NotNull TabPlayer player) {
Player p = (Player) player.getPlayer();
if (TAB.getInstance().getServerVersion().getMinorVersion() >= 14 && p.getPose() == Pose.SWIMMING) return true;
return TAB.getInstance().getServerVersion().getMinorVersion() == 13 && p.isSwimming();
}
@Override
public boolean isGliding(@NotNull TabPlayer player) {
return TAB.getInstance().getServerVersion().getMinorVersion() >= 9 && ((Player)player.getPlayer()).isGliding();
}
@Override
public boolean isSleeping(@NotNull TabPlayer player) {
return ((Player)player.getPlayer()).isSleeping();
}
@Override
public @NotNull Object getArmorStandType() {
return EntityType.ARMOR_STAND;
}
@Override
public double getX(@NotNull TabPlayer player) {
return ((Player)player.getPlayer()).getLocation().getX();
}
@Override
public double getY(@NotNull Object entity) {
return ((Entity)entity).getLocation().getY();
}
@Override
public double getZ(@NotNull TabPlayer player) {
return ((Player)player.getPlayer()).getLocation().getZ();
}
@Override
public EntityData createDataWatcher(@NotNull TabPlayer viewer, byte flags, @NotNull String displayName, boolean nameVisible) {
DataWatcher datawatcher = new DataWatcher();
datawatcher.getHelper().setEntityFlags(flags);
datawatcher.getHelper().setCustomName(displayName, viewer.getVersion());
datawatcher.getHelper().setCustomNameVisible(nameVisible);
datawatcher.getHelper().setArmorStandFlags((byte)16);
return datawatcher;
}
@Override
public void runInEntityScheduler(Object entity, Runnable task) {
((BukkitPlatform)TAB.getInstance().getPlatform()).runEntityTask((Entity) entity, task);
}
}
@@ -0,0 +1,60 @@
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.shared.TabConstants;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.platform.TabPlayer;
import me.neznamy.tab.shared.placeholders.expansion.TabExpansion;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
/**
* TAB's expansion for PlaceholderAPI
*/
@Getter
public class BukkitTabExpansion extends PlaceholderExpansion implements TabExpansion {
/** Map holding all values for all players for easy and high-performance access */
private final WeakHashMap<Player, Map<String, String>> values = new WeakHashMap<>();
private final String author = TabConstants.PLUGIN_AUTHOR;
private final String identifier = TabConstants.PLUGIN_ID;
private final String version = TabConstants.PLUGIN_VERSION;
@Override
public boolean persist() {
return true;
}
@Override
public String onPlaceholderRequest(@Nullable Player player, @NotNull String identifier) {
if (identifier.startsWith("replace_")) {
String text = "%" + identifier.substring(8) + "%";
String textBefore;
do {
textBefore = text;
for (String placeholder : TAB.getInstance().getPlaceholderManager().detectPlaceholders(text)) {
text = text.replace(placeholder, TAB.getInstance().getPlaceholderManager().findReplacement(placeholder,
PlaceholderAPI.setPlaceholders(player, placeholder)));
}
} while (!textBefore.equals(text));
return text;
}
if (identifier.startsWith("placeholder_")) {
TAB.getInstance().getPlaceholderManager().addUsedPlaceholder("%" + identifier.substring(12) + "%", TAB.getInstance().getPlaceholderManager());
}
return values.get(player).get(identifier);
}
@Override
public void setValue(@NotNull TabPlayer player, @NotNull String key, @NotNull String value) {
values.computeIfAbsent((Player) player.getPlayer(), p -> new HashMap<>()).put(key, value);
}
}
@@ -0,0 +1,112 @@
package me.neznamy.tab.platforms.bukkit.features;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import me.neznamy.tab.shared.features.types.Loadable;
import me.neznamy.tab.shared.features.types.UnLoadable;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerChangedWorldEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.plugin.java.JavaPlugin;
import me.neznamy.tab.shared.features.types.TabFeature;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.shared.TAB;
import org.jetbrains.annotations.NotNull;
/**
* Per-world-PlayerList feature handler
*/
@SuppressWarnings("deprecation")
@RequiredArgsConstructor
public class PerWorldPlayerList extends TabFeature implements Listener, Loadable, UnLoadable {
/** Config options */
private final boolean allowBypass = TAB.getInstance().getConfig().getBoolean("per-world-playerlist.allow-bypass-permission", false);
private final List<String> ignoredWorlds = TAB.getInstance().getConfig().getStringList("per-world-playerlist.ignore-effect-in-worlds", Arrays.asList("ignored_world", "build"));
private final Map<String, List<String>> sharedWorlds = TAB.getInstance().getConfig().getConfigurationSection("per-world-playerlist.shared-playerlist-world-groups");
/** Plugin reference*/
@NotNull private final JavaPlugin plugin;
@Getter private final String featureName = "Per world PlayerList";
@Override
public void load() {
Bukkit.getOnlinePlayers().forEach(this::checkPlayer);
Bukkit.getPluginManager().registerEvents(this, plugin);
}
@Override
public void unload() {
for (Player p : Bukkit.getOnlinePlayers()) {
for (Player pl : Bukkit.getOnlinePlayers()) {
p.showPlayer(pl);
}
}
HandlerList.unregisterAll(this);
}
@EventHandler
public void onJoin(PlayerJoinEvent e) {
long time = System.nanoTime();
checkPlayer(e.getPlayer());
TAB.getInstance().getCPUManager().addTime(featureName, TabConstants.CpuUsageCategory.PLAYER_JOIN, System.nanoTime()-time);
}
@EventHandler
public void onWorldChange(PlayerChangedWorldEvent e) {
long time = System.nanoTime();
checkPlayer(e.getPlayer());
TAB.getInstance().getCPUManager().addTime(featureName, TabConstants.CpuUsageCategory.WORLD_SWITCH, System.nanoTime()-time);
}
/**
* Performs visibility check on the player. Shows players this player should see and does not,
* hides players the player should not see, shows the player to those who should see player and hides
* from those, who should not see.
*
* @param p
* Player to update
*/
private void checkPlayer(@NotNull Player p) {
for (Player all : Bukkit.getOnlinePlayers()) {
if (all == p) continue;
if (!shouldSee(p, all) && p.canSee(all)) p.hidePlayer(all);
if (shouldSee(p, all) && !p.canSee(all)) p.showPlayer(all);
if (!shouldSee(all, p) && all.canSee(p)) all.hidePlayer(p);
if (shouldSee(all, p) && !all.canSee(p)) all.showPlayer(p);
}
}
/**
* Returns {@code true} if viewer should see target player, {@code false} if not.
* @param viewer
* Player viewing the TabList
* @param target
* Target displayed in the TabList
* @return {@code true} if viewer should see target, {@code false} if not.
*/
private boolean shouldSee(@NotNull Player viewer, @NotNull Player target) {
if (target == viewer) return true;
if ((allowBypass && viewer.hasPermission(TabConstants.Permission.PER_WORLD_PLAYERLIST_BYPASS)) || ignoredWorlds.contains(viewer.getWorld().getName())) return true;
String viewerWorldGroup = viewer.getWorld().getName() + "-default"; //preventing unwanted behavior when some group is called exactly like a world
String targetWorldGroup = target.getWorld().getName() + "-default";
for (Entry<String, List<String>> group : sharedWorlds.entrySet()) {
if (group.getValue() != null) {
if (group.getValue().contains(viewer.getWorld().getName())) viewerWorldGroup = group.getKey();
if (group.getValue().contains(target.getWorld().getName())) targetWorldGroup = group.getKey();
}
}
return viewerWorldGroup.equals(targetWorldGroup);
}
}
@@ -0,0 +1,83 @@
package me.neznamy.tab.platforms.bukkit.features;
import lombok.RequiredArgsConstructor;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.shared.platform.TabPlayer;
import me.neznamy.tab.api.bossbar.BossBar;
import me.neznamy.tab.shared.features.types.WorldSwitchListener;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.backend.BackendTabPlayer;
import me.neznamy.tab.shared.features.bossbar.BossBarManagerImpl;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
/**
* An additional class with additional code for &lt;1.9 servers due to an entity being required
*/
@RequiredArgsConstructor
public class WitherBossBar extends BossBarManagerImpl implements Listener, WorldSwitchListener {
/** Distance of the Wither in blocks */
private static final int WITHER_DISTANCE = 60;
/** Reference to plugin for registering listener */
private final @NotNull JavaPlugin plugin;
@Override
public void load() {
Bukkit.getPluginManager().registerEvents(this, plugin);
//when MC is on fullscreen, BossBar disappears after 1 second of not being seen
//when in a small window, it's about 100ms
TAB.getInstance().getCPUManager().startRepeatingMeasuredTask(100,
featureName, TabConstants.CpuUsageCategory.TELEPORTING_WITHER, this::teleport);
super.load();
teleport();
}
/**
* Updates Wither location for all online players
*/
private void teleport() {
for (TabPlayer p : TAB.getInstance().getOnlinePlayers()) {
if (p.getVersion().getMinorVersion() > 8) continue; //sending VV packets to those
for (BossBar line : getRegisteredBossBars().values()) {
if (!line.getPlayers().contains(p)) continue;
Location loc = ((Player) p.getPlayer()).getEyeLocation().add(((Player) p.getPlayer()).getEyeLocation().getDirection().normalize().multiply(WITHER_DISTANCE));
if (loc.getY() < 1) loc.setY(1);
((BackendTabPlayer)p).teleportEntity(line.getUniqueId().hashCode(), new me.neznamy.tab.shared.backend.Location(loc.getX(), loc.getY(), loc.getZ(), 0, 0));
}
}
}
@Override
public void unload() {
super.unload();
HandlerList.unregisterAll(this);
}
/**
* Respawning wither as respawn screen destroys all entities in client
*/
@EventHandler
public void onRespawn(PlayerRespawnEvent e) {
TabPlayer player = TAB.getInstance().getPlayer(e.getPlayer().getUniqueId());
if (player == null) return;
TAB.getInstance().getCPUManager().runMeasuredTask(featureName, TabConstants.CpuUsageCategory.PLAYER_RESPAWN,
() -> detectBossBarsAndSend(player));
}
@Override
public void onWorldChange(@NotNull TabPlayer p, @NotNull String from, @NotNull String to) {
for (BossBar line : lineValues) {
line.removePlayer(p);
}
detectBossBarsAndSend(p);
}
}
@@ -0,0 +1,89 @@
package me.neznamy.tab.platforms.bukkit.nms.datawatcher;
import lombok.Getter;
import lombok.SneakyThrows;
import lombok.ToString;
import me.neznamy.tab.platforms.bukkit.nms.storage.nms.NMSStorage;
import me.neznamy.tab.shared.backend.EntityData;
import me.neznamy.tab.shared.util.ReflectionUtils;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
/**
* A class representing the n.m.s.DataWatcher class to make work with it much easier
*/
@ToString
public class DataWatcher implements EntityData {
/** NMS Fields */
public static Class<?> CLASS;
private static Constructor<?> CONSTRUCTOR;
private static Method REGISTER;
public static Method markDirty;
public static Method packDirty;
/** 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) throws NoSuchMethodException {
CONSTRUCTOR = ReflectionUtils.getOnlyConstructor(CLASS);
if (nms.getMinorVersion() >= 9) {
REGISTER = ReflectionUtils.getMethod(CLASS, new String[]{"register", "a"}, DataWatcherObject.CLASS, Object.class); // {Bukkit, Bukkit 1.18+}
} else {
REGISTER = ReflectionUtils.getMethod(CLASS, new String[]{"func_75682_a", "a"}, int.class, Object.class); // {Thermos 1.7.10, Bukkit}
}
if (nms.getMinorVersion() >= 19) {
packDirty = CLASS.getMethod("b");
}
if (nms.is1_19_3Plus()) {
markDirty = ReflectionUtils.getOnlyMethod(CLASS, void.class, DataWatcherObject.CLASS);
}
}
/**
* Sets value into data values
*
* @param type
* type of value
* @param value
* value
*/
public void setValue(@NotNull DataWatcherObject type, @NotNull Object value) {
dataValues.put(type.getPosition(), new DataWatcherItem(type, value));
}
/**
* Converts the class into an instance of NMS.DataWatcher
*
* @return an instance of NMS.DataWatcher with same data
*/
@SneakyThrows
public @NotNull Object build() {
NMSStorage nms = NMSStorage.getInstance();
Object nmsWatcher;
if (CONSTRUCTOR.getParameterCount() == 1) { //1.7+
nmsWatcher = CONSTRUCTOR.newInstance(new Object[] {null});
} else {
nmsWatcher = CONSTRUCTOR.newInstance();
}
for (DataWatcherItem item : dataValues.values()) {
Object nmsObject = item.getType().build();
REGISTER.invoke(nmsWatcher, nmsObject, item.getValue());
if (nms.is1_19_3Plus()) markDirty.invoke(nmsWatcher, nmsObject);
}
return nmsWatcher;
}
}
@@ -0,0 +1,160 @@
package me.neznamy.tab.platforms.bukkit.nms.datawatcher;
import lombok.AllArgsConstructor;
import me.neznamy.tab.shared.ProtocolVersion;
import me.neznamy.tab.shared.chat.IChatBaseComponent;
import me.neznamy.tab.platforms.bukkit.nms.storage.nms.NMSStorage;
import me.neznamy.tab.shared.TAB;
import org.jetbrains.annotations.NotNull;
import java.util.Optional;
/**
* A class to help to assign DataWatcher items as positions often change per-version
*/
@AllArgsConstructor
public class DataWatcherHelper {
/** 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();
@NotNull private final DataWatcher data;
/**
* Returns armor stand flags position based on server version
*
* @return armor stand flags position based on server version
*/
private int getArmorStandFlagsPosition() {
if (TAB.getInstance().getServerVersion().getMinorVersion() >= 17) {
//1.17.x, 1.18.x, 1.19.x
return 15;
} else if (TAB.getInstance().getServerVersion().getMinorVersion() >= 15) {
//1.15.x, 1.16.x
return 14;
} else if (TAB.getInstance().getServerVersion().getMinorVersion() >= 14) {
//1.14.x
return 13;
} else if (TAB.getInstance().getServerVersion().getMinorVersion() >= 10) {
//1.10.x - 1.13.x
return 11;
} else {
//1.8.x - 1.9.x
return 10;
}
}
public static void load(NMSStorage nms) throws NoSuchFieldException, IllegalAccessException {
if (nms.getMinorVersion() < 9) return;
DataWatcherSerializer_BYTE = DataWatcherRegistry.getDeclaredField("a").get(null);
DataWatcherSerializer_FLOAT = DataWatcherRegistry.getDeclaredField("c").get(null);
DataWatcherSerializer_STRING = DataWatcherRegistry.getDeclaredField("d").get(null);
if (nms.is1_19_3Plus()) {
DataWatcherSerializer_OPTIONAL_COMPONENT = DataWatcherRegistry.getDeclaredField("g").get(null);
if (nms.is1_19_4Plus()) {
DataWatcherSerializer_BOOLEAN = DataWatcherRegistry.getDeclaredField("k").get(null);
} else {
DataWatcherSerializer_BOOLEAN = DataWatcherRegistry.getDeclaredField("j").get(null);
}
} else {
if (nms.getMinorVersion() >= 13) {
DataWatcherSerializer_OPTIONAL_COMPONENT = DataWatcherRegistry.getDeclaredField("f").get(null);
DataWatcherSerializer_BOOLEAN = DataWatcherRegistry.getDeclaredField("i").get(null);
} else {
DataWatcherSerializer_BOOLEAN = DataWatcherRegistry.getDeclaredField("h").get(null);
}
}
}
/**
* Writes entity byte flags
*
* @param flags
* flags to write
*/
public void setEntityFlags(byte flags) {
data.setValue(new DataWatcherObject(0, DataWatcherSerializer_BYTE), flags);
}
/**
* Writes entity custom name with position based on server version and value depending on client version (RGB or not)
*
* @param customName
* target custom name
* @param clientVersion
* client version
*/
public void setCustomName(@NotNull String customName, @NotNull ProtocolVersion clientVersion) {
if (TAB.getInstance().getServerVersion().getMinorVersion() >= 13) {
data.setValue(new DataWatcherObject(2, DataWatcherSerializer_OPTIONAL_COMPONENT),
Optional.ofNullable(NMSStorage.getInstance().toNMSComponent(IChatBaseComponent.optimizedComponent(customName), clientVersion)));
} else if (TAB.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 (TAB.getInstance().getServerVersion().getMinorVersion() >= 6) {
data.setValue(new DataWatcherObject(10, null), cutName);
} else {
data.setValue(new DataWatcherObject(5, null), cutName);
}
}
}
/**
* Writes custom name visibility boolean
*
* @param visible
* if visible or not
*/
public void setCustomNameVisible(boolean visible) {
if (TAB.getInstance().getServerVersion().getMinorVersion() >= 9) {
data.setValue(new DataWatcherObject(3, DataWatcherSerializer_BOOLEAN), visible);
} else {
data.setValue(new DataWatcherObject(3, null), (byte)(visible?1:0));
}
}
/**
* Writes entity health
*
* @param health
* health of entity
*/
public void setHealth(float health) {
if (TAB.getInstance().getServerVersion().getMinorVersion() >= 6) {
data.setValue(new DataWatcherObject(6, DataWatcherSerializer_FLOAT), health);
} else {
data.setValue(new DataWatcherObject(16, null), (int)health);
}
}
/**
* Writes armor stand flags
*
* @param flags
* flags to write
*/
public void setArmorStandFlags(byte flags) {
data.setValue(new DataWatcherObject(armorStandFlagsPosition, DataWatcherSerializer_BYTE), flags);
}
/**
* Writes wither invulnerable time
* @param time
* Time, apparently
*/
public void setWitherInvulnerableTime(int time) {
if (TAB.getInstance().getServerVersion().getMinorVersion() > 8)
throw new UnsupportedOperationException("Not supported on 1.9+");
data.setValue(new DataWatcherObject(20, null), time);
}
}
@@ -0,0 +1,39 @@
package me.neznamy.tab.platforms.bukkit.nms.datawatcher;
import lombok.Data;
import me.neznamy.tab.platforms.bukkit.nms.storage.nms.NMSStorage;
import me.neznamy.tab.shared.util.ReflectionUtils;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field;
/**
* Class representing NMS Data Watcher Item
*/
@Data
public class DataWatcherItem {
/** NMS Fields */
public static Class<?> CLASS;
public static Field TYPE;
public static Field VALUE;
/** Instance fields */
@NotNull private final DataWatcherObject type;
@NotNull private final Object value;
/**
* Loads all required Fields
*
* @param nms
* NMS storage reference
*/
public static void load(NMSStorage nms) {
VALUE = ReflectionUtils.getFields(CLASS, Object.class).get(0);
if (nms.getMinorVersion() >= 9) {
TYPE = ReflectionUtils.getOnlyField(CLASS, DataWatcherObject.CLASS);
} else {
TYPE = ReflectionUtils.getFields(CLASS, int.class).get(1);
}
}
}
@@ -0,0 +1,54 @@
package me.neznamy.tab.platforms.bukkit.nms.datawatcher;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.SneakyThrows;
import me.neznamy.tab.platforms.bukkit.nms.storage.nms.NMSStorage;
import me.neznamy.tab.shared.util.ReflectionUtils;
import org.jetbrains.annotations.Nullable;
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
*/
@Data @AllArgsConstructor
public class DataWatcherObject {
/** NMS Fields */
public static Class<?> CLASS;
public static Constructor<?> CONSTRUCTOR;
public static Field SLOT;
public static Field SERIALIZER;
/** Instance fields */
private final int position;
@Nullable private final Object serializer;
/**
* Loads all required Fields and throws Exception if something went wrong
*
* @throws NoSuchMethodException
* If something fails
*/
public static void load() throws NoSuchMethodException {
CONSTRUCTOR = CLASS.getConstructor(int.class, DataWatcherHelper.DataWatcherSerializer);
SLOT = ReflectionUtils.getOnlyField(CLASS, int.class);
SERIALIZER = ReflectionUtils.getOnlyField(CLASS, DataWatcherHelper.DataWatcherSerializer);
}
/**
* Converts the object into NMS object
*
* @return NMS object
*/
@SneakyThrows
public Object build() {
if (NMSStorage.getInstance().getMinorVersion() >= 9) {
return DataWatcherObject.CONSTRUCTOR.newInstance(position, serializer);
} else {
return position;
}
}
}
@@ -0,0 +1,109 @@
package me.neznamy.tab.platforms.bukkit.nms.storage.nms;
import me.neznamy.tab.platforms.bukkit.BukkitTabList;
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 me.neznamy.tab.platforms.bukkit.scoreboard.PacketScoreboard;
import org.jetbrains.annotations.NotNull;
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 {
/**
* 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(@NotNull 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. Supports modded servers, such as Thermos.
*
* @param name
* class name
* @return class from given name
* @throws ClassNotFoundException
* if class was not found
*/
public Class<?> getLegacyClass(@NotNull 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 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");
NetworkManager = getLegacyClass("NetworkManager");
DataWatcher.CLASS = getLegacyClass("DataWatcher");
DataWatcherItem.CLASS = getLegacyClass("DataWatcher$Item", "DataWatcher$WatchableObject", "WatchableObject");
PacketPlayOutSpawnEntityLivingStorage.CLASS = getLegacyClass("PacketPlayOutSpawnEntityLiving", "Packet24MobSpawn");
PacketPlayOutEntityTeleportStorage.CLASS = getLegacyClass("PacketPlayOutEntityTeleport", "Packet34EntityTeleport");
PacketPlayOutEntity = getLegacyClass("PacketPlayOutEntity", "Packet30Entity");
PacketPlayOutEntityDestroyStorage.CLASS = getLegacyClass("PacketPlayOutEntityDestroy", "Packet29DestroyEntity");
PacketPlayOutEntityLook = getLegacyClass("PacketPlayOutEntity$PacketPlayOutEntityLook", "PacketPlayOutEntityLook", "Packet32EntityLook");
PacketPlayOutEntityMetadataStorage.CLASS = getLegacyClass("PacketPlayOutEntityMetadata", "Packet40EntityMetadata");
PacketPlayOutNamedEntitySpawn = getLegacyClass("PacketPlayOutNamedEntitySpawn", "Packet20NamedEntitySpawn");
PacketScoreboard.DisplayObjectiveClass = getLegacyClass("PacketPlayOutScoreboardDisplayObjective", "Packet208SetScoreboardDisplayObjective");
PacketScoreboard.ObjectivePacketClass = getLegacyClass("PacketPlayOutScoreboardObjective", "Packet206SetScoreboardObjective");
PacketScoreboard.TeamPacketClass = getLegacyClass("PacketPlayOutScoreboardTeam", "Packet209SetScoreboardTeam");
PacketScoreboard.ScorePacketClass = getLegacyClass("PacketPlayOutScoreboardScore", "Packet207SetScoreboardScore");
PacketScoreboard.Scoreboard = getLegacyClass("Scoreboard");
PacketScoreboard.ScoreboardObjective = getLegacyClass("ScoreboardObjective");
PacketScoreboard.ScoreboardScoreClass = getLegacyClass("ScoreboardScore");
PacketScoreboard.IScoreboardCriteria = getLegacyClass("IScoreboardCriteria", "IObjective"); // 1.5.1+, 1.5
PacketScoreboard.ScoreboardTeam = getLegacyClass("ScoreboardTeam");
if (minorVersion >= 7) {
IChatBaseComponent = getLegacyClass("IChatBaseComponent");
ChatSerializer = getLegacyClass("IChatBaseComponent$ChatSerializer", "ChatSerializer");
}
if (minorVersion >= 8) {
BukkitTabList.PacketPlayOutPlayerListHeaderFooterClass = getLegacyClass("PacketPlayOutPlayerListHeaderFooter");
EntityArmorStand = getLegacyClass("EntityArmorStand");
BukkitTabList.PacketPlayOutPlayerInfoClass = getLegacyClass("PacketPlayOutPlayerInfo");
BukkitTabList.EnumPlayerInfoActionClass = (Class<Enum>) getLegacyClass("PacketPlayOutPlayerInfo$EnumPlayerInfoAction", "EnumPlayerInfoAction");
BukkitTabList.PlayerInfoDataClass = getLegacyClass("PacketPlayOutPlayerInfo$PlayerInfoData", "PlayerInfoData");
BukkitTabList.EnumGamemodeClass = (Class<Enum>) getLegacyClass("EnumGamemode", "WorldSettings$EnumGamemode");
PacketScoreboard.EnumScoreboardHealthDisplay = (Class<Enum>) getLegacyClass("IScoreboardCriteria$EnumScoreboardHealthDisplay", "EnumScoreboardHealthDisplay");
PacketScoreboard.EnumScoreboardAction = (Class<Enum>) getLegacyClass("ScoreboardServer$Action", "PacketPlayOutScoreboardScore$EnumScoreboardAction", "EnumScoreboardAction");
PacketScoreboard.EnumNameTagVisibility = (Class<Enum>) getLegacyClass("ScoreboardTeamBase$EnumNameTagVisibility", "EnumNameTagVisibility");
}
if (minorVersion >= 9) {
DataWatcherObject.CLASS = getLegacyClass("DataWatcherObject");
DataWatcherHelper.DataWatcherRegistry = getLegacyClass("DataWatcherRegistry");
DataWatcherHelper.DataWatcherSerializer = getLegacyClass("DataWatcherSerializer");
PacketScoreboard.EnumTeamPush = (Class<Enum>) getLegacyClass("ScoreboardTeamBase$EnumTeamPush");
}
}
}
@@ -0,0 +1,72 @@
package me.neznamy.tab.platforms.bukkit.nms.storage.nms;
import me.neznamy.tab.platforms.bukkit.BukkitTabList;
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 me.neznamy.tab.platforms.bukkit.scoreboard.PacketScoreboard;
/**
* NMS loader for minecraft 1.17+ using Mojang packaging and bukkit names.
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public class BukkitModernNMSStorage extends NMSStorage {
@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");
BukkitTabList.PacketPlayOutPlayerListHeaderFooterClass = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutPlayerListHeaderFooter");
PacketScoreboard.DisplayObjectiveClass = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutScoreboardDisplayObjective");
PacketScoreboard.ObjectivePacketClass = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutScoreboardObjective");
PacketScoreboard.Scoreboard = Class.forName("net.minecraft.world.scores.Scoreboard");
PacketScoreboard.ScorePacketClass = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutScoreboardScore");
PacketScoreboard.ScoreboardObjective = Class.forName("net.minecraft.world.scores.ScoreboardObjective");
PacketScoreboard.ScoreboardScoreClass = Class.forName("net.minecraft.world.scores.ScoreboardScore");
PacketScoreboard.IScoreboardCriteria = Class.forName("net.minecraft.world.scores.criteria.IScoreboardCriteria");
PacketScoreboard.EnumScoreboardHealthDisplay = (Class<Enum>) Class.forName("net.minecraft.world.scores.criteria.IScoreboardCriteria$EnumScoreboardHealthDisplay");
PacketScoreboard.EnumScoreboardAction = (Class<Enum>) Class.forName("net.minecraft.server.ScoreboardServer$Action");
PacketScoreboard.TeamPacketClass = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutScoreboardTeam");
PacketScoreboard.ScoreboardTeam = Class.forName("net.minecraft.world.scores.ScoreboardTeam");
PacketScoreboard.EnumNameTagVisibility = (Class<Enum>) Class.forName("net.minecraft.world.scores.ScoreboardTeamBase$EnumNameTagVisibility");
PacketScoreboard.EnumTeamPush = (Class<Enum>) Class.forName("net.minecraft.world.scores.ScoreboardTeamBase$EnumTeamPush");
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");
PacketPlayOutEntityTeleportStorage.CLASS = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutEntityTeleport");
PacketPlayOutEntity = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutEntity");
PacketPlayOutEntityDestroyStorage.CLASS = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutEntityDestroy");
PacketPlayOutEntityLook = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutEntity$PacketPlayOutEntityLook");
PacketPlayOutEntityMetadataStorage.CLASS = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutEntityMetadata");
PacketPlayOutNamedEntitySpawn = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutNamedEntitySpawn");
BukkitTabList.EnumGamemodeClass = (Class<Enum>) Class.forName("net.minecraft.world.level.EnumGamemode");
PacketPlayOutSpawnEntityLivingStorage.Vec3D = Class.forName("net.minecraft.world.phys.Vec3D");
PacketPlayOutSpawnEntityLivingStorage.EntityTypes = Class.forName("net.minecraft.world.entity.EntityTypes");
PacketPlayOutSpawnEntityLivingStorage.CLASS = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutSpawnEntity");
if (is1_19_3Plus()) {
BukkitTabList.ClientboundPlayerInfoRemovePacket = Class.forName("net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket");
BukkitTabList.PacketPlayOutPlayerInfoClass = Class.forName("net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket");
BukkitTabList.EnumPlayerInfoActionClass = (Class<Enum>) Class.forName("net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket$a");
BukkitTabList.PlayerInfoDataClass = Class.forName("net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket$b");
BukkitTabList.RemoteChatSession$Data = Class.forName("net.minecraft.network.chat.RemoteChatSession$a");
} else {
BukkitTabList.PacketPlayOutPlayerInfoClass = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo");
BukkitTabList.EnumPlayerInfoActionClass = (Class<Enum>) Class.forName("net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo$EnumPlayerInfoAction");
BukkitTabList.PlayerInfoDataClass = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo$PlayerInfoData");
}
}
}
@@ -0,0 +1,159 @@
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 lombok.SneakyThrows;
import me.neznamy.tab.platforms.bukkit.BukkitTabList;
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcherHelper;
import me.neznamy.tab.platforms.bukkit.scoreboard.PacketScoreboard;
import me.neznamy.tab.shared.ProtocolVersion;
import me.neznamy.tab.shared.chat.IChatBaseComponent;
import me.neznamy.tab.shared.util.ComponentCache;
import me.neznamy.tab.shared.util.ReflectionUtils;
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 org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* 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 */
@Getter 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");
@Getter private final boolean is1_19_4Plus = is1_19_3Plus && !serverPackage.equals("v1_19_R2");
/** 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;
// Ping field for 1.5.2 - 1.16.5, 1.17+ has Player#getPing()
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<?> PacketPlayOutEntity;
public Field PacketPlayOutEntity_ENTITYID;
public Class<?> PacketPlayOutEntityLook;
public Class<?> PacketPlayOutNamedEntitySpawn;
public Field PacketPlayOutNamedEntitySpawn_ENTITYID;
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.
*/
@SneakyThrows
public NMSStorage() {
ProtocolVersion.UNKNOWN_SERVER_VERSION.setMinorVersion(minorVersion); //fixing compatibility with forks that set version field value to "Unknown"
loadClasses();
if (minorVersion >= 7) {
NETWORK_MANAGER = ReflectionUtils.getOnlyField(PlayerConnection, NetworkManager);
sendPacket = ReflectionUtils.getMethods(PlayerConnection, void.class, Packet).get(0);
} else {
sendPacket = ReflectionUtils.getMethod(PlayerConnection, new String[]{"sendPacket"}, Packet);
}
if (minorVersion >= 8) {
ChatSerializer_DESERIALIZE = ChatSerializer.getMethod("a", String.class);
CHANNEL = ReflectionUtils.getOnlyField(NetworkManager, Channel.class);
try {
getProfile = ReflectionUtils.getOnlyMethod(EntityHuman, GameProfile.class);
} catch (IllegalStateException catServer) {
getProfile = EntityHuman.getMethod("getProfile");
}
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);
BukkitTabList.load(this);
}
if (minorVersion >= 9) {
DataWatcherObject.load();
}
PLAYER_CONNECTION = ReflectionUtils.getOnlyField(EntityPlayer, PlayerConnection);
getHandle = Class.forName("org.bukkit.craftbukkit." + serverPackage + ".entity.CraftPlayer").getMethod("getHandle");
DataWatcher.load(this);
DataWatcherItem.load(this);
DataWatcherHelper.load(this);
PacketPlayOutEntityDestroyStorage.load();
PacketPlayOutEntityMetadataStorage.load(this);
PacketPlayOutEntityTeleportStorage.load(this);
PacketPlayOutSpawnEntityLivingStorage.load(this);
PacketScoreboard.load(this);
PacketPlayOutEntity_ENTITYID = ReflectionUtils.getFields(PacketPlayOutEntity, int.class).get(0);
PacketPlayOutNamedEntitySpawn_ENTITYID = ReflectionUtils.getFields(PacketPlayOutNamedEntitySpawn, int.class).get(0);
if (minorVersion < 17) {
try {
(PING = EntityPlayer.getDeclaredField("ping")).setAccessible(true); // 1.5.2 - 1.16.5
} catch (NoSuchFieldException e) {
(PING = EntityPlayer.getDeclaredField("field_71138_i")).setAccessible(true); // 1.7.10 Thermos
}
}
}
/**
* Loads all classes used by the plugin
*
* @throws ClassNotFoundException
* If a class was not found
*/
public abstract void loadClasses() throws ClassNotFoundException;
/**
* 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 @Nullable Object toNMSComponent(@NotNull IChatBaseComponent component, @NotNull ProtocolVersion clientVersion) {
return componentCache.get(component, clientVersion);
}
}
@@ -0,0 +1,33 @@
package me.neznamy.tab.platforms.bukkit.nms.storage.packet;
import me.neznamy.tab.shared.util.ReflectionUtils;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
/**
* Custom class for holding data used in PacketPlayOutEntityDestroy minecraft packet.
*/
public class PacketPlayOutEntityDestroyStorage {
/** NMS Fields */
public static Class<?> CLASS;
public static Constructor<?> CONSTRUCTOR;
public static Field ENTITIES;
/**
* Loads all required Fields and throws Exception if something went wrong
*
* @throws NoSuchMethodException
* If something fails
*/
public static void load() throws NoSuchMethodException {
ENTITIES = ReflectionUtils.getOnlyField(CLASS);
try {
CONSTRUCTOR = CLASS.getConstructor(int[].class);
} catch (NoSuchMethodException e) {
//1.17.0
CONSTRUCTOR = CLASS.getConstructor(int.class);
}
}
}
@@ -0,0 +1,33 @@
package me.neznamy.tab.platforms.bukkit.nms.storage.packet;
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.util.List;
/**
* Custom class for holding data used in PacketPlayOutEntityMetadata minecraft packet.
*/
public class PacketPlayOutEntityMetadataStorage {
/** NMS Fields */
public static Class<?> CLASS;
public static Constructor<?> CONSTRUCTOR;
/**
* 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);
}
}
}
@@ -0,0 +1,87 @@
package me.neznamy.tab.platforms.bukkit.nms.storage.packet;
import lombok.SneakyThrows;
import me.neznamy.tab.platforms.bukkit.nms.storage.nms.NMSStorage;
import me.neznamy.tab.shared.backend.Location;
import me.neznamy.tab.shared.util.ReflectionUtils;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
/**
* Custom class for holding data used in PacketPlayOutEntityTeleport minecraft packet.
*/
public class PacketPlayOutEntityTeleportStorage {
/** 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;
/**
* 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 = ReflectionUtils.getFields(CLASS, int.class).get(0);
YAW = ReflectionUtils.getFields(CLASS, byte.class).get(0);
PITCH = ReflectionUtils.getFields(CLASS, byte.class).get(1);
if (nms.getMinorVersion() >= 17) {
CONSTRUCTOR = CLASS.getConstructor(nms.Entity);
} else {
CONSTRUCTOR = CLASS.getConstructor();
}
if (nms.getMinorVersion() >= 9) {
X = ReflectionUtils.getFields(CLASS, double.class).get(0);
Y = ReflectionUtils.getFields(CLASS, double.class).get(1);
Z = ReflectionUtils.getFields(CLASS, double.class).get(2);
} else {
X = ReflectionUtils.getFields(CLASS, int.class).get(1);
Y = ReflectionUtils.getFields(CLASS, int.class).get(2);
Z = ReflectionUtils.getFields(CLASS, int.class).get(3);
}
}
/**
* Converts this class into NMS packet
*
* @return NMS packet
*/
@SneakyThrows
public static Object build(int entityId, Location location) {
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 static int floor(double paramDouble) {
int i = (int)paramDouble;
return paramDouble < i ? i - 1 : i;
}
}
@@ -0,0 +1,131 @@
package me.neznamy.tab.platforms.bukkit.nms.storage.packet;
import lombok.SneakyThrows;
import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcher;
import me.neznamy.tab.platforms.bukkit.nms.storage.nms.NMSStorage;
import me.neznamy.tab.shared.backend.EntityData;
import me.neznamy.tab.shared.backend.Location;
import me.neznamy.tab.shared.util.ReflectionUtils;
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.
*/
public class PacketPlayOutSpawnEntityLivingStorage {
/** NMS Fields */
public static Class<?> CLASS;
public static Constructor<?> CONSTRUCTOR;
/** 1.17+ */
public static Class<?> Vec3D;
public static Class<?> EntityTypes;
public static Object Vec3D_Empty;
public static Object EntityTypes_ARMOR_STAND;
/** 1.16.5- */
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 final EnumMap<EntityType, Integer> entityIds = new EnumMap<>(EntityType.class);
/**
* 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, IllegalAccessException, NoSuchFieldException {
int minorVersion = nms.getMinorVersion();
if (minorVersion >= 13) {
entityIds.put(EntityType.ARMOR_STAND, 1);
} else {
entityIds.put(EntityType.WITHER, 64);
if (minorVersion >= 8) {
entityIds.put(EntityType.ARMOR_STAND, 30);
}
}
if (minorVersion >= 19) {
EntityTypes_ARMOR_STAND = EntityTypes.getDeclaredField("d").get(null);
CONSTRUCTOR = CLASS.getConstructor(int.class, UUID.class, double.class, double.class, double.class, float.class, float.class, EntityTypes, int.class, Vec3D, double.class);
Vec3D_Empty = ReflectionUtils.getOnlyField(Vec3D, Vec3D).get(null);
} else if (minorVersion >= 17) {
EntityTypes_ARMOR_STAND = EntityTypes.getDeclaredField("c").get(null);
CONSTRUCTOR = CLASS.getConstructor(int.class, UUID.class, double.class, double.class, double.class, float.class, float.class, EntityTypes, int.class, Vec3D);
Vec3D_Empty = ReflectionUtils.getOnlyField(Vec3D, Vec3D).get(null);
} else {
CONSTRUCTOR = CLASS.getConstructor();
ENTITY_ID = ReflectionUtils.getFields(CLASS, int.class).get(0);
YAW = ReflectionUtils.getFields(CLASS, byte.class).get(0);
PITCH = ReflectionUtils.getFields(CLASS, byte.class).get(1);
if (minorVersion >= 9) {
UUID = ReflectionUtils.getOnlyField(CLASS, UUID.class);
X = ReflectionUtils.getFields(CLASS, double.class).get(0);
Y = ReflectionUtils.getFields(CLASS, double.class).get(1);
Z = ReflectionUtils.getFields(CLASS, double.class).get(2);
} else {
X = ReflectionUtils.getFields(CLASS, int.class).get(2);
Y = ReflectionUtils.getFields(CLASS, int.class).get(3);
Z = ReflectionUtils.getFields(CLASS, int.class).get(4);
}
ENTITY_TYPE = ReflectionUtils.getFields(CLASS, int.class).get(1);
if (minorVersion <= 14) {
DATA_WATCHER = ReflectionUtils.getOnlyField(CLASS, DataWatcher.CLASS);
}
}
}
/**
* Converts this class into NMS packet
*
* @return NMS packet
*/
@SneakyThrows
public static Object build(int id, UUID uuid, Object entityType, Location l, EntityData data) {
int minorVersion = NMSStorage.getInstance().getMinorVersion();
if (minorVersion >= 19) {
return CONSTRUCTOR.newInstance(id, uuid, l.getX(), l.getY(), l.getZ(), l.getYaw(), l.getPitch(), EntityTypes_ARMOR_STAND, 0, Vec3D_Empty, 0d);
}
if (minorVersion >= 17) {
return CONSTRUCTOR.newInstance(id, uuid, l.getX(), l.getY(), l.getZ(), l.getYaw(), l.getPitch(), EntityTypes_ARMOR_STAND, 0, Vec3D_Empty);
}
Object nmsPacket = CONSTRUCTOR.newInstance();
ENTITY_ID.set(nmsPacket, id);
YAW.set(nmsPacket, (byte)(l.getYaw() * 256.0f / 360.0f));
PITCH.set(nmsPacket, (byte)(l.getPitch() * 256.0f / 360.0f));
if (minorVersion <= 14) {
DATA_WATCHER.set(nmsPacket, data.build());
}
if (minorVersion >= 9) {
UUID.set(nmsPacket, uuid);
X.set(nmsPacket, l.getX());
Y.set(nmsPacket, l.getY());
Z.set(nmsPacket, l.getZ());
} else {
X.set(nmsPacket, floor(l.getX()*32));
Y.set(nmsPacket, floor(l.getY()*32));
Z.set(nmsPacket, floor(l.getZ()*32));
}
ENTITY_TYPE.set(nmsPacket, entityIds.get((EntityType) entityType));
return nmsPacket;
}
private static int floor(double paramDouble) {
int i = (int)paramDouble;
return paramDouble < i ? i - 1 : i;
}
}
@@ -0,0 +1,176 @@
package me.neznamy.tab.platforms.bukkit.platform;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.SneakyThrows;
import me.clip.placeholderapi.PlaceholderAPI;
import me.neznamy.tab.platforms.bukkit.BukkitPipelineInjector;
import me.neznamy.tab.platforms.bukkit.BukkitPlaceholderRegistry;
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
import me.neznamy.tab.shared.GroupManager;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.shared.chat.IChatBaseComponent;
import me.neznamy.tab.shared.chat.rgb.RGBUtils;
import me.neznamy.tab.shared.features.injection.PipelineInjector;
import me.neznamy.tab.shared.features.types.TabFeature;
import me.neznamy.tab.platforms.bukkit.features.BukkitTabExpansion;
import me.neznamy.tab.platforms.bukkit.features.PerWorldPlayerList;
import me.neznamy.tab.platforms.bukkit.features.WitherBossBar;
import me.neznamy.tab.platforms.bukkit.features.BukkitNameTagX;
import me.neznamy.tab.platforms.bukkit.nms.storage.nms.NMSStorage;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.backend.BackendPlatform;
import me.neznamy.tab.shared.features.PlaceholderManagerImpl;
import me.neznamy.tab.shared.features.bossbar.BossBarManagerImpl;
import me.neznamy.tab.shared.features.nametags.NameTag;
import me.neznamy.tab.shared.hook.LuckPermsHook;
import me.neznamy.tab.shared.placeholders.PlayerPlaceholderImpl;
import me.neznamy.tab.shared.placeholders.expansion.EmptyTabExpansion;
import me.neznamy.tab.shared.placeholders.expansion.TabExpansion;
import me.neznamy.tab.shared.util.ReflectionUtils;
import net.milkbowl.vault.permission.Permission;
import org.bukkit.Bukkit;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
/**
* Implementation of Platform interface for Bukkit platform
*/
@RequiredArgsConstructor
@Getter
public class BukkitPlatform implements BackendPlatform {
/** Plugin instance for registering tasks and events */
private final JavaPlugin plugin;
/** Variables checking presence of other plugins to hook into */
private final boolean placeholderAPI = ReflectionUtils.classExists("me.clip.placeholderapi.PlaceholderAPI");
@Setter private boolean libsDisguisesEnabled = ReflectionUtils.classExists("me.libraryaddict.disguise.DisguiseAPI");
public @NotNull BossBarManagerImpl getLegacyBossBar() {
return new WitherBossBar(plugin);
}
@Override
public void loadPlayers() {
for (Player p : getOnlinePlayers()) {
TAB.getInstance().addPlayer(new BukkitTabPlayer(p));
}
}
@Override
public void registerPlaceholders() {
new BukkitPlaceholderRegistry().registerPlaceholders(TAB.getInstance().getPlaceholderManager());
}
@Override
public @Nullable PipelineInjector createPipelineInjector() {
return NMSStorage.getInstance().getMinorVersion() >= 8 ? new BukkitPipelineInjector() : null;
}
@Override
public @NotNull NameTag getUnlimitedNameTags() {
return new BukkitNameTagX(plugin);
}
@Override
public @NotNull TabExpansion createTabExpansion() {
if (placeholderAPI) {
BukkitTabExpansion expansion = new BukkitTabExpansion();
expansion.register();
return expansion;
}
return new EmptyTabExpansion();
}
@Override
public @Nullable TabFeature getPerWorldPlayerList() {
return new PerWorldPlayerList(plugin);
}
/**
* Returns online players from Bukkit API
*
* @return online players from Bukkit API
*/
@SuppressWarnings("unchecked")
@SneakyThrows
private @NotNull Player[] getOnlinePlayers() {
Object players = Bukkit.class.getMethod("getOnlinePlayers").invoke(null);
if (players instanceof Player[]) {
//1.7-
return (Player[]) players;
} else {
//1.8+
return ((Collection<Player>)players).toArray(new Player[0]);
}
}
@Override
public void registerUnknownPlaceholder(@NotNull String identifier) {
PlaceholderManagerImpl pl = TAB.getInstance().getPlaceholderManager();
int refresh = pl.getRefreshInterval(identifier);
if (identifier.startsWith("%rel_")) {
//relational placeholder
TAB.getInstance().getPlaceholderManager().registerRelationalPlaceholder(identifier, pl.getRefreshInterval(identifier), (viewer, target) ->
placeholderAPI ? PlaceholderAPI.setRelationalPlaceholders((Player) viewer.getPlayer(), (Player) target.getPlayer(), identifier) : identifier);
} else if (identifier.startsWith("%sync:")) {
registerSyncPlaceholder(identifier, refresh);
} else if (identifier.startsWith("%server_")) {
TAB.getInstance().getPlaceholderManager().registerServerPlaceholder(identifier, refresh, () ->
placeholderAPI ? PlaceholderAPI.setPlaceholders(null, identifier) : identifier);
} else {
TAB.getInstance().getPlaceholderManager().registerPlayerPlaceholder(identifier, refresh, p ->
placeholderAPI ? PlaceholderAPI.setPlaceholders((Player) p.getPlayer(), identifier) : identifier);
}
}
public void registerSyncPlaceholder(String identifier, int refresh) {
String syncedPlaceholder = "%" + identifier.substring(6);
PlayerPlaceholderImpl[] ppl = new PlayerPlaceholderImpl[1];
ppl[0] = TAB.getInstance().getPlaceholderManager().registerPlayerPlaceholder(identifier, refresh, p -> {
Bukkit.getScheduler().runTask(plugin, () -> {
long time = System.nanoTime();
ppl[0].updateValue(p, placeholderAPI ? PlaceholderAPI.setPlaceholders((Player) p.getPlayer(), syncedPlaceholder) : identifier);
TAB.getInstance().getCPUManager().addPlaceholderTime(identifier, System.nanoTime()-time);
});
return null;
});
}
@Override
public void sendConsoleMessage(@NotNull IChatBaseComponent message) {
Bukkit.getConsoleSender().sendMessage("[TAB] " + RGBUtils.getInstance().convertToBukkitFormat(message.toFlatText(),
TAB.getInstance().getServerVersion().getMinorVersion() >= 16));
}
@Override
public String getServerVersionInfo() {
return "[Bukkit] " + Bukkit.getName() + " - " + Bukkit.getBukkitVersion().split("-")[0] + " (" + NMSStorage.getInstance().getServerPackage() + ")";
}
@Override
@NotNull public GroupManager detectPermissionPlugin() {
if (LuckPermsHook.getInstance().isInstalled()) {
return new GroupManager("LuckPerms", LuckPermsHook.getInstance().getGroupFunction());
}
if (Bukkit.getPluginManager().isPluginEnabled("Vault")) {
RegisteredServiceProvider<Permission> provider = Bukkit.getServicesManager().getRegistration(Permission.class);
if (provider != null && !provider.getProvider().getName().equals("SuperPerms")) {
return new GroupManager(provider.getProvider().getName(), p -> provider.getProvider().getPrimaryGroup((Player) p.getPlayer()));
}
}
return new GroupManager("None", p -> TabConstants.NO_GROUP);
}
public void runEntityTask(Entity entity, Runnable task) {
task.run();
}
}
@@ -0,0 +1,88 @@
package me.neznamy.tab.platforms.bukkit.platform;
import lombok.SneakyThrows;
import me.clip.placeholderapi.PlaceholderAPI;
import me.neznamy.tab.platforms.bukkit.features.PerWorldPlayerList;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.shared.placeholders.PlayerPlaceholderImpl;
import me.neznamy.tab.shared.platform.TabPlayer;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerChangedWorldEvent;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.function.Consumer;
/**
* Platform override for Folia
*/
public class FoliaPlatform extends BukkitPlatform {
public FoliaPlatform(JavaPlugin plugin) {
super(plugin);
}
@Override
public void loadPlayers() {
super.loadPlayers();
// Values are never updated in the API, warn users
TAB.getInstance().sendConsoleMessage("&cFolia never updates MSPT and TPS values in the API, making " +
"%mspt% and %tps% return the default values (0 and 20).", true);
// Folia never calls PlayerChangedWorldEvent, this is a workaround
TAB.getInstance().getCPUManager().startRepeatingMeasuredTask(100, "Folia compatibility", "Refreshing world", () -> {
for (TabPlayer player : TAB.getInstance().getOnlinePlayers()) {
String bukkitWorld = ((Player)player.getPlayer()).getWorld().getName();
if (!player.getWorld().equals(bukkitWorld)) {
TAB.getInstance().getFeatureManager().onWorldChange(player.getUniqueId(), bukkitWorld);
PerWorldPlayerList pwp = TAB.getInstance().getFeatureManager().getFeature(TabConstants.Feature.PER_WORLD_PLAYER_LIST);
if (pwp != null) {
runSync((Entity) player.getPlayer(), () -> pwp.onWorldChange(new PlayerChangedWorldEvent((Player) player.getPlayer(), ((Player) player.getPlayer()).getWorld())));
}
}
}
});
}
@Override
public void registerSyncPlaceholder(String identifier, int refresh) {
String syncedPlaceholder = "%" + identifier.substring(6);
PlayerPlaceholderImpl[] ppl = new PlayerPlaceholderImpl[1];
ppl[0] = TAB.getInstance().getPlaceholderManager().registerPlayerPlaceholder(identifier, refresh, p -> {
runSync((Entity) p.getPlayer(), () -> {
long time = System.nanoTime();
String output = isPlaceholderAPI() ? PlaceholderAPI.setPlaceholders((Player) p.getPlayer(), syncedPlaceholder) : identifier;
TAB.getInstance().getCPUManager().addPlaceholderTime(identifier, System.nanoTime()-time);
TAB.getInstance().getCPUManager().runTask(() -> ppl[0].updateValue(p, output)); // To ensure player is loaded
});
return null;
});
}
/**
* Runs task using player's entity scheduler. It's using reflection, because
* Folia uses Java 17 while TAB maintains Java 8 compatibility for compatibility
* with MC versions older than their player base.
*
* @param entity
* entity to run task for
* @param task
* Task to run
*/
@SneakyThrows
@SuppressWarnings("JavaReflectionMemberAccess")
private void runSync(Entity entity, Runnable task) {
Object entityScheduler = Entity.class.getMethod("getScheduler").invoke(entity);
Consumer<?> consumer = $ -> task.run(); // Reflection and lambdas don't go together
entityScheduler.getClass().getMethod("run", Plugin.class, Consumer.class, Runnable.class)
.invoke(entityScheduler, getPlugin(), consumer, null);
}
@Override
public void runEntityTask(Entity entity, Runnable task) {
runSync(entity, task);
}
}
@@ -0,0 +1,312 @@
package me.neznamy.tab.platforms.bukkit.scoreboard;
import lombok.SneakyThrows;
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
import me.neznamy.tab.platforms.bukkit.nms.storage.nms.NMSStorage;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.chat.EnumChatFormat;
import me.neznamy.tab.shared.chat.IChatBaseComponent;
import me.neznamy.tab.shared.platform.Scoreboard;
import me.neznamy.tab.shared.util.ReflectionUtils;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.List;
/**
* Scoreboard implementation for Bukkit, which uses packets
* to send scoreboards. While md_5 keeps saying that you don't
* need packets for scoreboards in every single spigot update,
* this is not true. It may seem that way at first, but after
* investigating, fatal problems are found:<p>
* #1 - Limitations on legacy versions are forced in the API.
* While this may not seem like a problem, it enforces those
* limits even for 1.13+ players (if using ViaVersion).<p>
* #2 - Modern versions no longer have any limits, but md_5
* decided to add some random limits for absolutely no reason
* at all. Scoreboard title received a random 128 characters
* limit including color codes. Together with the almighty bukkit
* RGB format using 14 characters for 1 color code, this makes
* gradients just impossible to use. Team prefix/suffix also
* received a 64 characters limit (excluding color codes at least),
* however that might not be enough for displaying a line of text
* in sidebar, which would require splitting the text into prefix
* and suffix, which is just begging for bugs to be introduced.<p>
* #3 - Other plugins can decide to put players into their own
* scoreboard, automatically destroying all visuals made by the
* plugin. They might also put all players into the same scoreboard,
* making per-player view of teams, especially sidebar not working.<p>
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public class PacketScoreboard extends Scoreboard<BukkitTabPlayer> {
private static NMSStorage nms;
public static Class<?> Scoreboard;
public static Class<?> IScoreboardCriteria;
private static Object emptyScoreboard;
private static Field IScoreboardCriteria_self;
// PacketPlayOutScoreboardDisplayObjective
public static Class<?> DisplayObjectiveClass;
private static Constructor<?> newDisplayObjective;
public static Field DisplayObjective_POSITION;
public static Field DisplayObjective_OBJECTIVE_NAME;
// PacketPlayOutScoreboardScore
public static Class<?> ScorePacketClass;
public static Class<?> ScoreboardScoreClass;
public static Class<Enum> EnumScoreboardAction;
private static Constructor<?> newScorePacket_1_13;
private static Constructor<?> newScorePacket_String;
private static Constructor<?> newScorePacket;
private static Constructor<?> newScoreboardScore;
public static Method ScoreboardScore_setScore;
// PacketPlayOutScoreboardObjective
public static Class<?> ObjectivePacketClass;
private static Constructor<?> newObjectivePacket;
public static Field Objective_OBJECTIVE_NAME;
public static Field Objective_METHOD;
private static Field Objective_RENDER_TYPE;
private static Field Objective_DISPLAY_NAME;
public static Class<Enum> EnumScoreboardHealthDisplay;
public static Class<?> ScoreboardObjective;
private static Constructor<?> newScoreboardObjective;
// PacketPlayOutScoreboardTeamStorage
public static Class<?> TeamPacketClass;
private static Constructor<?> newTeamPacket;
private static Method TeamPacketConstructor_of;
private static Method TeamPacketConstructor_ofBoolean;
public static Field TeamPacket_NAME;
public static Field TeamPacket_ACTION;
public static Field TeamPacket_PLAYERS;
public static Class<Enum> EnumNameTagVisibility;
public static Class<Enum> EnumTeamPush;
public static Class<?> ScoreboardTeam;
private static Constructor<?> newScoreboardTeam;
private static Method ScoreboardTeam_getPlayerNameSet;
public static Method ScoreboardTeam_setNameTagVisibility;
private static Method ScoreboardTeam_setCollisionRule;
public static Method ScoreboardTeam_setPrefix;
public static Method ScoreboardTeam_setSuffix;
private static Method ScoreboardTeam_setColor;
public static Method ScoreboardTeam_setAllowFriendlyFire;
public static Method ScoreboardTeam_setCanSeeFriendlyInvisibles;
public static void load(NMSStorage nms) throws ReflectiveOperationException {
PacketScoreboard.nms = nms;
emptyScoreboard = Scoreboard.getConstructor().newInstance();
IScoreboardCriteria_self = ReflectionUtils.getFields(IScoreboardCriteria, IScoreboardCriteria).get(0);
newDisplayObjective = DisplayObjectiveClass.getConstructor(int.class, ScoreboardObjective);
DisplayObjective_POSITION = ReflectionUtils.getOnlyField(DisplayObjectiveClass, int.class);
DisplayObjective_OBJECTIVE_NAME = ReflectionUtils.getOnlyField(DisplayObjectiveClass, String.class);
newScoreboardObjective = ReflectionUtils.getOnlyConstructor(ScoreboardObjective);
Objective_OBJECTIVE_NAME = ReflectionUtils.getFields(ObjectivePacketClass, String.class).get(0);
List<Field> list = ReflectionUtils.getFields(ObjectivePacketClass, int.class);
Objective_METHOD = list.get(list.size()-1);
newScoreboardScore = ScoreboardScoreClass.getConstructor(Scoreboard, ScoreboardObjective, String.class);
newScoreboardTeam = ScoreboardTeam.getConstructor(Scoreboard, String.class);
TeamPacket_NAME = ReflectionUtils.getFields(TeamPacketClass, String.class).get(0);
TeamPacket_ACTION = ReflectionUtils.getInstanceFields(TeamPacketClass, int.class).get(0);
TeamPacket_PLAYERS = ReflectionUtils.getOnlyField(TeamPacketClass, Collection.class);
ScoreboardTeam_getPlayerNameSet = ReflectionUtils.getOnlyMethod(ScoreboardTeam, Collection.class);
ScoreboardScore_setScore = ReflectionUtils.getMethod(ScoreboardScoreClass, new String[] {"func_96647_c", "setScore", "b", "c"}, int.class); // {Thermos, 1.5.1 - 1.17.1, 1.18+, 1.5}
ScoreboardTeam_setAllowFriendlyFire = ReflectionUtils.getMethod(ScoreboardTeam, new String[] {"func_96660_a", "setAllowFriendlyFire", "a"}, boolean.class); // {Thermos, 1.5.1+, 1.5 & 1.18+}
ScoreboardTeam_setCanSeeFriendlyInvisibles = ReflectionUtils.getMethod(ScoreboardTeam, new String[] {"func_98300_b", "setCanSeeFriendlyInvisibles", "b"}, boolean.class); // {Thermos, 1.5.1+, 1.5 & 1.18+}
if (nms.getMinorVersion() >= 13) {
newScorePacket_1_13 = ScorePacketClass.getConstructor(EnumScoreboardAction, String.class, String.class, int.class);
newObjectivePacket = ObjectivePacketClass.getConstructor(ScoreboardObjective, int.class);
Objective_DISPLAY_NAME = ReflectionUtils.getOnlyField(ObjectivePacketClass, nms.IChatBaseComponent);
ScoreboardTeam_setColor = ReflectionUtils.getOnlyMethod(ScoreboardTeam, void.class, nms.EnumChatFormat);
ScoreboardTeam_setPrefix = ReflectionUtils.getMethod(ScoreboardTeam, new String[]{"setPrefix", "b"}, nms.IChatBaseComponent); // {1.17.1-, 1.18+}
ScoreboardTeam_setSuffix = ReflectionUtils.getMethod(ScoreboardTeam, new String[]{"setSuffix", "c"}, nms.IChatBaseComponent); // {1.17.1-, 1.18+}
} else {
newScorePacket_String = ScorePacketClass.getConstructor(String.class);
newObjectivePacket = ObjectivePacketClass.getConstructor();
Objective_DISPLAY_NAME = ReflectionUtils.getFields(ObjectivePacketClass, String.class).get(1);
ScoreboardTeam_setPrefix = ReflectionUtils.getMethod(ScoreboardTeam, new String[] {"func_96666_b", "setPrefix", "b"}, String.class); // {Thermos, 1.5.1+, 1.5}
ScoreboardTeam_setSuffix = ReflectionUtils.getMethod(ScoreboardTeam, new String[] {"func_96662_c", "setSuffix", "c"}, String.class); // {Thermos, 1.5.1+, 1.5}
if (nms.getMinorVersion() >= 8) {
newScorePacket = ScorePacketClass.getConstructor(ScoreboardScoreClass);
Objective_RENDER_TYPE = ReflectionUtils.getOnlyField(ObjectivePacketClass, EnumScoreboardHealthDisplay);
} else {
newScorePacket = ScorePacketClass.getConstructor(ScoreboardScoreClass, int.class);
}
}
if (nms.getMinorVersion() >= 8) {
ScoreboardTeam_setNameTagVisibility = ReflectionUtils.getMethod(ScoreboardTeam, new String[] {"setNameTagVisibility", "a"}, EnumNameTagVisibility); // {1.8.1+, 1.8 & 1.18+}
}
if (nms.getMinorVersion() >= 9) {
ScoreboardTeam_setCollisionRule = ReflectionUtils.getOnlyMethod(ScoreboardTeam, void.class, EnumTeamPush);
}
if (nms.getMinorVersion() >= 17) {
TeamPacketConstructor_of = ReflectionUtils.getOnlyMethod(TeamPacketClass, TeamPacketClass, ScoreboardTeam);
TeamPacketConstructor_ofBoolean = ReflectionUtils.getOnlyMethod(TeamPacketClass, TeamPacketClass, ScoreboardTeam, boolean.class);
} else {
newTeamPacket = TeamPacketClass.getConstructor(ScoreboardTeam, int.class);
}
}
public PacketScoreboard(BukkitTabPlayer player) {
super(player);
}
@Override
@SneakyThrows
public void setDisplaySlot(@NotNull DisplaySlot slot, @NotNull String objective) {
player.sendPacket(newDisplayObjective.newInstance(slot.ordinal(), newScoreboardObjective(objective)));
}
@Override
@SneakyThrows
public void registerObjective0(@NotNull String objectiveName, @NotNull String title, boolean hearts) {
player.sendPacket(buildObjective(0, objectiveName, title, hearts));
}
@Override
public void unregisterObjective0(@NotNull String objectiveName) {
player.sendPacket(buildObjective(1, objectiveName, "", false));
}
@Override
public void updateObjective0(@NotNull String objectiveName, @NotNull String title, boolean hearts) {
player.sendPacket(buildObjective(2, objectiveName, title, hearts));
}
@SneakyThrows
private Object buildObjective(int action, String objectiveName, String title, boolean hearts) {
if (nms.getMinorVersion() >= 13) {
return newObjectivePacket.newInstance(
newScoreboardObjective.newInstance(null, objectiveName, null,
nms.toNMSComponent(IChatBaseComponent.optimizedComponent(title), player.getVersion()),
asDisplayType(hearts)),
action
);
}
Object nmsPacket = newObjectivePacket.newInstance();
Objective_OBJECTIVE_NAME.set(nmsPacket, objectiveName);
Objective_DISPLAY_NAME.set(nmsPacket, title);
if (nms.getMinorVersion() >= 8) {
Objective_RENDER_TYPE.set(nmsPacket, asDisplayType(hearts));
}
Objective_METHOD.set(nmsPacket, action);
return nmsPacket;
}
private Object asDisplayType(boolean hearts) {
return Enum.valueOf(EnumScoreboardHealthDisplay, hearts ? "HEARTS" : "INTEGER");
}
@Override
@SneakyThrows
public void registerTeam0(@NotNull String name, @NotNull String prefix, @NotNull String suffix,
@NotNull NameVisibility visibility, @NotNull CollisionRule collision,
@NotNull Collection<String> players, int options) {
Object team = createTeam(name, prefix, suffix, visibility, collision, options);
((Collection<String>)ScoreboardTeam_getPlayerNameSet.invoke(team)).addAll(players);
if (nms.getMinorVersion() >= 17) {
player.sendPacket(TeamPacketConstructor_ofBoolean.invoke(null, team, true));
} else {
player.sendPacket(newTeamPacket.newInstance(team, 0));
}
}
@Override
@SneakyThrows
public void unregisterTeam0(@NotNull String name) {
Object team = newScoreboardTeam.newInstance(emptyScoreboard, name);
if (nms.getMinorVersion() >= 17) {
player.sendPacket(TeamPacketConstructor_of.invoke(null, team));
} else {
player.sendPacket(newTeamPacket.newInstance(team, 1));
}
}
@Override
@SneakyThrows
public void updateTeam0(@NotNull String name, @NotNull String prefix, @NotNull String suffix,
@NotNull NameVisibility visibility, @NotNull CollisionRule collision, int options) {
Object team = createTeam(name, prefix, suffix, visibility, collision, options);
if (nms.getMinorVersion() >= 17) {
player.sendPacket(TeamPacketConstructor_ofBoolean.invoke(null, team, false));
} else {
player.sendPacket(newTeamPacket.newInstance(team, 2));
}
}
@SneakyThrows
private Object createTeam(String teamName, String prefix, String suffix, NameVisibility visibility, CollisionRule collision, int options) {
Object team = newScoreboardTeam.newInstance(emptyScoreboard, teamName);
ScoreboardTeam_setAllowFriendlyFire.invoke(team, (options & 0x1) > 0);
ScoreboardTeam_setCanSeeFriendlyInvisibles.invoke(team, (options & 0x2) > 0);
if (nms.getMinorVersion() >= 13) {
ScoreboardTeam_setPrefix.invoke(team, nms.toNMSComponent(IChatBaseComponent.optimizedComponent(prefix), player.getVersion()));
ScoreboardTeam_setSuffix.invoke(team, nms.toNMSComponent(IChatBaseComponent.optimizedComponent(suffix), player.getVersion()));
ScoreboardTeam_setColor.invoke(team, Enum.valueOf(nms.EnumChatFormat, EnumChatFormat.lastColorsOf(prefix).toString()));
} else {
ScoreboardTeam_setPrefix.invoke(team, prefix);
ScoreboardTeam_setSuffix.invoke(team, suffix);
}
if (nms.getMinorVersion() >= 8) ScoreboardTeam_setNameTagVisibility.invoke(team, Enum.valueOf(EnumNameTagVisibility, visibility.name()));
if (nms.getMinorVersion() >= 9) ScoreboardTeam_setCollisionRule.invoke(team, Enum.valueOf(EnumTeamPush, collision.name()));
return team;
}
@Override
@SneakyThrows
public void setScore0(@NotNull String objective, @NotNull String playerName, int score) {
Object packet;
if (nms.getMinorVersion() >= 13) {
packet = newScorePacket_1_13.newInstance(Enum.valueOf(EnumScoreboardAction, "CHANGE"), objective, playerName, score);
} else {
Object scoreboardScore = newScoreboardScore.newInstance(emptyScoreboard, newScoreboardObjective(objective), playerName);
ScoreboardScore_setScore.invoke(scoreboardScore, score);
if (nms.getMinorVersion() >= 8) {
packet = newScorePacket.newInstance(scoreboardScore);
} else {
packet = newScorePacket.newInstance(scoreboardScore, 0);
}
}
player.sendPacket(packet);
}
@Override
@SneakyThrows
public void removeScore0(@NotNull String objective, @NotNull String playerName) {
if (nms.getMinorVersion() >= 13) {
player.sendPacket(newScorePacket_1_13.newInstance(Enum.valueOf(EnumScoreboardAction, "REMOVE"), objective, playerName, 0));
} else {
player.sendPacket(newScorePacket_String.newInstance(playerName));
}
}
/**
* Creates a new Scoreboard Objective with given name.
*
* @param objectiveName
* Objective name
* @return NMS Objective
*/
@SneakyThrows
public Object newScoreboardObjective(@NotNull String objectiveName) {
if (nms.getMinorVersion() >= 13) {
return newScoreboardObjective.newInstance(
null,
objectiveName,
null,
nms.toNMSComponent(new IChatBaseComponent(""), TAB.getInstance().getServerVersion()),
null
);
}
return newScoreboardObjective.newInstance(
null,
objectiveName,
IScoreboardCriteria_self.get(null)
);
}
}
@@ -0,0 +1,147 @@
package me.neznamy.tab.platforms.bukkit.scoreboard;
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.chat.EnumChatFormat;
import me.neznamy.tab.shared.chat.IChatBaseComponent;
import me.neznamy.tab.shared.platform.Scoreboard;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.scoreboard.Objective;
import org.bukkit.scoreboard.RenderType;
import org.bukkit.scoreboard.Team;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
/**
* Scoreboard handler using Paper API, which got added
* in early 1.16.5 builds. Unlike the Bukkit API, the new
* methods using adventure components do not have any
* pointless artificial limits added in.
* <p>
* However, it still inherits the issue with compatibility
* with other plugins that create scoreboards.
* <p>
* Currently, this class is never used. In the future, it might
* be used as a fallback solution for unsupported versions if NMS
* changes and fields fail to load. Or as a complete replacement
* if compatibility with other plugins turns out not to be a problem.
*/
// Throw the NPE if something is not as expected, parent class should ensure it anyway
// Use Bukkit setColor, the adventure one does not support magic codes while they are permitted
@SuppressWarnings({"ConstantConditions", "deprecation"})
public class PaperScoreboard extends Scoreboard<BukkitTabPlayer> {
private final org.bukkit.scoreboard.Scoreboard scoreboard = Bukkit.getScoreboardManager().getNewScoreboard();
public PaperScoreboard(BukkitTabPlayer player) {
super(player);
// Put player into a different scoreboard for per-player view
player.getPlayer().setScoreboard(scoreboard);
}
@Override
public void setDisplaySlot(@NotNull DisplaySlot slot, @NotNull String objective) {
checkPlayerScoreboard();
scoreboard.getObjective(objective).setDisplaySlot(org.bukkit.scoreboard.DisplaySlot.valueOf(slot.name()));
}
@Override
public void setScore0(@NotNull String objective, @NotNull String playerName, int score) {
checkPlayerScoreboard();
scoreboard.getObjective(objective).getScore(playerName).setScore(score);
}
@Override
public void removeScore0(@NotNull String objective, @NotNull String playerName) {
checkPlayerScoreboard();
scoreboard.resetScores(playerName);
}
@Override
public void registerObjective0(@NotNull String objectiveName, @NotNull String title, boolean hearts) {
checkPlayerScoreboard();
scoreboard.registerNewObjective(objectiveName, "dummy", toAdventure(title), hearts ? RenderType.HEARTS : RenderType.INTEGER);
}
@Override
public void unregisterObjective0(@NotNull String objectiveName) {
checkPlayerScoreboard();
scoreboard.getObjective(objectiveName).unregister();
}
@Override
public void updateObjective0(@NotNull String objectiveName, @NotNull String title, boolean hearts) {
checkPlayerScoreboard();
Objective obj = scoreboard.getObjective(objectiveName);
obj.setRenderType(hearts ? RenderType.HEARTS : RenderType.INTEGER);
obj.displayName(toAdventure(title));
}
@Override
public void registerTeam0(@NotNull String name, @NotNull String prefix, @NotNull String suffix,
@NotNull NameVisibility visibility, @NotNull CollisionRule collision,
@NotNull Collection<String> players, int options) {
checkPlayerScoreboard();
Team team = scoreboard.registerNewTeam(name);
team.prefix(toAdventure(prefix));
team.suffix(toAdventure(suffix));
team.setColor(ChatColor.valueOf(EnumChatFormat.lastColorsOf(prefix).name()));
team.setOption(Team.Option.NAME_TAG_VISIBILITY, Team.OptionStatus.values()[visibility.ordinal()]);
team.setOption(Team.Option.COLLISION_RULE, Team.OptionStatus.values()[collision.ordinal()]);
players.forEach(team::addEntry);
team.setAllowFriendlyFire((options & 0x01) != 0);
team.setCanSeeFriendlyInvisibles((options & 0x02) != 0);
}
@Override
public void unregisterTeam0(@NotNull String name) {
checkPlayerScoreboard();
scoreboard.getTeam(name).unregister();
}
@Override
public void updateTeam0(@NotNull String name, @NotNull String prefix, @NotNull String suffix,
@NotNull NameVisibility visibility, @NotNull CollisionRule collision, int options) {
checkPlayerScoreboard();
Team team = scoreboard.getTeam(name);
team.prefix(toAdventure(prefix));
team.suffix(toAdventure(suffix));
team.setColor(ChatColor.valueOf(EnumChatFormat.lastColorsOf(prefix).name()));
team.setOption(Team.Option.NAME_TAG_VISIBILITY, Team.OptionStatus.values()[visibility.ordinal()]);
team.setOption(Team.Option.COLLISION_RULE, Team.OptionStatus.values()[collision.ordinal()]);
team.setAllowFriendlyFire((options & 0x01) != 0);
team.setCanSeeFriendlyInvisibles((options & 0x02) != 0);
}
/**
* Converts raw text into adventure component
*
* @param text
* Text to convert
* @return Converted component
*/
private @NotNull Component toAdventure(@NotNull String text) {
return IChatBaseComponent.optimizedComponent(text).toAdventureComponent(player.getVersion());
}
/**
* Makes sure player is in the correct scoreboard.
* If not, puts the player into correct scoreboard and prints
* a warning.
* The only possible reason for this to happen is another plugin
* putting a player into a different scoreboard.
* Sadly there is no efficient solution to this, which md_5 fails
* to understand and keeps saying you don't need packets for scoreboards.
*/
private void checkPlayerScoreboard() {
if (player.getPlayer().getScoreboard() != scoreboard) {
player.getPlayer().setScoreboard(scoreboard);
TAB.getInstance().getErrorManager().printError("Player " + player.getName() + " was in a different scoreboard " +
"than expected. This means another plugin changed player's scoreboard.");
}
}
}
+111
View File
@@ -0,0 +1,111 @@
main: me.neznamy.tab.platforms.bukkit.BukkitTAB
name: @name@
version: @version@
description: @description@
api-version: 1.13 # Defining to avoid legacy plugin warn
load: POSTWORLD
author: @author@
website: "@website@"
depend: []
softdepend: [PlaceholderAPI, LuckPerms, LibsDisguises, ViaVersion, ViaRewind, floodgate]
loadbefore: []
prefix: TAB
libraries: []
folia-supported: true
commands:
tab:
description: Plugin's main command
permissions:
tab.admin:
description: Grants all TAB permissions
default: op
tab.tabcomplete:
description: Allows player to complete all TAB commands
default: op
tab.reload:
description: Allows player to run /tab reload
default: op
tab.cpu:
description: Allows player to run /tab cpu
default: op
tab.debug:
description: Allows player to run /tab debug [player]
default: op
tab.groupinfo:
description: Allows player to run /tab group <group>
default: op
tab.grouplist:
description: Allows player to run /tab groups
default: op
tab.parse:
description: Allows player to run /tab parse <player> <placeholder>
default: op
tab.setcollision:
description: Allows player to run /tab setcollision <player> <true/false>
default: op
tab.remove:
description: Allows player to remove group/user using commands
default: op
tab.change.*:
description: Allows player to change property using command
default: op
tab.width:
description: Allows player to run /tab width
default: op
tab.announce.bar:
description: Allows player to run /tab announce bar
default: op
tab.bossbar.toggle:
description: Allows player to run /tab bossbar
default: op
tab.send.bar:
description: Allows player to run /tab bossbar send
default: op
tab.mysql.download:
description: Allows player to run /tab mysql download
default: op
tab.mysql.upload:
description: Allows player to run /tab mysql upload
default: op
tab.nametag.toggle:
description: Allows player to run /tab nametag toggle
default: op
tab.nametag.toggle.other:
description: Allows player to run /tab nametag toggle [other player]
default: op
tab.nametag.preview:
description: Allows player to run /tab nametag preview
default: op
tab.nametag.preview.other:
description: Allows player to run /tab nametag preview [other player]
default: op
tab.announce.scoreboard:
description: Allows player to run /tab scoreboard announce
default: op
tab.scoreboard.toggle:
description: Allows player to run /tab scoreboard
default: op
tab.scoreboard.toggle.other:
description: Allows player to run /tab scoreboard for other players
default: op
tab.scoreboard.show:
description: Allows player to run /tab scoreboard show
default: op
tab.scoreboard.show.other:
description: Allows player to run /tab scoreboard show for other players
default: op
tab.staff:
description: Makes player counted in %staffonline% placeholder
default: op
tab.group.*:
description: Considers player in group if assigning by permissions
default: op
tab.bypass:
description: Makes player bypass per world playerlist if bypass permission is enabled
default: op
tab.seevanished:
description: Marks player as able to see vanished players for features hooking into vanish plugins
default: op
tab.spectatorbypass:
description: Makes player bypass spectator fix
default: op
+7
View File
@@ -0,0 +1,7 @@
dependencies {
implementation(projects.shared)
implementation("org.bstats:bstats-bungeecord:3.0.1")
compileOnly("net.md-5:bungeecord-proxy:1.20-R0.1-SNAPSHOT")
compileOnly("com.github.limework.redisbungee:RedisBungee-Bungee:0.11.0")
compileOnly("com.github.LeonMangler:PremiumVanishAPI:2.8.8")
}
@@ -0,0 +1,94 @@
package me.neznamy.tab.platforms.bungeecord;
import lombok.RequiredArgsConstructor;
import me.neznamy.tab.shared.platform.bossbar.BossBar;
import me.neznamy.tab.api.bossbar.BarColor;
import me.neznamy.tab.api.bossbar.BarStyle;
import me.neznamy.tab.shared.chat.IChatBaseComponent;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* BossBar handler for BungeeCord. It uses packets, since
* BungeeCord does not have a BossBar API. Only supports
* 1.9+ players, as dealing with entities would be simply impossible.
*/
@RequiredArgsConstructor
public class BungeeBossBar implements BossBar {
private final @NotNull BungeeTabPlayer player;
/** Both are included in the same action, need to remember and write them both */
private final Map<UUID, Integer> colors = new HashMap<>();
private final Map<UUID, Integer> styles = new HashMap<>();
@Override
public void create(@NotNull UUID id, @NotNull String title, float progress, @NotNull BarColor color, @NotNull BarStyle style) {
if (player.getVersion().getMinorVersion() < 9) return;
net.md_5.bungee.protocol.packet.BossBar packet = new net.md_5.bungee.protocol.packet.BossBar(id, 0);
packet.setHealth(progress);
packet.setTitle(IChatBaseComponent.optimizedComponent(title).toString(player.getVersion()));
packet.setColor(color.ordinal());
packet.setDivision(style.ordinal());
player.getPlayer().unsafe().sendPacket(packet);
colors.put(id, color.ordinal());
styles.put(id, style.ordinal());
}
@Override
public void update(@NotNull UUID id, @NotNull String title) {
if (player.getVersion().getMinorVersion() < 9) return;
net.md_5.bungee.protocol.packet.BossBar packet = new net.md_5.bungee.protocol.packet.BossBar(id, 3);
packet.setTitle(IChatBaseComponent.optimizedComponent(title).toString(player.getVersion()));
player.getPlayer().unsafe().sendPacket(packet);
}
@Override
public void update(@NotNull UUID id, float progress) {
if (player.getVersion().getMinorVersion() < 9) return;
net.md_5.bungee.protocol.packet.BossBar packet = new net.md_5.bungee.protocol.packet.BossBar(id, 2);
packet.setHealth(progress);
player.getPlayer().unsafe().sendPacket(packet);
}
@Override
public void update(@NotNull UUID id, @NotNull BarStyle style) {
if (player.getVersion().getMinorVersion() < 9) return;
net.md_5.bungee.protocol.packet.BossBar packet = new net.md_5.bungee.protocol.packet.BossBar(id, 4);
packet.setDivision(style.ordinal());
packet.setColor(colors.get(id));
player.getPlayer().unsafe().sendPacket(packet);
styles.put(id, style.ordinal());
}
@Override
public void update(@NotNull UUID id, @NotNull BarColor color) {
if (player.getVersion().getMinorVersion() < 9) return;
net.md_5.bungee.protocol.packet.BossBar packet = new net.md_5.bungee.protocol.packet.BossBar(id, 4);
packet.setDivision(styles.get(id));
packet.setColor(color.ordinal());
player.getPlayer().unsafe().sendPacket(packet);
colors.put(id, color.ordinal());
}
@Override
public void remove(@NotNull UUID id) {
if (player.getVersion().getMinorVersion() < 9) return;
player.getPlayer().unsafe().sendPacket(new net.md_5.bungee.protocol.packet.BossBar(id, 1));
colors.remove(id);
styles.remove(id);
}
}
@@ -0,0 +1,49 @@
package me.neznamy.tab.platforms.bungeecord;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.shared.platform.EventListener;
import me.neznamy.tab.shared.platform.TabPlayer;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.ChatEvent;
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
import net.md_5.bungee.api.event.PluginMessageEvent;
import net.md_5.bungee.api.event.ServerSwitchEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
/**
* The core for BungeeCord forwarding events into all enabled features
*/
public class BungeeEventListener extends EventListener<ProxiedPlayer> implements Listener {
@EventHandler
public void onQuit(PlayerDisconnectEvent e) {
quit(e.getPlayer().getUniqueId());
}
@EventHandler
public void onSwitch(ServerSwitchEvent e) {
serverChange(e.getPlayer(), e.getPlayer().getUniqueId(), e.getPlayer().getServer().getInfo().getName());
}
@EventHandler
public void onChat(ChatEvent e) {
if (e.isCommand() && command(((ProxiedPlayer)e.getSender()).getUniqueId(), e.getMessage())) {
e.setCancelled(true);
}
}
@EventHandler
public void on(PluginMessageEvent event) {
if (!event.getTag().equals(TabConstants.PLUGIN_MESSAGE_CHANNEL_NAME)) return;
if (event.getReceiver() instanceof ProxiedPlayer) {
event.setCancelled(true);
pluginMessage(((ProxiedPlayer) event.getReceiver()).getUniqueId(), event.getData());
}
}
@Override
public TabPlayer createPlayer(ProxiedPlayer player) {
return new BungeeTabPlayer(player);
}
}
@@ -0,0 +1,215 @@
package me.neznamy.tab.platforms.bungeecord;
import com.google.common.collect.Lists;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import java.lang.reflect.Field;
import me.neznamy.tab.shared.features.nametags.NameTag;
import me.neznamy.tab.shared.features.redis.RedisSupport;
import me.neznamy.tab.shared.features.redis.feature.RedisTeams;
import me.neznamy.tab.shared.platform.TabPlayer;
import me.neznamy.tab.shared.chat.IChatBaseComponent;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.shared.features.injection.NettyPipelineInjector;
import me.neznamy.tab.shared.features.redis.RedisPlayer;
import me.neznamy.tab.shared.features.sorting.Sorting;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.connection.InitialHandler;
import net.md_5.bungee.netty.ChannelWrapper;
import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.packet.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.function.Function;
import java.util.function.Supplier;
/**
* Pipeline injection to secure proper functionality
* of some features by preventing other plugins
* from overriding it.
*/
@SuppressWarnings("unchecked")
public class BungeePipelineInjector extends NettyPipelineInjector {
private static @Nullable Field wrapperField;
static {
try {
(wrapperField = InitialHandler.class.getDeclaredField("ch")).setAccessible(true);
} catch (ReflectiveOperationException exception) {
TAB.getInstance().getErrorManager().criticalError("Failed to initialize bungee internal fields", exception);
}
}
/** Packets used by the plugin that must be deserialized and BungeeCord does not do it automatically */
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};
@Override
public Function<TabPlayer, ChannelDuplexHandler> getChannelFunction() {
return byteBufDeserialization ? DeserializableBungeeChannelDuplexHandler::new : TabChannelDuplexHandler::new;
}
@Override
protected @Nullable Channel getChannel(@NotNull TabPlayer player) {
if (wrapperField == null) return null;
final BungeeTabPlayer bungee = (BungeeTabPlayer) player;
try {
return ((ChannelWrapper) wrapperField.get(bungee.getPlayer().getPendingConnection())).getHandle();
} catch (final IllegalAccessException exception) {
TAB.getInstance().getErrorManager().criticalError("Failed to get channel of " + bungee.getPlayer().getName(), exception);
}
return null;
}
@Override
public void onDisplayObjective(@NotNull TabPlayer player, @NotNull Object packet) {
TAB.getInstance().getFeatureManager().onDisplayObjective(player,
((ScoreboardDisplay) packet).getPosition(), ((ScoreboardDisplay) packet).getName());
}
@Override
public void onObjective(@NotNull TabPlayer player, @NotNull Object packet) {
TAB.getInstance().getFeatureManager().onObjective(player,
((ScoreboardObjective) packet).getAction(), ((ScoreboardObjective) packet).getName());
}
@Override
public boolean isDisplayObjective(@NotNull Object packet) {
return packet instanceof ScoreboardDisplay;
}
@Override
public boolean isObjective(@NotNull Object packet) {
return packet instanceof ScoreboardObjective;
}
@Override
public boolean isTeam(@NotNull Object packet) {
return packet instanceof Team;
}
@Override
public boolean isPlayerInfo(@NotNull Object packet) {
return packet instanceof PlayerListItem || packet instanceof PlayerListItemUpdate;
}
@Override
public void modifyPlayers(@NotNull Object team) {
if (TAB.getInstance().getNameTagManager() == null) return;
Team packet = (Team) team;
if (packet.getMode() == 1 || packet.getMode() == 2 || packet.getMode() == 4) return;
Collection<String> col = Lists.newArrayList(packet.getPlayers());
for (TabPlayer p : TAB.getInstance().getOnlinePlayers()) {
Sorting sorting = TAB.getInstance().getFeatureManager().getFeature(TabConstants.Feature.SORTING);
String expectedTeam = sorting.getShortTeamName(p);
if (expectedTeam != null && col.contains(p.getName()) &&
!((NameTag)TAB.getInstance().getNameTagManager()).getDisableChecker().isDisabledPlayer(p) &&
!TAB.getInstance().getNameTagManager().hasTeamHandlingPaused(p) && !packet.getName().equals(expectedTeam)) {
logTeamOverride(packet.getName(), p.getName(), expectedTeam);
col.remove(p.getName());
}
}
RedisSupport redis = TAB.getInstance().getFeatureManager().getFeature(TabConstants.Feature.REDIS_BUNGEE);
if (redis != null) {
RedisTeams teams = redis.getRedisTeams();
if (teams != null) {
for (RedisPlayer p : redis.getRedisPlayers().values()) {
if (col.contains(p.getName()) && !packet.getName().equals(teams.getTeamNames().get(p))) {
logTeamOverride(packet.getName(), p.getName(), teams.getTeamNames().get(p));
col.remove(p.getName());
}
}
}
}
packet.setPlayers(col.toArray(new String[0]));
}
@Override
public void onPlayerInfo(@NotNull TabPlayer receiver, @NotNull Object packet) {
if (packet instanceof PlayerListItemUpdate) {
PlayerListItemUpdate update = (PlayerListItemUpdate) packet;
for (PlayerListItem.Item item : update.getItems()) {
if (update.getActions().contains(PlayerListItemUpdate.Action.UPDATE_DISPLAY_NAME)) {
IChatBaseComponent newDisplayName = TAB.getInstance().getFeatureManager().onDisplayNameChange(receiver, item.getUuid());
if (newDisplayName != null) item.setDisplayName(newDisplayName.toString(receiver.getVersion()));
}
}
} else {
PlayerListItem listItem = (PlayerListItem) packet;
for (PlayerListItem.Item item : listItem.getItems()) {
if (listItem.getAction() == PlayerListItem.Action.UPDATE_DISPLAY_NAME || listItem.getAction() == PlayerListItem.Action.ADD_PLAYER) {
IChatBaseComponent newDisplayName = TAB.getInstance().getFeatureManager().onDisplayNameChange(receiver, item.getUuid());
if (newDisplayName != null) item.setDisplayName(newDisplayName.toString(receiver.getVersion()));
}
}
}
}
/**
* Constructs new instance of the feature
*/
public BungeePipelineInjector() {
super("inbound-boss");
}
/**
* Channel duplex handler override if features using packets that must be
* deserialized manually are used. If they are disabled, deserialization is
* disabled for better performance.
*/
public class DeserializableBungeeChannelDuplexHandler extends TabChannelDuplexHandler {
/**
* Constructs new instance with given player
*
* @param player
* player to inject
*/
public DeserializableBungeeChannelDuplexHandler(TabPlayer player) {
super(player);
}
@Override
public void write(ChannelHandlerContext context, Object packet, ChannelPromise channelPromise) {
long time = System.nanoTime();
Object modifiedPacket = packet instanceof ByteBuf ? deserialize((ByteBuf) packet) : packet;
TAB.getInstance().getCPUManager().addTime(TabConstants.Feature.PACKET_DESERIALIZING, TabConstants.CpuUsageCategory.BYTE_BUF, System.nanoTime()-time);
super.write(context, modifiedPacket, channelPromise);
}
/**
* Deserializes byte buf in case it is one of the tracked packets coming from backend server and returns it.
* If the packet is not one of them, returns input
*
* @param buf
* byte buf to deserialize
* @return deserialized packet or input byte buf if packet is not tracked
*/
private @NotNull Object deserialize(@NotNull ByteBuf buf) {
int marker = buf.readerIndex();
try {
int packetId = buf.readByte();
for (int i=0; i<extraPacketClasses.length; i++) {
if (packetId == ((BungeeTabPlayer)player).getPacketId(extraPacketClasses[i])) {
DefinedPacket packet = extraPacketSuppliers[i].get();
packet.read(buf, null, ((ProxiedPlayer)player.getPlayer()).getPendingConnection().getVersion());
buf.release();
return packet;
}
}
} catch (Exception e) {
//rare OverflowPacketException or IndexOutOfBoundsException
}
buf.readerIndex(marker);
return buf;
}
}
}
@@ -0,0 +1,54 @@
package me.neznamy.tab.platforms.bungeecord;
import com.imaginarycode.minecraft.redisbungee.RedisBungeeAPI;
import lombok.AllArgsConstructor;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.chat.IChatBaseComponent;
import me.neznamy.tab.shared.features.injection.PipelineInjector;
import me.neznamy.tab.shared.features.redis.RedisSupport;
import me.neznamy.tab.shared.proxy.ProxyPlatform;
import me.neznamy.tab.shared.util.ReflectionUtils;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* BungeeCord implementation of Platform
*/
@AllArgsConstructor
public class BungeePlatform extends ProxyPlatform {
@NotNull private final BungeeTAB plugin;
@Override
public @Nullable RedisSupport getRedisSupport() {
if (ReflectionUtils.classExists("com.imaginarycode.minecraft.redisbungee.RedisBungeeAPI") &&
RedisBungeeAPI.getRedisBungeeApi() != null) {
return new RedisBungeeSupport(plugin);
}
return null;
}
@Override
public void sendConsoleMessage(@NotNull IChatBaseComponent message) {
plugin.getLogger().info(message.toLegacyText());
}
@Override
public String getServerVersionInfo() {
return "[BungeeCord] " + plugin.getProxy().getName() + " - " + plugin.getProxy().getVersion();
}
@Override
public void loadPlayers() {
for (ProxiedPlayer p : ProxyServer.getInstance().getPlayers()) {
TAB.getInstance().addPlayer(new BungeeTabPlayer(p));
}
}
@Override
public @Nullable PipelineInjector createPipelineInjector() {
return new BungeePipelineInjector();
}
}
@@ -0,0 +1,102 @@
package me.neznamy.tab.platforms.bungeecord;
import me.neznamy.tab.shared.ProtocolVersion;
import me.neznamy.tab.shared.chat.EnumChatFormat;
import me.neznamy.tab.shared.chat.IChatBaseComponent;
import me.neznamy.tab.shared.platform.Scoreboard;
import net.md_5.bungee.protocol.packet.ScoreboardDisplay;
import net.md_5.bungee.protocol.packet.ScoreboardObjective;
import net.md_5.bungee.protocol.packet.ScoreboardScore;
import net.md_5.bungee.protocol.packet.Team;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
/**
* Scoreboard handler for BungeeCord. Because it does not offer
* any Scoreboard API and the scoreboard class it has is just a
* downstream tracker, we need to use packets.
*/
public class BungeeScoreboard extends Scoreboard<BungeeTabPlayer> {
public BungeeScoreboard(BungeeTabPlayer player) {
super(player);
}
@Override
public void setDisplaySlot(@NotNull DisplaySlot slot, @NotNull String objective) {
player.sendPacket(new ScoreboardDisplay((byte)slot.ordinal(), objective));
}
@Override
public void registerObjective0(@NotNull String objectiveName, @NotNull String title, boolean hearts) {
player.sendPacket(new ScoreboardObjective(objectiveName, jsonOrRaw(title, player.getVersion()), hearts ? ScoreboardObjective.HealthDisplay.HEARTS : ScoreboardObjective.HealthDisplay.INTEGER, (byte) 0));
}
@Override
public void unregisterObjective0(@NotNull String objectiveName) {
player.sendPacket(new ScoreboardObjective(objectiveName, "", null, (byte) 1)); // Empty string to prevent kick on 1.7
}
@Override
public void updateObjective0(@NotNull String objectiveName, @NotNull String title, boolean hearts) {
player.sendPacket(new ScoreboardObjective(objectiveName, jsonOrRaw(title, player.getVersion()), hearts ? ScoreboardObjective.HealthDisplay.HEARTS : ScoreboardObjective.HealthDisplay.INTEGER, (byte) 2));
}
@Override
public void registerTeam0(@NotNull String name, @NotNull String prefix, @NotNull String suffix, @NotNull NameVisibility visibility, @NotNull CollisionRule collision, @NotNull Collection<String> players, int options) {
int color = 0;
if (player.getVersion().getMinorVersion() >= 13) {
color = EnumChatFormat.lastColorsOf(prefix).ordinal();
}
player.sendPacket(new Team(name, (byte) 0, jsonOrRaw(name, player.getVersion()),
jsonOrRaw(prefix, player.getVersion()), jsonOrRaw(suffix, player.getVersion()),
visibility.toString(), collision.toString(), color, (byte)options, players.toArray(new String[0])));
}
@Override
public void unregisterTeam0(@NotNull String name) {
player.sendPacket(new Team(name));
}
@Override
public void updateTeam0(@NotNull String name, @NotNull String prefix, @NotNull String suffix, @NotNull NameVisibility visibility, @NotNull CollisionRule collision, int options) {
int color = 0;
if (player.getVersion().getMinorVersion() >= 13) {
color = EnumChatFormat.lastColorsOf(prefix).ordinal();
}
player.sendPacket(new Team(name, (byte) 2, jsonOrRaw(name, player.getVersion()),
jsonOrRaw(prefix, player.getVersion()), jsonOrRaw(suffix, player.getVersion()),
visibility.toString(), collision.toString(), color, (byte)options, null));
}
/**
* If {@code clientVersion} is &gt;= 1.13, creates a component from given text and returns
* it as a serialized component, which BungeeCord uses.
* <p>
* If {@code clientVersion} is &lt; 1.12, the text is returned
*
* @param text
* Text to convert
* @param clientVersion
* Version of player to convert text for
* @return serialized component for 1.13+ clients, cut string for 1.12-
*/
private String jsonOrRaw(@NotNull String text, @NotNull ProtocolVersion clientVersion) {
if (clientVersion.getMinorVersion() >= 13) {
return IChatBaseComponent.optimizedComponent(text).toString(clientVersion);
} else {
return text;
}
}
@Override
public void setScore0(@NotNull String objective, @NotNull String playerName, int score) {
player.sendPacket(new ScoreboardScore(playerName, (byte) 0, objective, score));
}
@Override
public void removeScore0(@NotNull String objective, @NotNull String playerName) {
player.sendPacket(new ScoreboardScore(playerName, (byte) 1, objective, 0));
}
}
@@ -0,0 +1,37 @@
package me.neznamy.tab.platforms.bungeecord;
import me.neznamy.tab.shared.ProtocolVersion;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.shared.chat.EnumChatFormat;
import me.neznamy.tab.shared.util.ReflectionUtils;
import net.md_5.bungee.api.plugin.Plugin;
import org.bstats.bungeecord.Metrics;
import org.bstats.charts.SimplePie;
/**
* Main class for BungeeCord platform
*/
public class BungeeTAB extends Plugin {
@Override
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;
}
getProxy().registerChannel(TabConstants.PLUGIN_MESSAGE_CHANNEL_NAME);
getProxy().getPluginManager().registerListener(this, new BungeeEventListener());
getProxy().getPluginManager().registerCommand(this, new BungeeTabCommand());
TAB.setInstance(new TAB(new BungeePlatform(this), ProtocolVersion.PROXY, getDataFolder()));
TAB.getInstance().load();
Metrics metrics = new Metrics(this, 10535);
metrics.addCustomChart(new SimplePie(TabConstants.MetricsChart.PERMISSION_SYSTEM, () -> TAB.getInstance().getGroupManager().getPermissionPlugin()));
metrics.addCustomChart(new SimplePie(TabConstants.MetricsChart.GLOBAL_PLAYER_LIST_ENABLED, () -> TAB.getInstance().getFeatureManager().isFeatureEnabled(TabConstants.Feature.GLOBAL_PLAYER_LIST) ? "Yes" : "No"));
}
@Override
public void onDisable() {
if (TAB.getInstance() != null) TAB.getInstance().unload();
}
}
@@ -0,0 +1,49 @@
package me.neznamy.tab.platforms.bungeecord;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.shared.chat.EnumChatFormat;
import me.neznamy.tab.shared.platform.TabPlayer;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Command;
import net.md_5.bungee.api.plugin.TabExecutor;
import java.util.ArrayList;
public class BungeeTabCommand extends Command implements TabExecutor {
/**
* Constructs new instance
*/
public BungeeTabCommand() {
super(TabConstants.COMMAND_PROXY, null);
}
@Override
public void execute(CommandSender sender, String[] args) {
if (TAB.getInstance().isPluginDisabled()) {
for (String message : TAB.getInstance().getDisabledCommand().execute(args, sender.hasPermission(TabConstants.Permission.COMMAND_RELOAD), sender.hasPermission(TabConstants.Permission.COMMAND_ALL))) {
sender.sendMessage(new TextComponent(EnumChatFormat.color(message)));
}
} else {
TabPlayer p = null;
if (sender instanceof ProxiedPlayer) {
p = TAB.getInstance().getPlayer(((ProxiedPlayer)sender).getUniqueId());
if (p == null) return; //player not loaded correctly
}
TAB.getInstance().getCommand().execute(p, args);
}
}
@Override
public Iterable<String> onTabComplete(CommandSender sender, String[] args) {
TabPlayer p = null;
if (sender instanceof ProxiedPlayer) {
p = TAB.getInstance().getPlayer(((ProxiedPlayer)sender).getUniqueId());
if (p == null) return new ArrayList<>(); //player not loaded correctly
}
return TAB.getInstance().getCommand().complete(p, args);
}
}
@@ -0,0 +1,161 @@
package me.neznamy.tab.platforms.bungeecord;
import de.myzelyam.api.vanish.BungeeVanishAPI;
import lombok.Getter;
import me.neznamy.tab.shared.ProtocolVersion;
import me.neznamy.tab.platforms.bungeecord.tablist.BungeeTabList1193;
import me.neznamy.tab.platforms.bungeecord.tablist.BungeeTabList17;
import me.neznamy.tab.platforms.bungeecord.tablist.BungeeTabList18;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.shared.chat.IChatBaseComponent;
import me.neznamy.tab.shared.platform.Scoreboard;
import me.neznamy.tab.shared.platform.TabList;
import me.neznamy.tab.shared.platform.bossbar.BossBar;
import me.neznamy.tab.shared.proxy.ProxyTabPlayer;
import me.neznamy.tab.shared.util.ReflectionUtils;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.chat.ComponentSerializer;
import net.md_5.bungee.connection.InitialHandler;
import net.md_5.bungee.connection.LoginResult;
import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.Property;
import net.md_5.bungee.protocol.Protocol;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Method;
/**
* TabPlayer implementation for BungeeCord
*/
public class BungeeTabPlayer extends ProxyTabPlayer {
/** Inaccessible bungee internals */
private static @Nullable Object directionData;
private static @Nullable Method getId;
/** Flag tracking plugin presence */
private static final boolean premiumVanish = ProxyServer.getInstance().getPluginManager().getPlugin("PremiumVanish") != null;
static {
try {
directionData = ReflectionUtils.setAccessible(Protocol.class.getDeclaredField("TO_CLIENT")).get(Protocol.GAME);
getId = ReflectionUtils.setAccessible(directionData.getClass().getDeclaredMethod("getId", Class.class, int.class));
} catch (ReflectiveOperationException e) {
TAB.getInstance().getErrorManager().criticalError("Failed to initialize bungee internal fields", e);
}
}
/** Player's scoreboard */
@Getter private final @NotNull Scoreboard<BungeeTabPlayer> scoreboard = new BungeeScoreboard(this);
/** Player's tab list based on version */
private final @NotNull TabList tabList1_7 = new BungeeTabList17(this);
private final @NotNull TabList tabList1_8 = new BungeeTabList18(this);
private final @NotNull TabList tabList1_19_3 = new BungeeTabList1193(this);
@Getter private final @NotNull BossBar bossBar = new BungeeBossBar(this);
/**
* Constructs new instance for given player
*
* @param p
* BungeeCord player
*/
public BungeeTabPlayer(@NotNull ProxiedPlayer p) {
super(p, p.getUniqueId(), p.getName(), p.getServer() != null ? p.getServer().getInfo().getName() : "-", -1);
}
@Override
public boolean hasPermission0(@NotNull String permission) {
return getPlayer().hasPermission(permission);
}
@Override
public int getPing() {
return getPlayer().getPing();
}
public void sendPacket(@NotNull Object nmsPacket) {
getPlayer().unsafe().sendPacket((DefinedPacket) nmsPacket);
}
@Override
public void sendMessage(@NotNull IChatBaseComponent message) {
getPlayer().sendMessage(ComponentSerializer.parse(message.toString(getVersion())));
}
@Override
public @Nullable TabList.Skin getSkin() {
LoginResult loginResult = ((InitialHandler)getPlayer().getPendingConnection()).getLoginProfile();
if (loginResult == null) return null;
Property[] properties = loginResult.getProperties();
if (properties == null || properties.length == 0) return null;
return new TabList.Skin(properties[0].getValue(), properties[0].getSignature());
}
@Override
public @NotNull ProxiedPlayer getPlayer() {
return (ProxiedPlayer) player;
}
/**
* Returns packet ID for this player of provided packet class
*
* @param clazz
* packet class
* @return packet ID
*/
public int getPacketId(@NotNull Class<? extends DefinedPacket> clazz) {
if (getId == null) return -1;
try {
return (int) getId.invoke(directionData, clazz, getPlayer().getPendingConnection().getVersion());
} catch (ReflectiveOperationException e) {
TAB.getInstance().getErrorManager().printError("Failed to get packet id for packet " + clazz +
" with client version " + getPlayer().getPendingConnection().getVersion(), e);
return -1;
}
}
/**
* If ViaVersion is installed on BungeeCord, it changes protocol to match version
* of server to which player is connected to. For that reason, we need to retrieve
* the field more often than just on join.
*
* @return Player's current protocol version
*/
@Override
public @NotNull ProtocolVersion getVersion() {
return ProtocolVersion.fromNetworkId(getPlayer().getPendingConnection().getVersion());
}
@Override
public boolean isVanished() {
//noinspection ConstantConditions
if (premiumVanish && BungeeVanishAPI.isInvisible(getPlayer())) return true;
return super.isVanished();
}
@Override
public boolean isOnline() {
return getPlayer().isConnected();
}
@Override
public @NotNull TabList getTabList() {
return getVersion().getNetworkId() >= ProtocolVersion.V1_19_3.getNetworkId() ?
tabList1_19_3 : getVersion().getMinorVersion() >= 8 ? tabList1_8 : tabList1_7;
}
@Override
public void sendPluginMessage(byte[] message) {
if (getPlayer().getServer() == null) {
TAB.getInstance().getErrorManager().printError("Skipped plugin message send to " + getName() + ", because player is not" +
"connected to any server (message=" + new String(message) + ")");
return;
}
getPlayer().getServer().sendData(TabConstants.PLUGIN_MESSAGE_CHANNEL_NAME, message);
}
}
@@ -0,0 +1,45 @@
package me.neznamy.tab.platforms.bungeecord;
import com.imaginarycode.minecraft.redisbungee.RedisBungeeAPI;
import com.imaginarycode.minecraft.redisbungee.events.PubSubMessageEvent;
import lombok.AllArgsConstructor;
import me.neznamy.tab.shared.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;
import org.jetbrains.annotations.NotNull;
/**
* Redis implementation for BungeeCord
*/
@AllArgsConstructor
public class RedisBungeeSupport extends RedisSupport implements Listener {
/** Plugin reference for registering listener */
private final @NotNull Plugin plugin;
@EventHandler
public void onMessage(@NotNull PubSubMessageEvent e) {
if (!e.getChannel().equals(TabConstants.REDIS_CHANNEL_NAME)) return;
processMessage(e.getMessage());
}
@Override
public void register() {
ProxyServer.getInstance().getPluginManager().registerListener(plugin, this);
RedisBungeeAPI.getRedisBungeeApi().registerPubSubChannels(TabConstants.REDIS_CHANNEL_NAME);
}
@Override
public void unregister() {
ProxyServer.getInstance().getPluginManager().unregisterListener(this);
RedisBungeeAPI.getRedisBungeeApi().unregisterPubSubChannels(TabConstants.REDIS_CHANNEL_NAME);
}
@Override
public void sendMessage(@NotNull String message) {
RedisBungeeAPI.getRedisBungeeApi().sendChannelMessage(TabConstants.REDIS_CHANNEL_NAME, message);
}
}
@@ -0,0 +1,91 @@
package me.neznamy.tab.platforms.bungeecord.tablist;
import lombok.RequiredArgsConstructor;
import me.neznamy.tab.platforms.bungeecord.BungeeTabPlayer;
import me.neznamy.tab.shared.chat.IChatBaseComponent;
import me.neznamy.tab.shared.platform.TabList;
import net.md_5.bungee.UserConnection;
import net.md_5.bungee.protocol.Property;
import net.md_5.bungee.protocol.packet.PlayerListItem.Item;
import net.md_5.bungee.protocol.packet.PlayerListItemRemove;
import net.md_5.bungee.protocol.packet.PlayerListItemUpdate;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.EnumSet;
import java.util.UUID;
/**
* TabList handler for 1.19.3+ players using the new tab list packets.
* Because BungeeCord does not have a TabList API, we need to use packets.
* They are sent using an internal BungeeCord method that keeps track of them,
* so they are removed on server switch to secure parity with Velocity.
*/
@RequiredArgsConstructor
public class BungeeTabList1193 implements TabList {
/** Player this TabList belongs to */
private final BungeeTabPlayer player;
@Override
public void removeEntry(@NotNull UUID entry) {
PlayerListItemRemove remove = new PlayerListItemRemove();
remove.setUuids(new UUID[]{entry});
((UserConnection)player.getPlayer()).getTabListHandler().onUpdate(remove);
}
@Override
public void updateDisplayName(@NotNull UUID entry, @Nullable IChatBaseComponent displayName) {
Item item = item(entry);
item.setDisplayName(displayName == null ? null : displayName.toString(player.getVersion()));
sendPacket(EnumSet.of(PlayerListItemUpdate.Action.UPDATE_DISPLAY_NAME), item);
}
@Override
public void updateLatency(@NotNull UUID entry, int latency) {
Item item = item(entry);
item.setPing(latency);
sendPacket(EnumSet.of(PlayerListItemUpdate.Action.UPDATE_LATENCY), item);
}
@Override
public void updateGameMode(@NotNull UUID entry, int gameMode) {
Item item = item(entry);
item.setGamemode(gameMode);
sendPacket(EnumSet.of(PlayerListItemUpdate.Action.UPDATE_GAMEMODE), item);
}
@Override
public void addEntry(@NotNull Entry entry) {
Item item = item(entry.getUniqueId());
if (entry.getDisplayName() != null) item.setDisplayName(entry.getDisplayName().toString(player.getVersion()));
item.setGamemode(entry.getGameMode());
item.setListed(true);
item.setPing(entry.getLatency());
if (entry.getSkin() != null) {
item.setProperties(new Property[]{new Property(TEXTURES_PROPERTY, entry.getSkin().getValue(), entry.getSkin().getSignature())});
} else {
item.setProperties(new Property[0]);
}
item.setUsername(entry.getName());
sendPacket(EnumSet.allOf(PlayerListItemUpdate.Action.class), item);
}
public @NotNull Item item(@NotNull UUID id) {
Item item = new Item();
item.setUuid(id);
return item;
}
private void sendPacket(@NotNull EnumSet<PlayerListItemUpdate.Action> actions, @NotNull Item item) {
PlayerListItemUpdate packet = new PlayerListItemUpdate();
packet.setActions(actions);
packet.setItems(new Item[]{item});
((UserConnection)player.getPlayer()).getTabListHandler().onUpdate(packet);
}
@Override
public void setPlayerListHeaderFooter(@NotNull IChatBaseComponent header, @NotNull IChatBaseComponent footer) {
player.getPlayer().setTabHeader(header.toBungeeComponent(player.getVersion()), footer.toBungeeComponent(player.getVersion()));
}
}
@@ -0,0 +1,93 @@
package me.neznamy.tab.platforms.bungeecord.tablist;
import lombok.RequiredArgsConstructor;
import me.neznamy.tab.platforms.bungeecord.BungeeTabPlayer;
import me.neznamy.tab.shared.chat.IChatBaseComponent;
import me.neznamy.tab.shared.platform.TabList;
import net.md_5.bungee.UserConnection;
import net.md_5.bungee.protocol.packet.PlayerListItem;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* TabList handler for 1.7 players, which has a completely different
* system. Entries are identified by display name, not uuids. Display
* names are changed by removing old entry and adding a new one, which
* requires further tracking than just the UUID.<p>
* Because BungeeCord does not have a TabList API, we need to use packets.
* They are sent using an internal BungeeCord method that keeps track of them,
* so they are removed on server switch to secure parity with Velocity.
* While BungeeCord itself does not support 1.7, some of its forks do.
* This was tested on FlameCord fork.
*/
@RequiredArgsConstructor
public class BungeeTabList17 implements TabList {
/** Player this TabList belongs to */
private final BungeeTabPlayer player;
/** Because entries are identified by names and not uuids on 1.7 */
private final Map<UUID, String> userNames = new HashMap<>();
private final Map<UUID, String> displayNames = new HashMap<>();
@Override
public void removeEntry(@NotNull UUID entry) {
if (!displayNames.containsKey(entry)) return; // Entry not tracked by TAB
update(PlayerListItem.Action.REMOVE_PLAYER, createItem(null, displayNames.get(entry), 0));
// Remove from map
userNames.remove(entry);
displayNames.remove(entry);
}
@Override
public void updateDisplayName(@NotNull UUID entry, @Nullable IChatBaseComponent displayName) {
if (!displayNames.containsKey(entry)) return; // Entry not tracked by TAB
update(PlayerListItem.Action.REMOVE_PLAYER, createItem(null, displayNames.get(entry), 0));
addEntry(new Entry.Builder(entry).displayName(displayName).name(userNames.get(entry)).build());
}
@Override
public void updateLatency(@NotNull UUID entry, int latency) {
if (!displayNames.containsKey(entry)) return; // Entry not tracked by TAB
update(PlayerListItem.Action.UPDATE_LATENCY, createItem(null, displayNames.get(entry), latency));
}
@Override
public void updateGameMode(@NotNull UUID entry, int gameMode) {/*Added in 1.8*/}
@Override
public void addEntry(@NotNull Entry entry) {
String displayNameString = entry.getDisplayName() == null ? String.valueOf(entry.getName()) : entry.getDisplayName().toLegacyText();
if (displayNameString.length() > 16) displayNameString = displayNameString.substring(0, 16); // 16 character limit
update(PlayerListItem.Action.ADD_PLAYER, createItem(entry.getName(), displayNameString, entry.getLatency()));
// Add to map
userNames.put(entry.getUniqueId(), entry.getName());
displayNames.put(entry.getUniqueId(), displayNameString);
}
private void update(@NotNull PlayerListItem.Action action, @NotNull PlayerListItem.Item item) {
PlayerListItem packet = new PlayerListItem();
packet.setAction(action);
packet.setItems(new PlayerListItem.Item[]{item});
((UserConnection)player.getPlayer()).getTabListHandler().onUpdate(packet);
}
private PlayerListItem.Item createItem(@Nullable String username, @NotNull String displayName, int latency) {
PlayerListItem.Item item = new PlayerListItem.Item();
item.setUsername(username);
item.setDisplayName(displayName);
item.setPing(latency);
return item;
}
@Override
public void setPlayerListHeaderFooter(@NotNull IChatBaseComponent header, @NotNull IChatBaseComponent footer) {
// Added in 1.8
}
}
@@ -0,0 +1,86 @@
package me.neznamy.tab.platforms.bungeecord.tablist;
import lombok.RequiredArgsConstructor;
import me.neznamy.tab.platforms.bungeecord.BungeeTabPlayer;
import me.neznamy.tab.shared.chat.IChatBaseComponent;
import me.neznamy.tab.shared.platform.TabList;
import net.md_5.bungee.UserConnection;
import net.md_5.bungee.protocol.Property;
import net.md_5.bungee.protocol.packet.PlayerListItem;
import net.md_5.bungee.protocol.packet.PlayerListItem.Item;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.UUID;
/**
* TabList handler for players between 1.8 and 1.19.2.<p>
* Because BungeeCord does not have a TabList API, we need to use packets.
* They are sent using an internal BungeeCord method that keeps track of them,
* so they are removed on server switch to secure parity with Velocity.
*/
@RequiredArgsConstructor
public class BungeeTabList18 implements TabList {
/** Player this TabList belongs to */
private final BungeeTabPlayer player;
@Override
public void removeEntry(@NotNull UUID entry) {
sendPacket(PlayerListItem.Action.REMOVE_PLAYER, item(entry));
}
@Override
public void updateDisplayName(@NotNull UUID entry, @Nullable IChatBaseComponent displayName) {
Item item = item(entry);
item.setDisplayName(displayName == null ? null : displayName.toString(player.getVersion()));
sendPacket(PlayerListItem.Action.UPDATE_DISPLAY_NAME, item);
}
@Override
public void updateLatency(@NotNull UUID entry, int latency) {
Item item = item(entry);
item.setPing(latency);
sendPacket(PlayerListItem.Action.UPDATE_LATENCY, item);
}
@Override
public void updateGameMode(@NotNull UUID entry, int gameMode) {
Item item = item(entry);
item.setGamemode(gameMode);
sendPacket(PlayerListItem.Action.UPDATE_GAMEMODE, item);
}
@Override
public void addEntry(@NotNull Entry entry) {
Item item = item(entry.getUniqueId());
if (entry.getDisplayName() != null) item.setDisplayName(entry.getDisplayName().toString(player.getVersion()));
item.setGamemode(entry.getGameMode());
item.setPing(entry.getLatency());
if (entry.getSkin() != null) {
item.setProperties(new Property[]{new Property(TEXTURES_PROPERTY, entry.getSkin().getValue(), entry.getSkin().getSignature())});
} else {
item.setProperties(new Property[0]);
}
item.setUsername(entry.getName());
sendPacket(PlayerListItem.Action.ADD_PLAYER, item);
}
public @NotNull Item item(@NotNull UUID id) {
Item item = new Item();
item.setUuid(id);
return item;
}
private void sendPacket(@NotNull PlayerListItem.Action action, @NotNull Item item) {
PlayerListItem packet = new PlayerListItem();
packet.setAction(action);
packet.setItems(new Item[]{item});
((UserConnection)player.getPlayer()).getTabListHandler().onUpdate(packet);
}
@Override
public void setPlayerListHeaderFooter(@NotNull IChatBaseComponent header, @NotNull IChatBaseComponent footer) {
player.getPlayer().setTabHeader(header.toBungeeComponent(player.getVersion()), footer.toBungeeComponent(player.getVersion()));
}
}
+7
View File
@@ -0,0 +1,7 @@
name: @name@
main: me.neznamy.tab.platforms.bungeecord.BungeeTAB
version: @version@
author: @author@
description: @description@
depends: []
softDepends: [RedisBungee, LuckPerms, PremiumVanish]
+78
View File
@@ -0,0 +1,78 @@
// Versions that don't require any code changes:
// 1.19.3, 1.19.4, 1.20, 1.20.1
val minecraftVersion = "1.20.1"
val v114 = "0.28.5+1.14"
val v115 = "0.28.5+1.15"
val v116 = "0.42.0+1.16"
val fabricApiVersions = mapOf(
"1.20.1" to "0.83.0+1.20.1",
"1.20" to "0.83.0+1.20",
"1.19.4" to "0.77.0+1.19.4",
"1.19.3" to "0.76.0+1.19.3",
"1.19.2" to "0.76.0+1.19.2",
"1.19.1" to "0.58.5+1.19.1",
"1.19" to "0.58.0+1.19",
"1.18.2" to "0.76.0+1.18.2",
"1.18.1" to "0.46.6+1.18",
"1.18" to "0.46.6+1.18",
"1.17.1" to "0.46.1+1.17",
"1.17" to "0.46.1+1.17",
"1.16.5" to v116,
"1.16.4" to v116,
"1.16.3" to v116,
"1.16.2" to v116,
"1.16.1" to v116,
"1.16" to v116,
"1.15.2" to v115,
"1.15.1" to v115,
"1.15" to v115,
"1.14.4" to v114,
"1.14.3" to v114,
"1.14.2" to v114,
"1.14.1" to v114,
"1.14" to v114,
)
plugins {
id("fabric-loom")
}
repositories {
// Gradle doesn't support combining settings and project repositories, so we have to re-declare all the settings repos we need
maven("https://repo.kryptonmc.org/releases")
maven("https://repo.opencollab.dev/maven-snapshots/")
maven("https://repo.viaversion.com/")
maven("https://oss.sonatype.org/content/repositories/snapshots")
}
dependencies {
implementation(projects.shared)
minecraft("com.mojang:minecraft:$minecraftVersion")
mappings(loom.officialMojangMappings())
modImplementation("net.fabricmc", "fabric-loader", "0.14.17")
modImplementation("me.lucko", "fabric-permissions-api", "0.2-SNAPSHOT")
modImplementation(fabricApi.module("fabric-api-base", fabricApiVersions[minecraftVersion]))
modImplementation(fabricApi.module("fabric-lifecycle-events-v1", fabricApiVersions[minecraftVersion]))
modImplementation(fabricApi.module("fabric-networking-api-v1", fabricApiVersions[minecraftVersion]))
modImplementation(fabricApi.module("fabric-entity-events-v1", fabricApiVersions[minecraftVersion]))
modImplementation(fabricApi.module("fabric-command-api-v${if (minecraftVersion.split(".")[1].toInt() >= 19) "2" else "1"}", fabricApiVersions[minecraftVersion]))
}
loom {
accessWidenerPath.set(file("src/main/resources/tab.accesswidener"))
}
tasks {
compileJava {
options.release.set(17)
}
validateAccessWidener {
// We don't want to validate the access wideners, as we have wideners for multiple versions, and the validation task will
// fail, as the classes for the old wideners don't exist in the new versions and vice versa.
enabled = false
}
}
@@ -0,0 +1,57 @@
package me.neznamy.tab.platforms.fabric;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import me.neznamy.tab.api.bossbar.BarColor;
import me.neznamy.tab.api.bossbar.BarStyle;
import me.neznamy.tab.shared.chat.IChatBaseComponent;
import me.neznamy.tab.shared.platform.bossbar.BossBar;
import net.minecraft.server.level.ServerBossEvent;
import net.minecraft.world.BossEvent;
import org.jetbrains.annotations.NotNull;
@RequiredArgsConstructor
public class FabricBossBar implements BossBar {
private final FabricTabPlayer player;
private final Map<UUID, ServerBossEvent> bars = new HashMap<>();
@Override
public void create(@NotNull UUID id, @NotNull String title, float progress, @NotNull BarColor color, @NotNull BarStyle style) {
ServerBossEvent bar = new ServerBossEvent(
FabricTAB.getInstance().toComponent(IChatBaseComponent.optimizedComponent(title), player.getVersion()),
BossEvent.BossBarColor.valueOf(color.name()),
BossEvent.BossBarOverlay.valueOf(style.name())
);
bar.setProgress(progress);
bars.put(id, bar);
bar.addPlayer(player.getPlayer());
}
@Override
public void update(@NotNull UUID id, @NotNull String title) {
bars.get(id).setName(FabricTAB.getInstance().toComponent(IChatBaseComponent.optimizedComponent(title), player.getVersion()));
}
@Override
public void update(@NotNull UUID id, float progress) {
bars.get(id).setProgress(progress);
}
@Override
public void update(@NotNull UUID id, @NotNull BarStyle style) {
bars.get(id).setOverlay(BossEvent.BossBarOverlay.valueOf(style.name()));
}
@Override
public void update(@NotNull UUID id, @NotNull BarColor color) {
bars.get(id).setColor(BossEvent.BossBarColor.valueOf(color.name()));
}
@Override
public void remove(@NotNull UUID id) {
bars.remove(id).removePlayer(player.getPlayer());
}
}
@@ -0,0 +1,23 @@
package me.neznamy.tab.platforms.fabric;
import me.neznamy.tab.shared.platform.EventListener;
import me.neznamy.tab.shared.platform.TabPlayer;
import net.fabricmc.fabric.api.entity.event.v1.ServerPlayerEvents;
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
import net.minecraft.server.level.ServerPlayer;
public class FabricEventListener extends EventListener<ServerPlayer> {
public void register() {
ServerPlayConnectionEvents.JOIN.register((connection, $, $$) -> join(connection.player));
ServerPlayConnectionEvents.DISCONNECT.register((connection, $) -> quit(connection.player.getUUID()));
ServerPlayerEvents.AFTER_RESPAWN.register((oldPlayer, newPlayer, alive) -> replacePlayer(oldPlayer.getUUID(), newPlayer));
}
@Override
public TabPlayer createPlayer(ServerPlayer player) {
return new FabricTabPlayer(player);
}
//TODO world switch
}
@@ -0,0 +1,16 @@
package me.neznamy.tab.platforms.fabric;
import me.neznamy.tab.api.placeholder.PlaceholderManager;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.shared.placeholders.UniversalPlaceholderRegistry;
import net.minecraft.server.level.ServerPlayer;
import org.jetbrains.annotations.NotNull;
public class FabricPlaceholderRegistry extends UniversalPlaceholderRegistry {
@Override
public void registerPlaceholders(@NotNull PlaceholderManager manager) {
manager.registerPlayerPlaceholder(TabConstants.Placeholder.HEALTH, 100, p -> (int) Math.ceil(((ServerPlayer) p.getPlayer()).getHealth()));
super.registerPlaceholders(manager);
}
}
@@ -0,0 +1,66 @@
package me.neznamy.tab.platforms.fabric;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.backend.BackendPlatform;
import me.neznamy.tab.shared.chat.IChatBaseComponent;
import me.neznamy.tab.shared.features.injection.PipelineInjector;
import me.neznamy.tab.shared.features.nametags.NameTag;
import me.neznamy.tab.shared.features.types.TabFeature;
import me.neznamy.tab.shared.placeholders.expansion.EmptyTabExpansion;
import me.neznamy.tab.shared.placeholders.expansion.TabExpansion;
import net.fabricmc.fabric.api.networking.v1.PlayerLookup;
import net.minecraft.SharedConstants;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public final class FabricPlatform implements BackendPlatform {
@Override
public void registerUnknownPlaceholder(@NotNull String identifier) {
TAB.getInstance().getPlaceholderManager().registerServerPlaceholder(identifier, -1, () -> identifier);
}
@Override
public void loadPlayers() {
for (ServerPlayer player : PlayerLookup.all(FabricTAB.getInstance().getServer())) {
TAB.getInstance().addPlayer(new FabricTabPlayer(player));
}
}
@Override
public void registerPlaceholders() {
new FabricPlaceholderRegistry().registerPlaceholders(TAB.getInstance().getPlaceholderManager());
}
@Override
public @NotNull NameTag getUnlimitedNameTags() {
return new NameTag();
}
@Override
public @Nullable PipelineInjector createPipelineInjector() {
return null;
}
@Override
public @NotNull TabExpansion createTabExpansion() {
return new EmptyTabExpansion();
}
@Override
public @Nullable TabFeature getPerWorldPlayerList() {
return null;
}
@Override
public void sendConsoleMessage(@NotNull IChatBaseComponent message) {
MinecraftServer.LOGGER.info("[TAB] " + message.toRawText());
}
@Override
public String getServerVersionInfo() {
return "[Fabric] " + SharedConstants.getCurrentVersion().getName();
}
}
@@ -0,0 +1,136 @@
package me.neznamy.tab.platforms.fabric;
import java.util.Collection;
import java.util.Objects;
import me.neznamy.tab.shared.chat.EnumChatFormat;
import me.neznamy.tab.shared.chat.IChatBaseComponent;
import me.neznamy.tab.shared.platform.Scoreboard;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.game.ClientboundSetDisplayObjectivePacket;
import net.minecraft.network.protocol.game.ClientboundSetObjectivePacket;
import net.minecraft.network.protocol.game.ClientboundSetPlayerTeamPacket;
import net.minecraft.network.protocol.game.ClientboundSetScorePacket;
import net.minecraft.server.ServerScoreboard;
import net.minecraft.world.scores.Objective;
import net.minecraft.world.scores.PlayerTeam;
import net.minecraft.world.scores.Team;
import net.minecraft.world.scores.criteria.ObjectiveCriteria;
import org.jetbrains.annotations.NotNull;
public class FabricScoreboard extends Scoreboard<FabricTabPlayer> {
private final @NotNull net.minecraft.world.scores.Scoreboard dummyScoreboard = new net.minecraft.world.scores.Scoreboard();
private final @NotNull Component EMPTY_COMPONENT = Objects.requireNonNull(Component.Serializer.fromJson(IChatBaseComponent.EMPTY_COMPONENT));
public FabricScoreboard(FabricTabPlayer player) {
super(player);
}
@Override
public void setDisplaySlot(@NotNull DisplaySlot slot, @NotNull String objective) {
player.sendPacket(
new ClientboundSetDisplayObjectivePacket(
slot.ordinal(),
new Objective(
dummyScoreboard,
objective,
ObjectiveCriteria.DUMMY,
EMPTY_COMPONENT,
ObjectiveCriteria.RenderType.INTEGER
)
)
);
}
@Override
public void registerObjective0(@NotNull String objectiveName, @NotNull String title, boolean hearts) {
player.sendPacket(
new ClientboundSetObjectivePacket(
new Objective(
dummyScoreboard,
objectiveName,
ObjectiveCriteria.DUMMY,
FabricTAB.getInstance().toComponent(IChatBaseComponent.optimizedComponent(title), player.getVersion()),
hearts ? ObjectiveCriteria.RenderType.HEARTS : ObjectiveCriteria.RenderType.INTEGER
),
0
)
);
}
@Override
public void unregisterObjective0(@NotNull String objectiveName) {
player.sendPacket(
new ClientboundSetObjectivePacket(
new Objective(
dummyScoreboard,
objectiveName,
ObjectiveCriteria.DUMMY,
EMPTY_COMPONENT,
ObjectiveCriteria.RenderType.INTEGER
),
1
)
);
}
@Override
public void updateObjective0(@NotNull String objectiveName, @NotNull String title, boolean hearts) {
player.sendPacket(
new ClientboundSetObjectivePacket(
new Objective(
dummyScoreboard,
objectiveName,
ObjectiveCriteria.DUMMY,
FabricTAB.getInstance().toComponent(IChatBaseComponent.optimizedComponent(title), player.getVersion()),
hearts ? ObjectiveCriteria.RenderType.HEARTS : ObjectiveCriteria.RenderType.INTEGER
),
2
)
);
}
@Override
public void registerTeam0(@NotNull String name, @NotNull String prefix, @NotNull String suffix, @NotNull NameVisibility visibility, @NotNull CollisionRule collision, @NotNull Collection<String> players, int options) {
PlayerTeam team = new PlayerTeam(dummyScoreboard, name);
team.setAllowFriendlyFire((options & 0x01) > 0);
team.setSeeFriendlyInvisibles((options & 0x02) > 0);
team.setColor(ChatFormatting.valueOf(EnumChatFormat.lastColorsOf(prefix).name()));
team.setCollisionRule(Team.CollisionRule.valueOf(collision.name()));
team.setNameTagVisibility(Team.Visibility.valueOf(visibility.name()));
team.setPlayerPrefix(FabricTAB.getInstance().toComponent(IChatBaseComponent.optimizedComponent(prefix), player.getVersion()));
team.setPlayerSuffix(FabricTAB.getInstance().toComponent(IChatBaseComponent.optimizedComponent(suffix), player.getVersion()));
team.getPlayers().addAll(players);
player.sendPacket(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(team, true));
}
@Override
public void unregisterTeam0(@NotNull String name) {
player.sendPacket(ClientboundSetPlayerTeamPacket.createRemovePacket(new PlayerTeam(dummyScoreboard, name)));
}
@Override
public void updateTeam0(@NotNull String name, @NotNull String prefix, @NotNull String suffix, @NotNull NameVisibility visibility, @NotNull CollisionRule collision, int options) {
PlayerTeam team = new PlayerTeam(dummyScoreboard, name);
team.setAllowFriendlyFire((options & 0x01) > 0);
team.setSeeFriendlyInvisibles((options & 0x02) > 0);
team.setColor(ChatFormatting.valueOf(EnumChatFormat.lastColorsOf(prefix).name()));
team.setCollisionRule(Team.CollisionRule.valueOf(collision.name()));
team.setNameTagVisibility(Team.Visibility.valueOf(visibility.name()));
team.setPlayerPrefix(FabricTAB.getInstance().toComponent(IChatBaseComponent.optimizedComponent(prefix), player.getVersion()));
team.setPlayerSuffix(FabricTAB.getInstance().toComponent(IChatBaseComponent.optimizedComponent(suffix), player.getVersion()));
player.sendPacket(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(team, false));
}
@Override
public void setScore0(@NotNull String objective, @NotNull String playerName, int score) {
player.sendPacket(new ClientboundSetScorePacket(ServerScoreboard.Method.CHANGE, objective, playerName, score));
}
@Override
public void removeScore0(@NotNull String objective, @NotNull String playerName) {
player.sendPacket(new ClientboundSetScorePacket(ServerScoreboard.Method.REMOVE, objective, playerName, 0));
}
}
Loaded 100 of 556 files, more files were not shown because too many files have changed in this diff. Show more