mirror of
https://github.com/NEZNAMY/TAB.git
synced 2026-11-12 20:22:01 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6d295960d5 | ||
|
|
983d6a055b | ||
|
|
9de3fc4bbb | ||
|
|
f4c986f0de | ||
|
|
434f629c0b | ||
|
|
dac32b6daf | ||
|
|
dd845013ce | ||
|
|
b9bad50dbd | ||
|
|
56540df419 | ||
|
|
d0b0c55ab8 | ||
|
|
6f2b92e044 | ||
|
|
5da16e8055 | ||
|
|
a522ea9902 | ||
|
|
36801184a5 | ||
|
|
d212eb108d | ||
|
|
cbc1de0f33 | ||
|
|
fcdc04e228 | ||
|
|
890f1ee131 | ||
|
|
f3aec47ac3 | ||
|
|
bcf1c828b5 | ||
|
|
5fd319a152 | ||
|
|
abecb58a8d | ||
|
|
135166b01e | ||
|
|
0770293452 | ||
|
|
f3c40ad582 | ||
|
|
aacc115a36 | ||
|
|
b7ba07b78d | ||
|
|
e13445f55d | ||
|
|
bd527d3868 | ||
|
|
f288112eb2 | ||
|
|
6b415e64a8 | ||
|
|
cfb2cb6b0a |
No files matched your search
@@ -5,9 +5,9 @@ The compact configuration allows you to get the plugin to work the way you want
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Badge_Release.svg[/IMG]
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Badge_Minecraft.svg[/IMG]
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Badge_Java.svg[/IMG]
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Badge_SourceCode.svg[/IMG]
|
||||
[URL='https://github.com/NEZNAMY/TAB'][IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Badge_SourceCode.svg[/IMG][/URL]
|
||||
[URL='https://github.com/NEZNAMY/TAB/issues'][IMG]https://img.shields.io/github/issues/neznamy/tab?label=Issues[/IMG][/URL]
|
||||
[IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Badge_Documentation.svg[/IMG]
|
||||
[URL='https://github.com/NEZNAMY/TAB/wiki'][IMG]https://raw.githubusercontent.com/NEZNAMY/TAB/master/.github/description/images/Badge_Documentation.svg[/IMG][/URL]
|
||||
[CENTER][B][SIZE=7]Discord?[/SIZE][/B][/CENTER]
|
||||
Official support by me is no longer provided to free users due to limited time and extreme inefficiency (see [URL='https://github.com/NEZNAMY/TAB?tab=readme-ov-file#provided-services']provided services[/URL] for more info).
|
||||
However, you can join this [URL='https://discord.gg/YPqXt63YQj']fresh new community discord[/URL] made by a nice person who promises to help everyone with all plugins, including TAB.
|
||||
|
||||
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="138" height="20" role="img" aria-label="Minecraft: 1.5 - 1.21.5"><title>Minecraft: 1.5 - 1.21.5</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="138" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="61" height="20" fill="#555"/><rect x="61" width="77" height="20" fill="#007ec6"/><rect width="138" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="315" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="510">Minecraft</text><text x="315" y="140" transform="scale(.1)" fill="#fff" textLength="510">Minecraft</text><text aria-hidden="true" x="985" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="670">1.5 - 1.21.5</text><text x="985" y="140" transform="scale(.1)" fill="#fff" textLength="670">1.5 - 1.21.5</text></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="138" height="20" role="img" aria-label="Minecraft: 1.5 - 1.21.7"><title>Minecraft: 1.5 - 1.21.7</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="138" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="61" height="20" fill="#555"/><rect x="61" width="77" height="20" fill="#007ec6"/><rect width="138" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="315" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="510">Minecraft</text><text x="315" y="140" transform="scale(.1)" fill="#fff" textLength="510">Minecraft</text><text aria-hidden="true" x="985" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="670">1.5 - 1.21.7</text><text x="985" y="140" transform="scale(.1)" fill="#fff" textLength="670">1.5 - 1.21.7</text></g></svg>
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="92" height="20" role="img" aria-label="Release: 5.2.1"><title>Release: 5.2.1</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="92" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="53" height="20" fill="#555"/><rect x="53" width="39" height="20" fill="#007ec6"/><rect width="92" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="275" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">Release</text><text x="275" y="140" transform="scale(.1)" fill="#fff" textLength="430">Release</text><text aria-hidden="true" x="715" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="290">5.2.1</text><text x="715" y="140" transform="scale(.1)" fill="#fff" textLength="290">5.2.1</text></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="92" height="20" role="img" aria-label="Release: 5.2.4"><title>Release: 5.2.4</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="92" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="53" height="20" fill="#555"/><rect x="53" width="39" height="20" fill="#007ec6"/><rect width="92" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="275" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">Release</text><text x="275" y="140" transform="scale(.1)" fill="#fff" textLength="430">Release</text><text aria-hidden="true" x="715" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="290">5.2.4</text><text x="715" y="140" transform="scale(.1)" fill="#fff" textLength="290">5.2.4</text></g></svg>
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
@@ -274,10 +274,10 @@ if __name__ == "__main__":
|
||||
]
|
||||
)
|
||||
|
||||
release = "5.2.1"
|
||||
release = "5.2.4"
|
||||
download_image(f"https://img.shields.io/badge/Release-{release}-blue.svg", "Badge_Release.svg")
|
||||
|
||||
minecraft = "1.5 - 1.21.5".replace(" ", "%20").replace("-", "--")
|
||||
minecraft = "1.5 - 1.21.7".replace(" ", "%20").replace("-", "--")
|
||||
download_image(f"https://img.shields.io/badge/Minecraft-{minecraft}-blue.svg", "Badge_Minecraft.svg")
|
||||
|
||||
java = "8+"
|
||||
|
||||
@@ -35,7 +35,7 @@ TAB's shared module is compiled with Java 8. For the platforms themselves, TAB d
|
||||
<tr>
|
||||
<td rowspan=2>Vanilla</td>
|
||||
<td rowspan=1><a href="https://getbukkit.org/">Bukkit</a> (+forge hybrids)</td>
|
||||
<td>✔ (1.5 - 1.21.5)</td>
|
||||
<td>✔ (1.5 - 1.21.7)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=1><a href="https://www.spongepowered.org/">Sponge</a></td>
|
||||
@@ -46,33 +46,33 @@ TAB's shared module is compiled with Java 8. For the platforms themselves, TAB d
|
||||
<tr>
|
||||
<td rowspan=3>Modded</td>
|
||||
<td rowspan=1><a href="https://fabricmc.net">Fabric</a></td>
|
||||
<td>✔ (1.21.4 - 1.21.5)</td>
|
||||
<td>✔ (1.21.6 - 1.21.7)<sup>1</sup></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=1><a href="https://minecraftforge.net">Forge</a></td>
|
||||
<td>✔ (1.21.4 - 1.21.5)</td>
|
||||
<td>✔ (1.21.6 - 1.21.7)<sup>1</sup></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=1><a href="https://neoforged.net/">NeoForge</a></td>
|
||||
<td>✔ (1.21.4 - 1.21.5)</td>
|
||||
<td>✔ (1.21.6 - 1.21.7)<sup>1</sup></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td rowspan=2>Proxies</td>
|
||||
<td rowspan=1><a href="https://ci.md-5.net/job/BungeeCord/">BungeeCord</a></td>
|
||||
<td>✔ (latest only<sup>1</sup>)</td>
|
||||
<td>✔ (latest only)<sup>2</sup></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=1><a href="https://www.velocitypowered.com/">Velocity</a></td>
|
||||
<td>✔ (latest only<sup>1</sup>)</td>
|
||||
<td>✔ (latest only)<sup>2</sup></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
Modded platforms only support the latest MC version(s). For older MC versions try [modrinth](https://modrinth.com/plugin/tab-was-taken)'s version download filter.
|
||||
<sup>1</sup> Modded platforms only support the latest MC version(s). For older MC versions try [modrinth](https://modrinth.com/plugin/tab-was-taken)'s version download filter. If your desired version is not available, you may request it.
|
||||
|
||||
<sup>1</sup> Latest only doesn't mean only the latest build will work,
|
||||
<sup>2</sup> Latest only doesn't mean only the latest build will work,
|
||||
it means the plugin was made to be compatible with the latest version/build.
|
||||
Since breaking changes don't happen too often, it means a wide range of versions is usually supported.
|
||||
When a breaking change occurs, the plugin is updated to support the new version,
|
||||
|
||||
@@ -35,7 +35,7 @@ For Maven users, you can add the API dependency like this:
|
||||
<dependency>
|
||||
<groupId>com.github.NEZNAMY</groupId>
|
||||
<artifactId>TAB-API</artifactId>
|
||||
<version>5.2.1</version>
|
||||
<version>5.2.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
@@ -50,7 +50,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly 'com.github.NEZNAMY:TAB-API:5.2.1'
|
||||
compileOnly 'com.github.NEZNAMY:TAB-API:5.2.4'
|
||||
}
|
||||
```
|
||||
|
||||
@@ -61,7 +61,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly("com.github.NEZNAMY", "TAB-API", "5.2.1")
|
||||
compileOnly("com.github.NEZNAMY", "TAB-API", "5.2.4")
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -79,6 +79,7 @@ If you want health to display health as 0-10 instead of 0-20, you can achieve it
|
||||
# Limitations
|
||||
* [1.5 - 1.12.2] Title length is limited to 32 characters (including color codes).
|
||||
* [1.5 - 1.20.2] `value` is limited to a white number.
|
||||
* [Bedrock] Doesn't support 1.20.3+ features (`fancy-value`), `value` will be displayed instead, just like on <1.20.3
|
||||
* The format is a **[score] + space + shared title**. No, the space cannot be removed.
|
||||
* The title is the same on all players, therefore, it cannot be personalized (such as player's faction). Only [score] can be per-player.
|
||||
* It appears on all entities of player type. **This includes player NPCs.**
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Content
|
||||
* [About](#about)
|
||||
* [Condition types](#condition-types)
|
||||
* [Number comparations](#number-comparations)
|
||||
* [Number comparisons](#number-comparisons)
|
||||
* [Text operations](#text-operations)
|
||||
* [Permission](#permission)
|
||||
* [Multiple condition requirements](#multiple-condition-requirements)
|
||||
@@ -15,6 +15,7 @@
|
||||
* [Examples](#examples)
|
||||
* [Example 1 - Chaining conditional placeholders](#example-1---chaining-conditional-placeholders)
|
||||
* [Example 2 - Conditions in conditions](#example-2---conditions-in-conditions)
|
||||
* [Example 3 - Negating expressions](#example-3---negating-expressions)
|
||||
|
||||
# About
|
||||
Conditions / conditional placeholders allow you
|
||||
@@ -24,7 +25,7 @@ They have 2 main uses in the plugin:
|
||||
* Conditional placeholders which return defined outputs in both cases if the condition passes or fails
|
||||
|
||||
# Condition types
|
||||
## Number comparations
|
||||
## Number comparisons
|
||||
| Operation | Description | Example |
|
||||
|-----------|--------------------------|--------------------------------------------------------------------------------|
|
||||
| `>=` | Greater than or equal to | `%ping%>=100` will pass if the player's ping is greater than or equal to `100` |
|
||||
@@ -188,7 +189,7 @@ conditions:
|
||||
Finally, we can use this ping placeholder using `%condition:ping%`.
|
||||
This example chained 2 conditions, but more can be used. There is no limit.
|
||||
|
||||
# Example 2 - Conditions in conditions
|
||||
## Example 2 - Conditions in conditions
|
||||
If you want to use a condition in another one,
|
||||
for example, to use both "AND" and "OR" types, create 2 conditions and use one in the other one.
|
||||
For example, if we want to check that player is in server `lobby` **and** in worlds **either** `world1` or `world2`,
|
||||
@@ -206,4 +207,35 @@ conditions:
|
||||
- "%server%=lobby"
|
||||
type: AND
|
||||
```
|
||||
Then, use condition `main` as the display condition. Note that `yes`/`no` values were not defined, as such, they default to `true` and `false`, respectively. Therefore, we use the placeholder from the condition and check if the result is `true`. Then, check if player is also in the specified server.
|
||||
Then, use condition `main` as the display condition. Note that `yes`/`no` values were not defined, as such, they default to `true` and `false`, respectively. Therefore, we use the placeholder from the condition and check if the result is `true`. Then, check if player is also in the specified server.
|
||||
|
||||
## Example 3 - Negating expressions
|
||||
Most condition types contain their opposites, such as:
|
||||
* `=` -> `!=`
|
||||
* `permission:` -> `!permission:`
|
||||
* `>=` -> `<`
|
||||
* `>` -> `<=`
|
||||
|
||||
However, some of them don't, as things could get too complicated. This includes:
|
||||
* `|-` starts with
|
||||
* `-|` ends with
|
||||
* `<-` contains
|
||||
|
||||
You can achieve this by creating a full condition and check if it returned false.
|
||||
**Example:**
|
||||
Original:
|
||||
```
|
||||
display-condition: "%server%|-lobby"
|
||||
```
|
||||
Negated:
|
||||
```
|
||||
conditions:
|
||||
lobby:
|
||||
conditions:
|
||||
- "%server%|-lobby"
|
||||
```
|
||||
...
|
||||
```
|
||||
display-condition: "%condition:lobby%=false"
|
||||
```
|
||||
This way, the display condition will pass if the nested condition returned `false` (player is not in any lobby).
|
||||
@@ -4,6 +4,7 @@
|
||||
* [Groups and users](#groups-and-users)
|
||||
* [Per-world / per-server](#per-world--per-server)
|
||||
* [Priority system](#priority-system)
|
||||
* [Name color](#name-color)
|
||||
* [Placeholder support](#placeholder-support)
|
||||
* [Additional settings](#additional-settings)
|
||||
* [Tips & Tricks](#tips--tricks)
|
||||
@@ -115,6 +116,13 @@ This means you can set per-world tagprefix, but only keep one global tagsuffix,
|
||||
You can see the source of a value displayed on player by using `/tab debug <player>` and checking "source"
|
||||
part of the value you are looking for.
|
||||
|
||||
## Name color
|
||||
On versions 1.12.2 and below, name color follows the last color of prefix. This also includes magic codes. On 1.13+, this is no longer the case. Instead, a new field called "team color" was created. This is an enum constant, where we need to pick from 22 options - 16 colors, 5 magic codes and reset. **As you can see, it doesn't allow for RGB colors**. This also means name can no longer have color and magic codes simultaneously.
|
||||
|
||||
TAB does not have an option for configuring team color to avoid complexity, such as per-version configuration, or having to configure an additional field, while people are used to putting some color code at the end of prefix and expect the name to take it. For that reason, TAB detects the last used color code and uses that for team color.
|
||||
> [!CAUTION]
|
||||
> An exception is when using MiniMessage syntax / using RGB codes on server which has MiniMessage library. In this scenario, it is not possible to detect reset (`&r`) as last used "color", because in minecraft components it is not a color, rather, it resets formatting by setting all magic codes to false / color to null. If you use `&r` (`<reset>`) and notice it not working, replace it with `&f` (`<white>`) (or add it after the reset to be safe). There seems to be no difference between setting color to `WHITE` versus `RESET`.
|
||||
|
||||
## Placeholder support
|
||||
All values fully support [TAB's internal placeholders](https://github.com/NEZNAMY/TAB/wiki/Placeholders#internal-placeholders) and [PlaceholderAPI placeholders](https://github.com/PlaceholderAPI/PlaceholderAPI/wiki/Placeholders) including relational placeholders.
|
||||
The number of placeholders is not limited, and they can be used in combination with static text as well.
|
||||
@@ -125,7 +133,6 @@ The number of placeholders is not limited, and they can be used in combination w
|
||||
| enabled | true | Enables / Disables the feature |
|
||||
| enable-collision | true | Controls collision rule. Available values are: <br />- `true` - Collision will be enabled permanently. <br />- `false` - Collision will be disabled permanently. <br /> - *Conditional expression* - Collision will be enabled if player meets the condition (for example `%world%=world` will result in collision only being enabled for players in world `world`). <br /> - *Condition name* - Uses name of a [defined condition](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders) that must be met for a player to have collision enabled. |
|
||||
| invisible-nametags | false | When enabled, everyone will have invisible nametag all the time. Option to hide nametags was added in minecraft **1.8**, therefore it will not work on 1.7 and lower. |
|
||||
| anti-override | true | While enabled, prevents other plugins from assigning online players into teams and making TAB not work correctly. They should be configured to not use teams, however many users fail to disable features in other plugins that they don't want, making this option required. Some plugins don't even say they use teams to achieve their goals. Did you know even Paper uses teams? |
|
||||
| can-see-friendly-invisibles | false | Controlling value of the team flag. It allows you to see invisible players in the same team as transparent instead of completely invisible. Since TAB places each player into an individual team, this option will only take effect in combination with plugins that spawn a dummy clone of the player (sit or disguise plugins). |
|
||||
| disable-condition | %world%=disabledworld | A [condition](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders) that must be met for disabling the feature for players. Set to empty for not disabling the feature ever. |
|
||||
|
||||
@@ -154,7 +161,7 @@ To avoid it, make their names not match any online player and use holograms to d
|
||||
(Citizens plugin has an option for this).
|
||||
|
||||
## Additional note 2 - Prefix/suffix on pets
|
||||
Since 1.9 teams affect tamed animals as well, displaying prefix/suffix on them as well and if nametags are set to be invisible, they will be completely invisible as well. If you want to avoid it, install [this plugin](https://www.spigotmc.org/resources/109466/).
|
||||
Since Minecraft 1.9, teams affect tamed animals as well, displaying prefix/suffix on them as well and if nametags are set to be invisible, they will be completely invisible as well. If you want to avoid it, install [this plugin](https://www.spigotmc.org/resources/109466/).
|
||||
|
||||
## Additional note 3 - Changing name itself
|
||||
Teams do not allow to change the nametag name itself. The only way to achieve this goal is to send & modify packets to replace the player's actual profile name with a fake one. This is very complicated and can have a lot of side effects. This is out of scope of TAB and is in fact something nick plugins are trying to achieve. As such, **TAB does not offer this**.
|
||||
@@ -205,8 +212,10 @@ To get custom values previously set using the API (they will return `null` if no
|
||||
* `NameTagManager#getCustomSuffix(TabPlayer)`
|
||||
|
||||
To get the original value set by the plugin based on configuration:
|
||||
* `NameTagManager#getOriginalPrefix(TabPlayer)`
|
||||
* `NameTagManager#getOriginalSuffix(TabPlayer)`
|
||||
* `NameTagManager#getOriginalRawPrefix(TabPlayer)` - Prefix with raw placeholder identifiers
|
||||
* `NameTagManager#getOriginalRawSuffix(TabPlayer)` - Suffix with raw placeholder identifiers
|
||||
* `NameTagManager#getOriginalReplacedPrefix(TabPlayer)` - Prefix with all placeholders parsed
|
||||
* `NameTagManager#getOriginalReplacedSuffix(TabPlayer)` - Suffix with all placeholders parsed
|
||||
|
||||
> [!NOTE]
|
||||
> These values are only temporary,
|
||||
|
||||
@@ -168,7 +168,7 @@ and you'll need
|
||||
to use [Conditional placeholders](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders) instead
|
||||
to achieve colored ping.
|
||||
|
||||
# Example 3 - Using both original and replaced output
|
||||
## Example 3 - Using both original and replaced output
|
||||
Once configured, replacements are applied as the placeholder output everywhere. It is not directly possible to use original output in one place and replaced in another.
|
||||
|
||||
If you need this, you should consider [conditional placeholders](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders) instead.
|
||||
|
||||
@@ -205,11 +205,8 @@ In other words, only one plugin can handle teams at a time.
|
||||
Having multiple plugins handling teams is supposed to end in a disaster.
|
||||
|
||||
Fortunately, TAB contains a function that prevents other plugins from assigning players into teams.
|
||||
This can be enabled/disabled by toggling `anti-override` setting under `scoreboard-teams`.
|
||||
This is, however, highly recommended to keep enabled, unless all of your plugins are configured correctly.
|
||||
When a plugin tries to override TAB's teams, this action is logged into `anti-override.log` file.
|
||||
If your file is empty / does not exist, it means you have no conflicting plugins / settings and can disable this option,
|
||||
slightly boosting performance.
|
||||
If your file is empty / does not exist, it means you have no conflicting plugins / settings.
|
||||
If the file exists, most of the time you can guess where the teams come from by their name.
|
||||
Here are a few common teams and their sources (`xxxx` means any, usually random character sequence):
|
||||
* `collideRule_xxxx` - this comes from Paper. Not going to explain why as that would be quite long, but the way you can avoid is by setting `enable-player-collisions: true` in paper config and `enable-collision: false` in TAB config (yes, collisions will be disabled).
|
||||
@@ -229,7 +226,6 @@ For that reason, let's call it list of mistakes made when following this page.
|
||||
|
||||
The most common mistakes include:
|
||||
* Disabling both teams and layout, not realizing it disables sorting as well.
|
||||
* Disabling anti-override without disabling teams in other plugins.
|
||||
* Mistaking `primary-group-finding-list` for the sorting list, despite that list having nothing to do with sorting and by default even having a comment above it saying it has nothing to do with sorting.
|
||||
* Not configuring primary groups correctly. This can have multiple reasons, such as
|
||||
* Not configuring group weights in LuckPerms.
|
||||
|
||||
@@ -126,7 +126,6 @@ The number of placeholders is not limited, and they can be used in combination w
|
||||
| Option name | Default value | Description |
|
||||
|-------------------|-----------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| enabled | true | Enables / Disables the feature |
|
||||
| anti-override | true | When enabled, prevents other plugins from overriding TAB. This results in slightly higher CPU usage, but will make sure the function works as expected. <br />Unlike with teams, attempts to override TAB are not logged into anti-override.log file. This is due to high amount of false positives from TAB's own features, as well as bungeecord server switch, higher CPU usage and more. Whether you need this or not depends on how properly your plugins are configured. Some of them attempt to format tablist even if you'd not expect it from such plugin. Keep this enabled to stay safe. |
|
||||
| disable-condition | %world%=disabledworld | A [condition](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Conditional-placeholders) that must be met for disabling the feature for players. Set to empty for not disabling the feature ever. |
|
||||
|
||||
# Tips & Tricks
|
||||
@@ -156,8 +155,11 @@ To get custom values previously set using the API (they will return `null` if no
|
||||
* `TabListFormatManager#getCustomSuffix(TabPlayer)`
|
||||
|
||||
To get the original value set by the plugin based on configuration:
|
||||
* `TabListFormatManager#getOriginalPrefix(TabPlayer)`
|
||||
* `TabListFormatManager#getOriginalName(TabPlayer)`
|
||||
* `TabListFormatManager#getOriginalSuffix(TabPlayer)`
|
||||
* `TabListFormatManager#getOriginalRawPrefix(TabPlayer)` - Prefix with raw placeholder identifiers
|
||||
* `TabListFormatManager#getOriginalRawName(TabPlayer)` - Name with raw placeholder identifiers
|
||||
* `TabListFormatManager#getOriginalRawSuffix(TabPlayer)` - Suffix with raw placeholder identifiers
|
||||
* `TabListFormatManager#getOriginalReplacedPrefix(TabPlayer)` - Prefix with all placeholders parsed
|
||||
* `TabListFormatManager#getOriginalReplacedName(TabPlayer)` - Name with all placeholders parsed
|
||||
* `TabListFormatManager#getOriginalReplacedSuffix(TabPlayer)` - Suffix with all placeholders parsed
|
||||
|
||||
**Note**: These values are only temporary, meaning they won't get saved anywhere and will get reset on player quit or plugin reload. If you wish to save these values into file, use [commands](https://github.com/NEZNAMY/TAB/wiki/Commands-&-Permissions#tab-playergroupplayeruuid-name-property-value-options).
|
||||
@@ -99,10 +99,15 @@ Using `''` will result in the text being display literally, not as a code.
|
||||
**Note:** Minecraft does not support every single UTF symbol and displays unsupported symbols as a box. You can try sending your symbol into chat and see if it works or not. If not, it's not supported by MC.
|
||||
|
||||
## #14 - Is there a way to remove all players from tablist?
|
||||
For a player to be visible in game, they must be in the tablist as well.
|
||||
Remember the NPC in tablist issue?
|
||||
If you don't mind players not appearing in the game, get a plugin that hides all players.
|
||||
If you want to see them in the game, however, your only choice is to put a lot of empty lines into header,
|
||||
In Minecraft, for a player to be visible in-game, they also need to appear in the tablist.
|
||||
Remember the issue with NPCs showing up in the tablist? It's the same underlying mechanic.
|
||||
|
||||
If you're okay with players not being visible in the world, you can use a plugin that hides all players completely.
|
||||
|
||||
Since Minecraft 1.19.3, this limitation has been lifted — it's now possible to have entities in the game without showing them in the tablist.
|
||||
However, the TAB plugin does **not** support removing all players from the tablist in any version of Minecraft.
|
||||
|
||||
An alternative solution using TAB is putting a lot of empty lines into header,
|
||||
which will push all players out of the screen.
|
||||
|
||||
## #15 - How to add images to tablist?
|
||||
@@ -114,8 +119,8 @@ Kind of.
|
||||
MiniMessage support **is** included; however, this doesn't mean it is guaranteed to work.
|
||||
MiniMessage library must be included in your server software.
|
||||
TAB does not include this library.
|
||||
* It **is** included in **Paper 1.18.2** and higher, **Velocity** and **Sponge 8**.
|
||||
* It **is not** included in **Spigot**, any server software for 1.18.1 and lower, **BungeeCord**, **Sponge 7** and **Fabric**.
|
||||
* It **is** included in **Paper 1.18.2** and higher, **Velocity** and **Sponge**.
|
||||
* It **is not** included in **Spigot**, any server software for 1.18.1 and lower, **BungeeCord**, **Fabric**, **Forge** and **NeoForge**.
|
||||
|
||||
If you believe MiniMessage should be supported on your server but doesn't work, open a bug report.
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# About the wiki
|
||||
The wiki explains the functionality of the plugin as of version **5.2.1**.
|
||||
The wiki explains the functionality of the plugin as of version **5.2.4**.
|
||||
If your config looks different or is missing some features, you are using an old version of the plugin.
|
||||
To get the latest version, check [releases](https://github.com/NEZNAMY/TAB/releases/).
|
||||
Wiki for older plugin versions is not available.
|
||||
@@ -11,7 +11,7 @@ This will give you knowledge to do things you had no idea were possible, giving
|
||||
A lot of examples on the wiki use PlaceholderAPI placeholders without explaining its installation step by step. If you are going to use the examples and aren't familiar with the plugin, check out [Quick PlaceholderAPI startup guide](https://github.com/NEZNAMY/TAB/wiki/Quick-PlaceholderAPI-startup-guide).
|
||||
|
||||
# Limitations of plugins
|
||||
TAB is a plugin.
|
||||
TAB is a plugin (even on modded platforms, it is only a server-sided mod).
|
||||
It only modifies the server behavior to your liking.
|
||||
It does not add anything into the game.
|
||||
Because of that, you'll need
|
||||
|
||||
@@ -33,7 +33,8 @@ install [VelocityScoreboardAPI](https://github.com/NEZNAMY/VelocityScoreboardAPI
|
||||
> With proxy installation, use **/btab** command instead of **/tab**.
|
||||
|
||||
Advantages of proxy installation compared to installing on all backend servers instead:
|
||||
* Can use the [Global player list](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Global-playerlist) without requiring Redis set up and [Layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout) can work with all players connected to the proxy
|
||||
* Can use the [Global player list](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Global-playerlist) without requiring Redis set up
|
||||
* [Layout](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Layout) can work with all players connected to the proxy
|
||||
* Avoid [header/footer](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Header-&-Footer#additional-note-1---not-resetting-on-server-switch) and [bossbar](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Bossbar#additional-note-2---not-hiding-on-server-switch) not disappearing on server switch
|
||||
* Configuration files in a single place for easier editing / no need to use MySQL for syncing data
|
||||
|
||||
|
||||
@@ -56,6 +56,8 @@ These placeholders are available on all platforms.
|
||||
| %player-version-id% | -1 | Network ID of player's version. You can see the full version map on [fan wiki](https://wiki.vg/Protocol_version_numbers) for all versions or [TAB's source code](https://github.com/NEZNAMY/TAB/blob/master/shared/src/main/java/me/neznamy/tab/shared/ProtocolVersion.java) for releases only. Useful for conditions to create per-version results. |
|
||||
| %luckperms-prefix% | 1000 | Prefix from LuckPerms from the server where TAB is installed |
|
||||
| %luckperms-suffix% | 1000 | Suffix from LuckPerms from the server where TAB is installed |
|
||||
| %luckperms-prefixes% | 1000 | All prefixes combined from LuckPerms from the server where TAB is installed |
|
||||
| %luckperms-suffixes% | 1000 | All suffixes combined from LuckPerms from the server where TAB is installed |
|
||||
| %displayname% | 500 | Display name variable set by permission plugin, typically prefix + name + suffix |
|
||||
| %group% | 1000 | Returns player's primary group name. Created for internal functionality, but can be used as a display placeholder as well. |
|
||||
| %vanished% | 1000 | Returns `true`/`false` based on player's vanish status. Created for internal functionality, but can be used as a display placeholder as well. |
|
||||
@@ -70,8 +72,8 @@ These placeholders only work when TAB is installed on a backend server (Bukkit /
|
||||
| ------------- | ------------- | ------------- | ------------- |
|
||||
| %health% | 100 | Player's health, rounded up to match Minecraft's heart display. | %player_health_rounded% |
|
||||
| %displayname% | 500 | Player's display name value set by permission plugin. | %player_displayname% |
|
||||
| %tps% | 1000 | TPS of server from the last minute (measured by server, not available on Fabric as it doesn't measure the value) | %server_tps_1% |
|
||||
| %mspt% | 1000 | Server's current milliseconds per tick (Paper / Sponge 8+ / Fabric only) | - |
|
||||
| %tps% | 1000 | TPS of server from the last minute. Measured by the server. Not directly available on Fabric, Forge and Neoforge. Primitive approximation using MSPT (TPS = 1000/MSPT, max 20) is used there. | %server_tps_1% |
|
||||
| %mspt% | 1000 | Server's current milliseconds per tick (not available on Spigot) | - |
|
||||
|
||||
## BungeeCord only
|
||||
| Identifier | Refresh interval | Description |
|
||||
@@ -112,8 +114,7 @@ Full list of placeholders:
|
||||
| %tab_scoreboard_name% | Returns name of player's currently displayed scoreboard or empty string if none is displayed due to no display condition being met |
|
||||
| %tab_scoreboard_visible% | "Enabled" if visible, "Disabled" if not |
|
||||
| %tab_bossbar_visible% | "Enabled" if visible, "Disabled" if not |
|
||||
| %tab_nametag_preview% | "Enabled" if previewing armor stands using /tab nametag preview, "Disabled" if not |
|
||||
| %tab_nametag_visibility% | "Enabled" if player can see nametags, "Disabled" if disabled using /tab nametag toggle |
|
||||
| %tab_nametag_visibility% | "Enabled" if player can see nametags, "Disabled" if disabled using `/tab nametag toggleview` |
|
||||
| %tab_replace_\<placeholder\>% | Applies [Placeholder output replacements](https://github.com/NEZNAMY/TAB/wiki/Feature-guide:-Placeholder-output-replacements) to a PlaceholderAPI placeholder (for example %tab_replace_essentials_vanished%) |
|
||||
| %tab_placeholder_\<placeholder\>% | returns value of tab's internal placeholder (such as %tab_placeholder_animation:name% for %animation:name%) |
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
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;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* An interface allowing work with BossBars such as creating, sending
|
||||
* and toggling.
|
||||
@@ -78,6 +78,28 @@ public interface BossBarManager {
|
||||
*/
|
||||
@NotNull Map<String, BossBar> getRegisteredBossBars();
|
||||
|
||||
/**
|
||||
* Removes BossBar with specified name from the manager, making it no longer available.
|
||||
* If BossBar was displayed to any players, it is removed.
|
||||
*
|
||||
* @param name
|
||||
* Name of registered BossBar to remove
|
||||
* @throws IllegalArgumentException
|
||||
* if no BossBar with specified name exists
|
||||
*/
|
||||
void removeBossBar(@NonNull String name);
|
||||
|
||||
/**
|
||||
* Removes BossBar from the manager, making it no longer available.
|
||||
* If BossBar was displayed to any players, it is removed.
|
||||
*
|
||||
* @param bossBar
|
||||
* BossBar to remove
|
||||
* @throws IllegalArgumentException
|
||||
* if specified BossBar is not registered
|
||||
*/
|
||||
void removeBossBar(@NonNull BossBar bossBar);
|
||||
|
||||
/**
|
||||
* Toggles BossBar for this player and sends toggle message if {@code sendToggleMessage} is true.
|
||||
*
|
||||
|
||||
@@ -134,7 +134,7 @@ public interface NameTagManager {
|
||||
* @param prefix
|
||||
* new prefix value
|
||||
* @see #getCustomPrefix(TabPlayer)
|
||||
* @see #getOriginalPrefix(TabPlayer)
|
||||
* @see #getOriginalRawPrefix(TabPlayer)
|
||||
*/
|
||||
void setPrefix(@NonNull TabPlayer player, @Nullable String prefix);
|
||||
|
||||
@@ -148,7 +148,7 @@ public interface NameTagManager {
|
||||
* @param suffix
|
||||
* new suffix value
|
||||
* @see #getCustomSuffix(TabPlayer)
|
||||
* @see #getOriginalSuffix(TabPlayer)
|
||||
* @see #getOriginalRawSuffix(TabPlayer)
|
||||
*/
|
||||
void setSuffix(@NonNull TabPlayer player, @Nullable String suffix);
|
||||
|
||||
@@ -160,7 +160,7 @@ public interface NameTagManager {
|
||||
* Player to get custom prefix of
|
||||
* @return Custom prefix assigned using the API.
|
||||
* @see #setPrefix(TabPlayer, String)
|
||||
* @see #getOriginalPrefix(TabPlayer)
|
||||
* @see #getOriginalRawPrefix(TabPlayer)
|
||||
*/
|
||||
@Nullable
|
||||
String getCustomPrefix(@NonNull TabPlayer player);
|
||||
@@ -173,7 +173,7 @@ public interface NameTagManager {
|
||||
* Player to get custom suffix of
|
||||
* @return Custom suffix assigned using the API.
|
||||
* @see #setSuffix(TabPlayer, String)
|
||||
* @see #getOriginalSuffix(TabPlayer)
|
||||
* @see #getOriginalRawSuffix(TabPlayer)
|
||||
*/
|
||||
@Nullable
|
||||
String getCustomSuffix(@NonNull TabPlayer player);
|
||||
@@ -186,7 +186,7 @@ public interface NameTagManager {
|
||||
* @see #getCustomPrefix(TabPlayer)
|
||||
*/
|
||||
@NotNull
|
||||
String getOriginalPrefix(@NonNull TabPlayer player);
|
||||
String getOriginalRawPrefix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns original suffix assigned by the plugin using internal logic.
|
||||
@@ -196,6 +196,50 @@ public interface NameTagManager {
|
||||
* @see #getCustomSuffix(TabPlayer)
|
||||
*/
|
||||
@NotNull
|
||||
String getOriginalRawSuffix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns original prefix assigned by the plugin using internal logic with all placeholders replaced.
|
||||
* @param player
|
||||
* Player to get replaced original prefix of
|
||||
* @return Original prefix assigned by the plugin's internal logic.
|
||||
* @see #getCustomPrefix(TabPlayer)
|
||||
*/
|
||||
@NotNull
|
||||
String getOriginalReplacedPrefix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns original suffix assigned by the plugin using internal logic with all placeholders replaced.
|
||||
* @param player
|
||||
* Player to get replaced original suffix of
|
||||
* @return Original suffix assigned by the plugin's internal logic.
|
||||
* @see #getCustomSuffix(TabPlayer)
|
||||
*/
|
||||
@NotNull
|
||||
String getOriginalReplacedSuffix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns original suffix assigned by the plugin using internal logic.
|
||||
* @param player
|
||||
* Player to get replaced original prefix of
|
||||
* @return Original prefix assigned by the plugin's internal logic.
|
||||
* @see #getCustomPrefix(TabPlayer)
|
||||
* @deprecated Use {@link #getOriginalRawPrefix(TabPlayer)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@NotNull
|
||||
String getOriginalPrefix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns original suffix assigned by the plugin using internal logic.
|
||||
* @param player
|
||||
* Player to get replaced original suffix of
|
||||
* @return Original suffix assigned by the plugin's internal logic.
|
||||
* @see #getCustomSuffix(TabPlayer)
|
||||
* @deprecated Use {@link #getOriginalRawSuffix(TabPlayer)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@NotNull
|
||||
String getOriginalSuffix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
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;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Interface allowing work with scoreboards, such as creating,
|
||||
* sending, toggling and modifying.
|
||||
@@ -54,6 +54,29 @@ public interface ScoreboardManager {
|
||||
* @return map of registered scoreboards
|
||||
*/
|
||||
@NotNull Map<String, Scoreboard> getRegisteredScoreboards();
|
||||
|
||||
/**
|
||||
* Removes scoreboard with specified name from list of scoreboards. If it was displayed to anyone,
|
||||
* it will be removed from their display as well. Then, those players will receive a new scoreboard based
|
||||
* on configuration.
|
||||
*
|
||||
* @param name Name of scoreboard to remove
|
||||
* @throws IllegalArgumentException
|
||||
* if scoreboard with such name does not exist
|
||||
*/
|
||||
void removeScoreboard(@NonNull String name);
|
||||
|
||||
/**
|
||||
* Removes scoreboard from list of scoreboards. If it was displayed to anyone,
|
||||
* it will be removed from their display as well. Then, those players will receive a new scoreboard based
|
||||
* on configuration.
|
||||
*
|
||||
* @param scoreboard
|
||||
* Scoreboard to remove
|
||||
* @throws IllegalArgumentException
|
||||
* if specified scoreboard is not registered
|
||||
*/
|
||||
void removeScoreboard(@NonNull Scoreboard scoreboard);
|
||||
|
||||
/**
|
||||
* Displays scoreboard to defined player. This will disable all display
|
||||
|
||||
@@ -27,7 +27,7 @@ public interface TabListFormatManager {
|
||||
* @param prefix
|
||||
* new prefix value
|
||||
* @see #getCustomPrefix(TabPlayer)
|
||||
* @see #getOriginalPrefix(TabPlayer)
|
||||
* @see #getOriginalRawPrefix(TabPlayer)
|
||||
*/
|
||||
void setPrefix(@NonNull TabPlayer player, @Nullable String prefix);
|
||||
|
||||
@@ -41,7 +41,7 @@ public interface TabListFormatManager {
|
||||
* @param customName
|
||||
* new customName value
|
||||
* @see #getCustomName(TabPlayer)
|
||||
* @see #getOriginalName(TabPlayer)
|
||||
* @see #getOriginalRawName(TabPlayer)
|
||||
*/
|
||||
void setName(@NonNull TabPlayer player, @Nullable String customName);
|
||||
|
||||
@@ -55,7 +55,7 @@ public interface TabListFormatManager {
|
||||
* @param suffix
|
||||
* new suffix value
|
||||
* @see #getCustomSuffix(TabPlayer)
|
||||
* @see #getOriginalSuffix(TabPlayer)
|
||||
* @see #getOriginalRawSuffix(TabPlayer)
|
||||
*/
|
||||
void setSuffix(@NonNull TabPlayer player, @Nullable String suffix);
|
||||
|
||||
@@ -67,7 +67,7 @@ public interface TabListFormatManager {
|
||||
* player to get custom prefix of
|
||||
* @return player's custom prefix or {@code null} if not defined
|
||||
* @see #setPrefix(TabPlayer, String)
|
||||
* @see #getOriginalPrefix(TabPlayer)
|
||||
* @see #getOriginalRawPrefix(TabPlayer)
|
||||
*/
|
||||
@Nullable String getCustomPrefix(@NonNull TabPlayer player);
|
||||
|
||||
@@ -104,8 +104,11 @@ public interface TabListFormatManager {
|
||||
* @return player's original prefix
|
||||
* @see #setPrefix(TabPlayer, String)
|
||||
* @see #getCustomPrefix(TabPlayer)
|
||||
* @deprecated Use {@link #getOriginalRawPrefix(TabPlayer)} instead.
|
||||
*/
|
||||
@NotNull String getOriginalPrefix(@NonNull TabPlayer player);
|
||||
@NotNull
|
||||
@Deprecated
|
||||
String getOriginalPrefix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns player's original name applied using plugin's internal logic.
|
||||
@@ -116,8 +119,11 @@ public interface TabListFormatManager {
|
||||
* @return player's original name
|
||||
* @see #setName(TabPlayer, String)
|
||||
* @see #getCustomName(TabPlayer)
|
||||
* @deprecated Use {@link #getOriginalRawName(TabPlayer)} instead.
|
||||
*/
|
||||
@NotNull String getOriginalName(@NonNull TabPlayer player);
|
||||
@NotNull
|
||||
@Deprecated
|
||||
String getOriginalName(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns player's original suffix applied using plugin's internal logic.
|
||||
@@ -128,6 +134,69 @@ public interface TabListFormatManager {
|
||||
* @return player's original suffix
|
||||
* @see #setSuffix(TabPlayer, String)
|
||||
* @see #getCustomSuffix(TabPlayer)
|
||||
* @deprecated Use {@link #getOriginalRawSuffix(TabPlayer)} instead.
|
||||
*/
|
||||
@NotNull String getOriginalSuffix(@NonNull TabPlayer player);
|
||||
@NotNull
|
||||
@Deprecated
|
||||
String getOriginalSuffix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns original prefix assigned by the plugin using internal logic.
|
||||
* @param player
|
||||
* Player to get original prefix of
|
||||
* @return Original prefix assigned by the plugin's internal logic.
|
||||
* @see #getCustomPrefix(TabPlayer)
|
||||
*/
|
||||
@NotNull
|
||||
String getOriginalRawPrefix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns original name assigned by the plugin using internal logic.
|
||||
* @param player
|
||||
* Player to get original name of
|
||||
* @return Original name assigned by the plugin's internal logic.
|
||||
* @see #getCustomName(TabPlayer)
|
||||
*/
|
||||
@NotNull
|
||||
String getOriginalRawName(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns original suffix assigned by the plugin using internal logic.
|
||||
* @param player
|
||||
* Player to get original suffix of
|
||||
* @return Original suffix assigned by the plugin's internal logic.
|
||||
* @see #getCustomSuffix(TabPlayer)
|
||||
*/
|
||||
@NotNull
|
||||
String getOriginalRawSuffix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns original prefix assigned by the plugin using internal logic with all placeholders replaced.
|
||||
* @param player
|
||||
* Player to get replaced original prefix of
|
||||
* @return Original prefix assigned by the plugin's internal logic.
|
||||
* @see #getCustomPrefix(TabPlayer)
|
||||
*/
|
||||
@NotNull
|
||||
String getOriginalReplacedPrefix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns original name assigned by the plugin using internal logic with all placeholders replaced.
|
||||
* @param player
|
||||
* Player to get replaced original name of
|
||||
* @return Original name assigned by the plugin's internal logic.
|
||||
* @see #getCustomName(TabPlayer)
|
||||
*/
|
||||
@NotNull
|
||||
String getOriginalReplacedName(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns original suffix assigned by the plugin using internal logic with all placeholders replaced.
|
||||
* @param player
|
||||
* Player to get replaced original suffix of
|
||||
* @return Original suffix assigned by the plugin's internal logic.
|
||||
* @see #getCustomSuffix(TabPlayer)
|
||||
*/
|
||||
@NotNull
|
||||
String getOriginalReplacedSuffix(@NonNull TabPlayer player);
|
||||
}
|
||||
+1
-1
@@ -4,7 +4,7 @@ plugins {
|
||||
|
||||
allprojects {
|
||||
group = "me.neznamy"
|
||||
version = "5.2.2"
|
||||
version = "5.2.5"
|
||||
description = "An all-in-one solution that works"
|
||||
|
||||
ext.set("id", "tab")
|
||||
|
||||
@@ -15,6 +15,4 @@ dependencies {
|
||||
exclude("net.md-5", "bungeecord-chat")
|
||||
}
|
||||
compileOnly("com.github.LeonMangler:PremiumVanishAPI:2.8.8")
|
||||
compileOnlyApi("com.viaversion:viaversion-api:5.2.1")
|
||||
compileOnly("com.viaversion:viaversion-common:5.2.1")
|
||||
}
|
||||
-13
@@ -2,12 +2,9 @@ package me.neznamy.tab.platforms.paper_1_20_5;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ComponentConverter;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ImplementationProvider;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.viaversion.ViaScoreboard;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.viaversion.ViaTabList;
|
||||
import me.neznamy.tab.shared.platform.Scoreboard;
|
||||
import me.neznamy.tab.shared.platform.TabList;
|
||||
import me.neznamy.tab.shared.util.function.FunctionWithException;
|
||||
@@ -29,16 +26,6 @@ public class PaperImplementationProvider implements ImplementationProvider {
|
||||
return new PaperPacketScoreboard(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSend(@NonNull Object packet, @NonNull ViaScoreboard scoreboard) {
|
||||
PaperPacketScoreboard.onPacketSend(packet, scoreboard);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSend(@NonNull Object packet, @NonNull ViaTabList tabList) {
|
||||
PaperPacketTabList.onPacketSend(packet, tabList);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public TabList newTabList(@NotNull BukkitTabPlayer player) {
|
||||
|
||||
+26
-30
@@ -33,35 +33,6 @@ public class PaperPacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
private static final Scoreboard dummyScoreboard = new Scoreboard();
|
||||
private static final Field players = ReflectionUtils.getOnlyField(ClientboundSetPlayerTeamPacket.class, Collection.class);
|
||||
|
||||
@SneakyThrows
|
||||
public static void onPacketSend(@NonNull Object packet, @NonNull SafeScoreboard<BukkitTabPlayer> scoreboard) {
|
||||
if (packet instanceof ClientboundSetDisplayObjectivePacket display) {
|
||||
TAB.getInstance().getFeatureManager().onDisplayObjective(scoreboard.getPlayer(), display.getSlot().ordinal(), display.getObjectiveName());
|
||||
}
|
||||
if (packet instanceof ClientboundSetObjectivePacket objective) {
|
||||
TAB.getInstance().getFeatureManager().onObjective(scoreboard.getPlayer(), objective.getMethod(), objective.getObjectiveName());
|
||||
}
|
||||
if (packet instanceof ClientboundSetPlayerTeamPacket team) {
|
||||
int action = getMethod(team);
|
||||
if (action == TeamAction.UPDATE) return;
|
||||
players.set(team, scoreboard.onTeamPacket(action, team.getName(), team.getPlayers() == null ? Collections.emptyList() : team.getPlayers()));
|
||||
}
|
||||
}
|
||||
|
||||
private static int getMethod(@NonNull ClientboundSetPlayerTeamPacket team) {
|
||||
if (team.getTeamAction() == ClientboundSetPlayerTeamPacket.Action.ADD) {
|
||||
return 0;
|
||||
} else if (team.getTeamAction() == ClientboundSetPlayerTeamPacket.Action.REMOVE) {
|
||||
return 1;
|
||||
} else if (team.getPlayerAction() == ClientboundSetPlayerTeamPacket.Action.ADD) {
|
||||
return 3;
|
||||
} else if (team.getPlayerAction() == ClientboundSetPlayerTeamPacket.Action.REMOVE) {
|
||||
return 4;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance with given player.
|
||||
*
|
||||
@@ -161,8 +132,33 @@ public class PaperPacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void onPacketSend(@NonNull Object packet) {
|
||||
onPacketSend(packet, this);
|
||||
if (packet instanceof ClientboundSetDisplayObjectivePacket display) {
|
||||
TAB.getInstance().getFeatureManager().onDisplayObjective(player, display.getSlot().ordinal(), display.getObjectiveName());
|
||||
}
|
||||
if (packet instanceof ClientboundSetObjectivePacket objective) {
|
||||
TAB.getInstance().getFeatureManager().onObjective(player, objective.getMethod(), objective.getObjectiveName());
|
||||
}
|
||||
if (packet instanceof ClientboundSetPlayerTeamPacket team) {
|
||||
int action = getMethod(team);
|
||||
if (action == TeamAction.UPDATE) return;
|
||||
players.set(team, onTeamPacket(action, team.getName(), team.getPlayers() == null ? Collections.emptyList() : team.getPlayers()));
|
||||
}
|
||||
}
|
||||
|
||||
private int getMethod(@NonNull ClientboundSetPlayerTeamPacket team) {
|
||||
if (team.getTeamAction() == ClientboundSetPlayerTeamPacket.Action.ADD) {
|
||||
return 0;
|
||||
} else if (team.getTeamAction() == ClientboundSetPlayerTeamPacket.Action.REMOVE) {
|
||||
return 1;
|
||||
} else if (team.getPlayerAction() == ClientboundSetPlayerTeamPacket.Action.ADD) {
|
||||
return 3;
|
||||
} else if (team.getPlayerAction() == ClientboundSetPlayerTeamPacket.Action.REMOVE) {
|
||||
return 4;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+33
-37
@@ -36,42 +36,6 @@ public class PaperPacketTabList extends TrackedTabList<BukkitTabPlayer> {
|
||||
|
||||
private static final Field entries = ReflectionUtils.getOnlyField(ClientboundPlayerInfoUpdatePacket.class, List.class);
|
||||
|
||||
@SneakyThrows
|
||||
public static void onPacketSend(@NonNull Object packet, TrackedTabList<BukkitTabPlayer> tabList) {
|
||||
if (packet instanceof ClientboundPlayerInfoUpdatePacket info) {
|
||||
EnumSet<ClientboundPlayerInfoUpdatePacket.Action> actions = info.actions();
|
||||
List<ClientboundPlayerInfoUpdatePacket.Entry> updatedList = new ArrayList<>();
|
||||
boolean rewritePacket = false;
|
||||
for (ClientboundPlayerInfoUpdatePacket.Entry nmsData : info.entries()) {
|
||||
boolean rewriteEntry = false;
|
||||
Component displayName = nmsData.displayName();
|
||||
int latency = nmsData.latency();
|
||||
if (actions.contains(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME)) {
|
||||
TabComponent expectedDisplayName = tabList.getExpectedDisplayNames().get(nmsData.profileId());
|
||||
if (expectedDisplayName != null && expectedDisplayName.convert() != displayName) {
|
||||
displayName = expectedDisplayName.convert();
|
||||
rewriteEntry = rewritePacket = true;
|
||||
}
|
||||
}
|
||||
if (actions.contains(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY)) {
|
||||
int newLatency = TAB.getInstance().getFeatureManager().onLatencyChange(tabList.getPlayer(), nmsData.profileId(), latency);
|
||||
if (newLatency != latency) {
|
||||
latency = newLatency;
|
||||
rewriteEntry = rewritePacket = true;
|
||||
}
|
||||
}
|
||||
if (actions.contains(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER)) {
|
||||
TAB.getInstance().getFeatureManager().onEntryAdd(tabList.getPlayer(), nmsData.profileId(), nmsData.profile().getName());
|
||||
}
|
||||
updatedList.add(rewriteEntry ? new ClientboundPlayerInfoUpdatePacket.Entry(
|
||||
nmsData.profileId(), nmsData.profile(), nmsData.listed(), latency, nmsData.gameMode(), displayName,
|
||||
nmsData.chatSession()
|
||||
) : nmsData);
|
||||
}
|
||||
if (rewritePacket) entries.set(info, updatedList);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance.
|
||||
*
|
||||
@@ -143,8 +107,40 @@ public class PaperPacketTabList extends TrackedTabList<BukkitTabPlayer> {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void onPacketSend(@NonNull Object packet) {
|
||||
onPacketSend(packet, this);
|
||||
if (packet instanceof ClientboundPlayerInfoUpdatePacket info) {
|
||||
EnumSet<ClientboundPlayerInfoUpdatePacket.Action> actions = info.actions();
|
||||
List<ClientboundPlayerInfoUpdatePacket.Entry> updatedList = new ArrayList<>();
|
||||
boolean rewritePacket = false;
|
||||
for (ClientboundPlayerInfoUpdatePacket.Entry nmsData : info.entries()) {
|
||||
boolean rewriteEntry = false;
|
||||
Component displayName = nmsData.displayName();
|
||||
int latency = nmsData.latency();
|
||||
if (actions.contains(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME)) {
|
||||
TabComponent expectedDisplayName = getExpectedDisplayNames().get(nmsData.profileId());
|
||||
if (expectedDisplayName != null && expectedDisplayName.convert() != displayName) {
|
||||
displayName = expectedDisplayName.convert();
|
||||
rewriteEntry = rewritePacket = true;
|
||||
}
|
||||
}
|
||||
if (actions.contains(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY)) {
|
||||
int newLatency = TAB.getInstance().getFeatureManager().onLatencyChange(player, nmsData.profileId(), latency);
|
||||
if (newLatency != latency) {
|
||||
latency = newLatency;
|
||||
rewriteEntry = rewritePacket = true;
|
||||
}
|
||||
}
|
||||
if (actions.contains(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER)) {
|
||||
TAB.getInstance().getFeatureManager().onEntryAdd(player, nmsData.profileId(), nmsData.profile().getName());
|
||||
}
|
||||
updatedList.add(rewriteEntry ? new ClientboundPlayerInfoUpdatePacket.Entry(
|
||||
nmsData.profileId(), nmsData.profile(), nmsData.listed(), latency, nmsData.gameMode(), displayName,
|
||||
nmsData.chatSession()
|
||||
) : nmsData);
|
||||
}
|
||||
if (rewritePacket) entries.set(info, updatedList);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendPacket(@NonNull EnumSet<ClientboundPlayerInfoUpdatePacket.Action> action, @NonNull UUID id, @NonNull String name, @Nullable Skin skin,
|
||||
|
||||
-13
@@ -2,12 +2,9 @@ package me.neznamy.tab.platforms.paper_1_21_2;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ComponentConverter;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ImplementationProvider;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.viaversion.ViaScoreboard;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.viaversion.ViaTabList;
|
||||
import me.neznamy.tab.shared.platform.Scoreboard;
|
||||
import me.neznamy.tab.shared.platform.TabList;
|
||||
import me.neznamy.tab.shared.util.function.FunctionWithException;
|
||||
@@ -29,16 +26,6 @@ public class PaperImplementationProvider implements ImplementationProvider {
|
||||
return new PaperPacketScoreboard(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSend(@NonNull Object packet, @NonNull ViaScoreboard scoreboard) {
|
||||
PaperPacketScoreboard.onPacketSend(packet, scoreboard);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSend(@NonNull Object packet, @NonNull ViaTabList tabList) {
|
||||
PaperPacketTabList.onPacketSend(packet, tabList);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public TabList newTabList(@NotNull BukkitTabPlayer player) {
|
||||
|
||||
+26
-30
@@ -33,35 +33,6 @@ public class PaperPacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
private static final Scoreboard dummyScoreboard = new Scoreboard();
|
||||
private static final Field players = ReflectionUtils.getOnlyField(ClientboundSetPlayerTeamPacket.class, Collection.class);
|
||||
|
||||
@SneakyThrows
|
||||
public static void onPacketSend(@NonNull Object packet, @NonNull SafeScoreboard<BukkitTabPlayer> scoreboard) {
|
||||
if (packet instanceof ClientboundSetDisplayObjectivePacket display) {
|
||||
TAB.getInstance().getFeatureManager().onDisplayObjective(scoreboard.getPlayer(), display.getSlot().ordinal(), display.getObjectiveName());
|
||||
}
|
||||
if (packet instanceof ClientboundSetObjectivePacket objective) {
|
||||
TAB.getInstance().getFeatureManager().onObjective(scoreboard.getPlayer(), objective.getMethod(), objective.getObjectiveName());
|
||||
}
|
||||
if (packet instanceof ClientboundSetPlayerTeamPacket team) {
|
||||
int action = getMethod(team);
|
||||
if (action == TeamAction.UPDATE) return;
|
||||
players.set(team, scoreboard.onTeamPacket(action, team.getName(), team.getPlayers() == null ? Collections.emptyList() : team.getPlayers()));
|
||||
}
|
||||
}
|
||||
|
||||
private static int getMethod(@NonNull ClientboundSetPlayerTeamPacket team) {
|
||||
if (team.getTeamAction() == ClientboundSetPlayerTeamPacket.Action.ADD) {
|
||||
return 0;
|
||||
} else if (team.getTeamAction() == ClientboundSetPlayerTeamPacket.Action.REMOVE) {
|
||||
return 1;
|
||||
} else if (team.getPlayerAction() == ClientboundSetPlayerTeamPacket.Action.ADD) {
|
||||
return 3;
|
||||
} else if (team.getPlayerAction() == ClientboundSetPlayerTeamPacket.Action.REMOVE) {
|
||||
return 4;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance with given player.
|
||||
*
|
||||
@@ -161,8 +132,33 @@ public class PaperPacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void onPacketSend(@NonNull Object packet) {
|
||||
onPacketSend(packet, this);
|
||||
if (packet instanceof ClientboundSetDisplayObjectivePacket display) {
|
||||
TAB.getInstance().getFeatureManager().onDisplayObjective(player, display.getSlot().ordinal(), display.getObjectiveName());
|
||||
}
|
||||
if (packet instanceof ClientboundSetObjectivePacket objective) {
|
||||
TAB.getInstance().getFeatureManager().onObjective(player, objective.getMethod(), objective.getObjectiveName());
|
||||
}
|
||||
if (packet instanceof ClientboundSetPlayerTeamPacket team) {
|
||||
int action = getMethod(team);
|
||||
if (action == TeamAction.UPDATE) return;
|
||||
players.set(team, onTeamPacket(action, team.getName(), team.getPlayers() == null ? Collections.emptyList() : team.getPlayers()));
|
||||
}
|
||||
}
|
||||
|
||||
private static int getMethod(@NonNull ClientboundSetPlayerTeamPacket team) {
|
||||
if (team.getTeamAction() == ClientboundSetPlayerTeamPacket.Action.ADD) {
|
||||
return 0;
|
||||
} else if (team.getTeamAction() == ClientboundSetPlayerTeamPacket.Action.REMOVE) {
|
||||
return 1;
|
||||
} else if (team.getPlayerAction() == ClientboundSetPlayerTeamPacket.Action.ADD) {
|
||||
return 3;
|
||||
} else if (team.getPlayerAction() == ClientboundSetPlayerTeamPacket.Action.REMOVE) {
|
||||
return 4;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+33
-37
@@ -37,42 +37,6 @@ public class PaperPacketTabList extends TrackedTabList<BukkitTabPlayer> {
|
||||
|
||||
private static final Field entries = ReflectionUtils.getOnlyField(ClientboundPlayerInfoUpdatePacket.class, List.class);
|
||||
|
||||
@SneakyThrows
|
||||
public static void onPacketSend(@NonNull Object packet, TrackedTabList<BukkitTabPlayer> tabList) {
|
||||
if (packet instanceof ClientboundPlayerInfoUpdatePacket info) {
|
||||
EnumSet<ClientboundPlayerInfoUpdatePacket.Action> actions = info.actions();
|
||||
List<ClientboundPlayerInfoUpdatePacket.Entry> updatedList = new ArrayList<>();
|
||||
boolean rewritePacket = false;
|
||||
for (ClientboundPlayerInfoUpdatePacket.Entry nmsData : info.entries()) {
|
||||
boolean rewriteEntry = false;
|
||||
Component displayName = nmsData.displayName();
|
||||
int latency = nmsData.latency();
|
||||
if (actions.contains(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME)) {
|
||||
TabComponent expectedDisplayName = tabList.getExpectedDisplayNames().get(nmsData.profileId());
|
||||
if (expectedDisplayName != null && expectedDisplayName.convert() != displayName) {
|
||||
displayName = expectedDisplayName.convert();
|
||||
rewriteEntry = rewritePacket = true;
|
||||
}
|
||||
}
|
||||
if (actions.contains(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY)) {
|
||||
int newLatency = TAB.getInstance().getFeatureManager().onLatencyChange(tabList.getPlayer(), nmsData.profileId(), latency);
|
||||
if (newLatency != latency) {
|
||||
latency = newLatency;
|
||||
rewriteEntry = rewritePacket = true;
|
||||
}
|
||||
}
|
||||
if (actions.contains(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER)) {
|
||||
TAB.getInstance().getFeatureManager().onEntryAdd(tabList.getPlayer(), nmsData.profileId(), nmsData.profile().getName());
|
||||
}
|
||||
updatedList.add(rewriteEntry ? new ClientboundPlayerInfoUpdatePacket.Entry(
|
||||
nmsData.profileId(), nmsData.profile(), nmsData.listed(), latency, nmsData.gameMode(), displayName,
|
||||
nmsData.listOrder(), nmsData.chatSession()
|
||||
) : nmsData);
|
||||
}
|
||||
if (rewritePacket) entries.set(info, updatedList);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance.
|
||||
*
|
||||
@@ -144,8 +108,40 @@ public class PaperPacketTabList extends TrackedTabList<BukkitTabPlayer> {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void onPacketSend(@NonNull Object packet) {
|
||||
onPacketSend(packet, this);
|
||||
if (packet instanceof ClientboundPlayerInfoUpdatePacket info) {
|
||||
EnumSet<ClientboundPlayerInfoUpdatePacket.Action> actions = info.actions();
|
||||
List<ClientboundPlayerInfoUpdatePacket.Entry> updatedList = new ArrayList<>();
|
||||
boolean rewritePacket = false;
|
||||
for (ClientboundPlayerInfoUpdatePacket.Entry nmsData : info.entries()) {
|
||||
boolean rewriteEntry = false;
|
||||
Component displayName = nmsData.displayName();
|
||||
int latency = nmsData.latency();
|
||||
if (actions.contains(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME)) {
|
||||
TabComponent expectedDisplayName = getExpectedDisplayNames().get(nmsData.profileId());
|
||||
if (expectedDisplayName != null && expectedDisplayName.convert() != displayName) {
|
||||
displayName = expectedDisplayName.convert();
|
||||
rewriteEntry = rewritePacket = true;
|
||||
}
|
||||
}
|
||||
if (actions.contains(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY)) {
|
||||
int newLatency = TAB.getInstance().getFeatureManager().onLatencyChange(player, nmsData.profileId(), latency);
|
||||
if (newLatency != latency) {
|
||||
latency = newLatency;
|
||||
rewriteEntry = rewritePacket = true;
|
||||
}
|
||||
}
|
||||
if (actions.contains(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER)) {
|
||||
TAB.getInstance().getFeatureManager().onEntryAdd(player, nmsData.profileId(), nmsData.profile().getName());
|
||||
}
|
||||
updatedList.add(rewriteEntry ? new ClientboundPlayerInfoUpdatePacket.Entry(
|
||||
nmsData.profileId(), nmsData.profile(), nmsData.listed(), latency, nmsData.gameMode(), displayName,
|
||||
nmsData.listOrder(), nmsData.chatSession()
|
||||
) : nmsData);
|
||||
}
|
||||
if (rewritePacket) entries.set(info, updatedList);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendPacket(@NonNull EnumSet<ClientboundPlayerInfoUpdatePacket.Action> action, @NonNull UUID id, @NonNull String name, @Nullable Skin skin,
|
||||
|
||||
+1
-14
@@ -2,12 +2,9 @@ package me.neznamy.tab.platforms.paper_1_21_4;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ComponentConverter;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ImplementationProvider;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.viaversion.ViaScoreboard;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.viaversion.ViaTabList;
|
||||
import me.neznamy.tab.shared.platform.Scoreboard;
|
||||
import me.neznamy.tab.shared.platform.TabList;
|
||||
import me.neznamy.tab.shared.util.function.FunctionWithException;
|
||||
@@ -15,7 +12,7 @@ import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Implementation provider using direct Mojang-mapped NMS code for versions 1.21.4 - 1.21.6.
|
||||
* Implementation provider using direct Mojang-mapped NMS code for versions 1.21.4 - 1.21.8.
|
||||
*/
|
||||
@Getter
|
||||
public class PaperImplementationProvider implements ImplementationProvider {
|
||||
@@ -29,16 +26,6 @@ public class PaperImplementationProvider implements ImplementationProvider {
|
||||
return new PaperPacketScoreboard(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSend(@NonNull Object packet, @NonNull ViaScoreboard scoreboard) {
|
||||
PaperPacketScoreboard.onPacketSend(packet, scoreboard);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSend(@NonNull Object packet, @NonNull ViaTabList tabList) {
|
||||
PaperPacketTabList.onPacketSend(packet, tabList);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public TabList newTabList(@NotNull BukkitTabPlayer player) {
|
||||
|
||||
+27
-31
@@ -33,35 +33,6 @@ public class PaperPacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
private static final Scoreboard dummyScoreboard = new Scoreboard();
|
||||
private static final Field players = ReflectionUtils.getOnlyField(ClientboundSetPlayerTeamPacket.class, Collection.class);
|
||||
|
||||
@SneakyThrows
|
||||
public static void onPacketSend(@NonNull Object packet, @NonNull SafeScoreboard<BukkitTabPlayer> scoreboard) {
|
||||
if (packet instanceof ClientboundSetDisplayObjectivePacket display) {
|
||||
TAB.getInstance().getFeatureManager().onDisplayObjective(scoreboard.getPlayer(), display.getSlot().ordinal(), display.getObjectiveName());
|
||||
}
|
||||
if (packet instanceof ClientboundSetObjectivePacket objective) {
|
||||
TAB.getInstance().getFeatureManager().onObjective(scoreboard.getPlayer(), objective.getMethod(), objective.getObjectiveName());
|
||||
}
|
||||
if (packet instanceof ClientboundSetPlayerTeamPacket team) {
|
||||
int action = getMethod(team);
|
||||
if (action == TeamAction.UPDATE) return;
|
||||
players.set(team, scoreboard.onTeamPacket(action, team.getName(), team.getPlayers() == null ? Collections.emptyList() : team.getPlayers()));
|
||||
}
|
||||
}
|
||||
|
||||
private static int getMethod(@NonNull ClientboundSetPlayerTeamPacket team) {
|
||||
if (team.getTeamAction() == ClientboundSetPlayerTeamPacket.Action.ADD) {
|
||||
return 0;
|
||||
} else if (team.getTeamAction() == ClientboundSetPlayerTeamPacket.Action.REMOVE) {
|
||||
return 1;
|
||||
} else if (team.getPlayerAction() == ClientboundSetPlayerTeamPacket.Action.ADD) {
|
||||
return 3;
|
||||
} else if (team.getPlayerAction() == ClientboundSetPlayerTeamPacket.Action.REMOVE) {
|
||||
return 4;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance with given player.
|
||||
*
|
||||
@@ -161,8 +132,33 @@ public class PaperPacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void onPacketSend(@NonNull Object packet) {
|
||||
onPacketSend(packet, this);
|
||||
if (packet instanceof ClientboundSetDisplayObjectivePacket display) {
|
||||
TAB.getInstance().getFeatureManager().onDisplayObjective(player, display.getSlot().ordinal(), display.getObjectiveName());
|
||||
}
|
||||
if (packet instanceof ClientboundSetObjectivePacket objective) {
|
||||
TAB.getInstance().getFeatureManager().onObjective(player, objective.getMethod(), objective.getObjectiveName());
|
||||
}
|
||||
if (packet instanceof ClientboundSetPlayerTeamPacket team) {
|
||||
int action = getMethod(team);
|
||||
if (action == TeamAction.UPDATE) return;
|
||||
players.set(team, onTeamPacket(action, team.getName(), team.getPlayers() == null ? Collections.emptyList() : team.getPlayers()));
|
||||
}
|
||||
}
|
||||
|
||||
private int getMethod(@NonNull ClientboundSetPlayerTeamPacket team) {
|
||||
if (team.getTeamAction() == ClientboundSetPlayerTeamPacket.Action.ADD) {
|
||||
return 0;
|
||||
} else if (team.getTeamAction() == ClientboundSetPlayerTeamPacket.Action.REMOVE) {
|
||||
return 1;
|
||||
} else if (team.getPlayerAction() == ClientboundSetPlayerTeamPacket.Action.ADD) {
|
||||
return 3;
|
||||
} else if (team.getPlayerAction() == ClientboundSetPlayerTeamPacket.Action.REMOVE) {
|
||||
return 4;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -172,6 +168,6 @@ public class PaperPacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
* Packet to send
|
||||
*/
|
||||
private void sendPacket(@NotNull Packet<?> packet) {
|
||||
((CraftPlayer)player.getPlayer()).getHandle().connection.sendPacket(packet);
|
||||
((CraftPlayer)player.getPlayer()).getHandle().connection.send(packet);
|
||||
}
|
||||
}
|
||||
+33
-37
@@ -38,42 +38,6 @@ public class PaperPacketTabList extends TrackedTabList<BukkitTabPlayer> {
|
||||
|
||||
private static final Field entries = ReflectionUtils.getOnlyField(ClientboundPlayerInfoUpdatePacket.class, List.class);
|
||||
|
||||
@SneakyThrows
|
||||
public static void onPacketSend(@NonNull Object packet, TrackedTabList<BukkitTabPlayer> tabList) {
|
||||
if (packet instanceof ClientboundPlayerInfoUpdatePacket info) {
|
||||
EnumSet<ClientboundPlayerInfoUpdatePacket.Action> actions = info.actions();
|
||||
List<ClientboundPlayerInfoUpdatePacket.Entry> updatedList = new ArrayList<>();
|
||||
boolean rewritePacket = false;
|
||||
for (ClientboundPlayerInfoUpdatePacket.Entry nmsData : info.entries()) {
|
||||
boolean rewriteEntry = false;
|
||||
Component displayName = nmsData.displayName();
|
||||
int latency = nmsData.latency();
|
||||
if (actions.contains(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME)) {
|
||||
TabComponent expectedDisplayName = tabList.getExpectedDisplayNames().get(nmsData.profileId());
|
||||
if (expectedDisplayName != null && expectedDisplayName.convert() != displayName) {
|
||||
displayName = expectedDisplayName.convert();
|
||||
rewriteEntry = rewritePacket = true;
|
||||
}
|
||||
}
|
||||
if (actions.contains(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY)) {
|
||||
int newLatency = TAB.getInstance().getFeatureManager().onLatencyChange(tabList.getPlayer(), nmsData.profileId(), latency);
|
||||
if (newLatency != latency) {
|
||||
latency = newLatency;
|
||||
rewriteEntry = rewritePacket = true;
|
||||
}
|
||||
}
|
||||
if (actions.contains(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER)) {
|
||||
TAB.getInstance().getFeatureManager().onEntryAdd(tabList.getPlayer(), nmsData.profileId(), nmsData.profile().getName());
|
||||
}
|
||||
updatedList.add(rewriteEntry ? new ClientboundPlayerInfoUpdatePacket.Entry(
|
||||
nmsData.profileId(), nmsData.profile(), nmsData.listed(), latency, nmsData.gameMode(), displayName,
|
||||
nmsData.showHat(), nmsData.listOrder(), nmsData.chatSession()
|
||||
) : nmsData);
|
||||
}
|
||||
if (rewritePacket) entries.set(info, updatedList);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance.
|
||||
*
|
||||
@@ -145,8 +109,40 @@ public class PaperPacketTabList extends TrackedTabList<BukkitTabPlayer> {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void onPacketSend(@NonNull Object packet) {
|
||||
onPacketSend(packet, this);
|
||||
if (packet instanceof ClientboundPlayerInfoUpdatePacket info) {
|
||||
EnumSet<ClientboundPlayerInfoUpdatePacket.Action> actions = info.actions();
|
||||
List<ClientboundPlayerInfoUpdatePacket.Entry> updatedList = new ArrayList<>();
|
||||
boolean rewritePacket = false;
|
||||
for (ClientboundPlayerInfoUpdatePacket.Entry nmsData : info.entries()) {
|
||||
boolean rewriteEntry = false;
|
||||
Component displayName = nmsData.displayName();
|
||||
int latency = nmsData.latency();
|
||||
if (actions.contains(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME)) {
|
||||
TabComponent expectedDisplayName = getExpectedDisplayNames().get(nmsData.profileId());
|
||||
if (expectedDisplayName != null && expectedDisplayName.convert() != displayName) {
|
||||
displayName = expectedDisplayName.convert();
|
||||
rewriteEntry = rewritePacket = true;
|
||||
}
|
||||
}
|
||||
if (actions.contains(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY)) {
|
||||
int newLatency = TAB.getInstance().getFeatureManager().onLatencyChange(player, nmsData.profileId(), latency);
|
||||
if (newLatency != latency) {
|
||||
latency = newLatency;
|
||||
rewriteEntry = rewritePacket = true;
|
||||
}
|
||||
}
|
||||
if (actions.contains(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER)) {
|
||||
TAB.getInstance().getFeatureManager().onEntryAdd(player, nmsData.profileId(), nmsData.profile().getName());
|
||||
}
|
||||
updatedList.add(rewriteEntry ? new ClientboundPlayerInfoUpdatePacket.Entry(
|
||||
nmsData.profileId(), nmsData.profile(), nmsData.listed(), latency, nmsData.gameMode(), displayName,
|
||||
nmsData.showHat(), nmsData.listOrder(), nmsData.chatSession()
|
||||
) : nmsData);
|
||||
}
|
||||
if (rewritePacket) entries.set(info, updatedList);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendPacket(@NonNull EnumSet<ClientboundPlayerInfoUpdatePacket.Action> action, @NonNull UUID id, @NonNull String name, @Nullable Skin skin,
|
||||
|
||||
@@ -23,6 +23,6 @@ public class BukkitPipelineInjector extends NettyPipelineInjector {
|
||||
@NotNull
|
||||
@SneakyThrows
|
||||
protected Channel getChannel(@NotNull TabPlayer player) {
|
||||
return ((BukkitPlatform)player.getPlatform()).getServerImplementationProvider().getChannelFunction().apply((BukkitTabPlayer) player);
|
||||
return ((BukkitPlatform)player.getPlatform()).getImplementationProvider().getChannelFunction().apply((BukkitTabPlayer) player);
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,7 @@ public class BukkitTabPlayer extends BackendTabPlayer {
|
||||
|
||||
@Override
|
||||
public int getPing() {
|
||||
return getPlatform().getServerImplementationProvider().getPing(this);
|
||||
return getPlatform().getImplementationProvider().getPing(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package me.neznamy.tab.platforms.bukkit.platform;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.SneakyThrows;
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import me.neznamy.chat.component.*;
|
||||
@@ -14,7 +15,6 @@ import me.neznamy.tab.platforms.bukkit.provider.ImplementationProvider;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.bukkit.BukkitImplementationProvider;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.bukkit.PaperScoreboard;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.reflection.ReflectionImplementationProvider;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.viaversion.ViaVersionProvider;
|
||||
import me.neznamy.tab.shared.GroupManager;
|
||||
import me.neznamy.tab.shared.ProtocolVersion;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
@@ -67,7 +67,6 @@ public class BukkitPlatform implements BackendPlatform {
|
||||
private final JavaPlugin plugin;
|
||||
|
||||
/** Server version */
|
||||
@Getter
|
||||
private final ProtocolVersion serverVersion = ProtocolVersion.fromFriendlyName(Bukkit.getBukkitVersion().split("-")[0]);
|
||||
|
||||
/** Variables checking presence of other plugins to hook into */
|
||||
@@ -84,13 +83,8 @@ public class BukkitPlatform implements BackendPlatform {
|
||||
|
||||
/** Implementation for creating new instances using content available on the server */
|
||||
@NotNull
|
||||
private final ImplementationProvider serverImplementationProvider = findImplementationProvider();
|
||||
|
||||
/** Implementation for sending new content to new players on old servers */
|
||||
@Nullable
|
||||
private final ViaVersionProvider viaVersionProvider =
|
||||
ReflectionUtils.classExists("com.viaversion.viaversion.protocols.v1_20_2to1_20_3.Protocol1_20_2To1_20_3") ?
|
||||
new ViaVersionProvider(serverVersion) : null;
|
||||
@Setter
|
||||
private ImplementationProvider implementationProvider = findImplementationProvider();
|
||||
|
||||
private final boolean modernOnlinePlayers;
|
||||
|
||||
@@ -161,7 +155,7 @@ public class BukkitPlatform implements BackendPlatform {
|
||||
}
|
||||
Bukkit.getConsoleSender().sendMessage("§c[TAB] Please use " +
|
||||
"a plugin version with full support for your server version for optimal experience. This plugin version " +
|
||||
"has full support for 1.8.8, 1.12.x, 1.16.5, 1.17.x, 1.18.2 and 1.19.1 - 1.21.6.");
|
||||
"has full support for 1.8.8, 1.12.x, 1.16.5, 1.17.x, 1.18.2 and 1.19.1 - 1.21.8.");
|
||||
}
|
||||
return new BukkitImplementationProvider();
|
||||
}
|
||||
@@ -189,6 +183,8 @@ public class BukkitPlatform implements BackendPlatform {
|
||||
case V1_21_4:
|
||||
case V1_21_5:
|
||||
case V1_21_6:
|
||||
case V1_21_7:
|
||||
case V1_21_8:
|
||||
return "1_21_4";
|
||||
default:
|
||||
return null;
|
||||
@@ -223,7 +219,7 @@ public class BukkitPlatform implements BackendPlatform {
|
||||
@Override
|
||||
@Nullable
|
||||
public PipelineInjector createPipelineInjector() {
|
||||
return serverImplementationProvider.getChannelFunction() != null ? new BukkitPipelineInjector() : null;
|
||||
return implementationProvider.getChannelFunction() != null ? new BukkitPipelineInjector() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -323,8 +319,8 @@ public class BukkitPlatform implements BackendPlatform {
|
||||
Metrics metrics = new Metrics(plugin, TabConstants.BSTATS_PLUGIN_ID_BUKKIT);
|
||||
metrics.addCustomChart(new SimplePie(TabConstants.MetricsChart.PERMISSION_SYSTEM,
|
||||
() -> TAB.getInstance().getGroupManager().getPermissionPlugin()));
|
||||
metrics.addCustomChart(new SimplePie(TabConstants.MetricsChart.SERVER_VERSION,
|
||||
() -> "1." + serverVersion.getMinorVersion() + ".x"));
|
||||
String version = serverVersion == ProtocolVersion.UNKNOWN ? "Unknown" : "1." + serverVersion.getMinorVersion() + ".x";
|
||||
metrics.addCustomChart(new SimplePie(TabConstants.MetricsChart.SERVER_VERSION, () -> version));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -336,8 +332,8 @@ public class BukkitPlatform implements BackendPlatform {
|
||||
@Override
|
||||
@NotNull
|
||||
public Object convertComponent(@NotNull TabComponent component) {
|
||||
if (serverImplementationProvider.getComponentConverter() != null) {
|
||||
return serverImplementationProvider.getComponentConverter().convert(component);
|
||||
if (implementationProvider.getComponentConverter() != null) {
|
||||
return implementationProvider.getComponentConverter().convert(component);
|
||||
} else {
|
||||
return component;
|
||||
}
|
||||
@@ -345,13 +341,8 @@ public class BukkitPlatform implements BackendPlatform {
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
@SneakyThrows
|
||||
public Scoreboard createScoreboard(@NotNull TabPlayer player) {
|
||||
if (viaVersionProvider != null) {
|
||||
Scoreboard scoreboard = viaVersionProvider.newScoreboard((BukkitTabPlayer) player);
|
||||
if (scoreboard != null) return scoreboard;
|
||||
}
|
||||
return serverImplementationProvider.newScoreboard((BukkitTabPlayer) player);
|
||||
return implementationProvider.newScoreboard((BukkitTabPlayer) player);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -372,13 +363,8 @@ public class BukkitPlatform implements BackendPlatform {
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
@SneakyThrows
|
||||
public TabList createTabList(@NotNull TabPlayer player) {
|
||||
if (viaVersionProvider != null) {
|
||||
TabList tabList = viaVersionProvider.newTabList((BukkitTabPlayer) player);
|
||||
if (tabList != null) return tabList;
|
||||
}
|
||||
return serverImplementationProvider.newTabList((BukkitTabPlayer) player);
|
||||
return implementationProvider.newTabList((BukkitTabPlayer) player);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -386,6 +372,11 @@ public class BukkitPlatform implements BackendPlatform {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsListOrder() {
|
||||
return serverVersion.getNetworkId() >= ProtocolVersion.V1_21_2.getNetworkId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSafeFromPacketEventsBug() {
|
||||
return serverVersion.getMinorVersion() >= 13;
|
||||
|
||||
-7
@@ -1,10 +1,7 @@
|
||||
package me.neznamy.tab.platforms.bukkit.provider;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.viaversion.ViaScoreboard;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.viaversion.ViaTabList;
|
||||
import me.neznamy.tab.shared.platform.Scoreboard;
|
||||
import me.neznamy.tab.shared.platform.TabList;
|
||||
import me.neznamy.tab.shared.util.function.FunctionWithException;
|
||||
@@ -16,10 +13,6 @@ public interface ImplementationProvider {
|
||||
@NotNull
|
||||
Scoreboard newScoreboard(@NotNull BukkitTabPlayer player);
|
||||
|
||||
void onPacketSend(@NonNull Object packet, @NonNull ViaScoreboard scoreboard);
|
||||
|
||||
void onPacketSend(@NonNull Object packet, @NonNull ViaTabList tabList);
|
||||
|
||||
@NotNull
|
||||
TabList newTabList(@NotNull BukkitTabPlayer player);
|
||||
|
||||
|
||||
-13
@@ -2,12 +2,9 @@ package me.neznamy.tab.platforms.bukkit.provider.bukkit;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ComponentConverter;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ImplementationProvider;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.viaversion.ViaScoreboard;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.viaversion.ViaTabList;
|
||||
import me.neznamy.tab.shared.platform.Scoreboard;
|
||||
import me.neznamy.tab.shared.platform.TabList;
|
||||
import me.neznamy.tab.shared.platform.impl.DummyScoreboard;
|
||||
@@ -40,16 +37,6 @@ public class BukkitImplementationProvider implements ImplementationProvider {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSend(@NonNull Object packet, @NonNull ViaScoreboard scoreboard) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSend(@NonNull Object packet, @NonNull ViaTabList tabList) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public TabList newTabList(@NotNull BukkitTabPlayer player) {
|
||||
|
||||
+10
-14
@@ -136,19 +136,6 @@ public class PacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
}
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public static void onPacketSend(@NonNull Object packet, @NonNull SafeScoreboard<BukkitTabPlayer> scoreboard) {
|
||||
if (DisplayObjectiveClass.isInstance(packet)) {
|
||||
TAB.getInstance().getFeatureManager().onDisplayObjective(scoreboard.getPlayer(), packetToSlot.apply(packet),
|
||||
(String) DisplayObjective_OBJECTIVE_NAME.get(packet));
|
||||
}
|
||||
if (ObjectivePacketClass.isInstance(packet)) {
|
||||
TAB.getInstance().getFeatureManager().onObjective(scoreboard.getPlayer(),
|
||||
Objective_METHOD.getInt(packet), (String) Objective_OBJECTIVE_NAME.get(packet));
|
||||
}
|
||||
teamPacketData.onPacketSend(scoreboard.getPlayer(), packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance with given player.
|
||||
*
|
||||
@@ -227,8 +214,17 @@ public class PacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void onPacketSend(@NonNull Object packet) {
|
||||
onPacketSend(packet, this);
|
||||
if (DisplayObjectiveClass.isInstance(packet)) {
|
||||
TAB.getInstance().getFeatureManager().onDisplayObjective(player, packetToSlot.apply(packet),
|
||||
(String) DisplayObjective_OBJECTIVE_NAME.get(packet));
|
||||
}
|
||||
if (ObjectivePacketClass.isInstance(packet)) {
|
||||
TAB.getInstance().getFeatureManager().onObjective(player,
|
||||
Objective_METHOD.getInt(packet), (String) Objective_OBJECTIVE_NAME.get(packet));
|
||||
}
|
||||
teamPacketData.onPacketSend(player, packet);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
|
||||
+44
-53
@@ -157,52 +157,6 @@ public class PacketTabList extends TrackedTabList<BukkitTabPlayer> {
|
||||
}
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public static void onPacketSend(@NonNull Object packet, @NonNull TrackedTabList<BukkitTabPlayer> tabList) {
|
||||
if (!(PlayerInfoClass.isInstance(packet))) return;
|
||||
EnumSet<?> actions = (EnumSet<?>) ACTION.get(packet);
|
||||
List<Object> updatedList = new ArrayList<>();
|
||||
boolean rewritePacket = false;
|
||||
for (Object nmsData : (List<?>) PLAYERS.get(packet)) {
|
||||
boolean rewriteEntry = false;
|
||||
UUID id = (UUID) PlayerInfoData_UUID.get(nmsData);
|
||||
GameProfile profile = (GameProfile) PlayerInfoData_Profile.get(nmsData);
|
||||
Object displayName = PlayerInfoData_DisplayName.get(nmsData);
|
||||
int latency = PlayerInfoData_Latency.getInt(nmsData);
|
||||
int listOrder = v1_21_2Plus ? PlayerInfoData_ListOrder.getInt(nmsData) : 0;
|
||||
boolean showHat = v1_21_4Plus && PlayerInfoData_ShowHat.getBoolean(nmsData);
|
||||
if (actions.contains(actionUpdateDisplayName)) {
|
||||
TabComponent expectedName = tabList.getExpectedDisplayNames().get(id);
|
||||
if (expectedName != null && expectedName.convert() != displayName) {
|
||||
displayName = expectedName.convert();
|
||||
rewriteEntry = rewritePacket = true;
|
||||
}
|
||||
}
|
||||
if (actions.contains(actionUpdateLatency)) {
|
||||
int newLatency = TAB.getInstance().getFeatureManager().onLatencyChange(tabList.getPlayer(), id, latency);
|
||||
if (newLatency != latency) {
|
||||
latency = newLatency;
|
||||
rewriteEntry = rewritePacket = true;
|
||||
}
|
||||
}
|
||||
if (actions.contains(actionAddPlayer)) {
|
||||
TAB.getInstance().getFeatureManager().onEntryAdd(tabList.getPlayer(), id, profile.getName());
|
||||
}
|
||||
// 1.19.3 is using records, which do not allow changing final fields, need to rewrite the list entirely
|
||||
updatedList.add(rewriteEntry ? newPlayerInfoData(
|
||||
id,
|
||||
profile,
|
||||
PlayerInfoData_Listed.getBoolean(nmsData),
|
||||
latency,
|
||||
PlayerInfoData_GameMode.get(nmsData),
|
||||
displayName,
|
||||
showHat,
|
||||
listOrder,
|
||||
PlayerInfoData_RemoteChatSession.get(nmsData)) : nmsData);
|
||||
}
|
||||
if (rewritePacket) PLAYERS.set(packet, updatedList);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void removeEntry(@NonNull UUID entry) {
|
||||
@@ -282,8 +236,50 @@ public class PacketTabList extends TrackedTabList<BukkitTabPlayer> {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void onPacketSend(@NonNull Object packet) {
|
||||
onPacketSend(packet, this);
|
||||
if (!(PlayerInfoClass.isInstance(packet))) return;
|
||||
EnumSet<?> actions = (EnumSet<?>) ACTION.get(packet);
|
||||
List<Object> updatedList = new ArrayList<>();
|
||||
boolean rewritePacket = false;
|
||||
for (Object nmsData : (List<?>) PLAYERS.get(packet)) {
|
||||
boolean rewriteEntry = false;
|
||||
UUID id = (UUID) PlayerInfoData_UUID.get(nmsData);
|
||||
GameProfile profile = (GameProfile) PlayerInfoData_Profile.get(nmsData);
|
||||
Object displayName = PlayerInfoData_DisplayName.get(nmsData);
|
||||
int latency = PlayerInfoData_Latency.getInt(nmsData);
|
||||
int listOrder = v1_21_2Plus ? PlayerInfoData_ListOrder.getInt(nmsData) : 0;
|
||||
boolean showHat = v1_21_4Plus && PlayerInfoData_ShowHat.getBoolean(nmsData);
|
||||
if (actions.contains(actionUpdateDisplayName)) {
|
||||
TabComponent expectedName = getExpectedDisplayNames().get(id);
|
||||
if (expectedName != null && expectedName.convert() != displayName) {
|
||||
displayName = expectedName.convert();
|
||||
rewriteEntry = rewritePacket = true;
|
||||
}
|
||||
}
|
||||
if (actions.contains(actionUpdateLatency)) {
|
||||
int newLatency = TAB.getInstance().getFeatureManager().onLatencyChange(player, id, latency);
|
||||
if (newLatency != latency) {
|
||||
latency = newLatency;
|
||||
rewriteEntry = rewritePacket = true;
|
||||
}
|
||||
}
|
||||
if (actions.contains(actionAddPlayer)) {
|
||||
TAB.getInstance().getFeatureManager().onEntryAdd(player, id, profile.getName());
|
||||
}
|
||||
// 1.19.3 is using records, which do not allow changing final fields, need to rewrite the list entirely
|
||||
updatedList.add(rewriteEntry ? newPlayerInfoData(
|
||||
id,
|
||||
profile,
|
||||
PlayerInfoData_Listed.getBoolean(nmsData),
|
||||
latency,
|
||||
PlayerInfoData_GameMode.get(nmsData),
|
||||
displayName,
|
||||
showHat,
|
||||
listOrder,
|
||||
PlayerInfoData_RemoteChatSession.get(nmsData)) : nmsData);
|
||||
}
|
||||
if (rewritePacket) PLAYERS.set(packet, updatedList);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -327,13 +323,8 @@ public class PacketTabList extends TrackedTabList<BukkitTabPlayer> {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Skin getSkin() {
|
||||
return getSkin(player);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@SneakyThrows
|
||||
public static Skin getSkin(@NotNull BukkitTabPlayer player) {
|
||||
public Skin getSkin() {
|
||||
Collection<Property> col = ((GameProfile) getProfile.invoke(player.getHandle())).getProperties().get(TabList.TEXTURES_PROPERTY);
|
||||
if (col.isEmpty()) return null; //offline mode
|
||||
Property property = col.iterator().next();
|
||||
|
||||
-13
@@ -2,13 +2,10 @@ package me.neznamy.tab.platforms.bukkit.provider.reflection;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitReflection;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ComponentConverter;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ImplementationProvider;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.viaversion.ViaScoreboard;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.viaversion.ViaTabList;
|
||||
import me.neznamy.tab.shared.platform.Scoreboard;
|
||||
import me.neznamy.tab.shared.platform.TabList;
|
||||
import me.neznamy.tab.shared.util.ReflectionUtils;
|
||||
@@ -64,16 +61,6 @@ public class ReflectionImplementationProvider implements ImplementationProvider
|
||||
return new PacketScoreboard(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSend(@NonNull Object packet, @NonNull ViaScoreboard scoreboard) {
|
||||
PacketScoreboard.onPacketSend(packet, scoreboard);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSend(@NonNull Object packet, @NonNull ViaTabList tabList) {
|
||||
PacketTabList.onPacketSend(packet, tabList);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public TabList newTabList(@NotNull BukkitTabPlayer player) {
|
||||
|
||||
-195
@@ -1,195 +0,0 @@
|
||||
package me.neznamy.tab.platforms.bukkit.provider.viaversion;
|
||||
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.protocol.Protocol;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketType;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.protocol.packet.State;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.chat.component.TabComponent;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.platforms.bukkit.platform.BukkitPlatform;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.platform.decorators.SafeScoreboard;
|
||||
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Scoreboard abstract implementation using ViaVersion packets,
|
||||
* focused to unlock new features on older versions, and also
|
||||
* optimize packet conversion between versions.
|
||||
*/
|
||||
public abstract class ViaScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
|
||||
private static final long CHECK_DELAY = 50;
|
||||
private static final Object DUMMY = new Object();
|
||||
|
||||
protected final Class<? extends Protocol> protocol;
|
||||
protected final PacketType setDisplayObjective;
|
||||
private final PacketType setObjective;
|
||||
protected final PacketType setScore;
|
||||
private final PacketType setPlayerTeam;
|
||||
/** User connection this scoreboard belongs to */
|
||||
protected final UserConnection connection;
|
||||
|
||||
private transient ScheduledFuture<?> task;
|
||||
private transient final Queue<PacketWrapper> queuedPackets = new ConcurrentLinkedQueue<>();
|
||||
|
||||
/**
|
||||
* Constructs new instance with given player.
|
||||
*
|
||||
* @param player
|
||||
* Player this scoreboard will belong to
|
||||
* @param protocol
|
||||
* Protocol to be sent packets through
|
||||
* @param setDisplayObjective
|
||||
* Objective creation packet
|
||||
* @param setObjective
|
||||
* Objective update packet
|
||||
* @param setScore
|
||||
* Score update packet
|
||||
* @param setPlayerTeam
|
||||
* Player team packet
|
||||
*/
|
||||
public ViaScoreboard(@NonNull BukkitTabPlayer player, @NonNull Class<? extends Protocol> protocol, @NonNull PacketType setDisplayObjective, @NonNull PacketType setObjective, @NonNull PacketType setScore, @NonNull PacketType setPlayerTeam) {
|
||||
super(player);
|
||||
this.protocol = protocol;
|
||||
this.setDisplayObjective = setDisplayObjective;
|
||||
this.setObjective = setObjective;
|
||||
this.setScore = setScore;
|
||||
this.setPlayerTeam = setPlayerTeam;
|
||||
this.connection = Via.getManager().getConnectionManager().getConnectedClient(player.getUniqueId());
|
||||
|
||||
// Queue packets until connection is available
|
||||
// Is important to use scheduleWithFixedDelay() to avoid task overlap
|
||||
task = connection.getChannel().eventLoop().scheduleWithFixedDelay(() -> {
|
||||
if (connection.getProtocolInfo().getClientState() == State.PLAY) {
|
||||
PacketWrapper packet;
|
||||
while ((packet = queuedPackets.poll()) != null) {
|
||||
packet.send(protocol);
|
||||
}
|
||||
task.cancel(true);
|
||||
}
|
||||
}, 0L, CHECK_DELAY, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerObjective(@NonNull Objective objective) {
|
||||
sendObjectiveUpdate(ObjectiveAction.REGISTER, objective);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterObjective(@NonNull Objective objective) {
|
||||
sendObjectiveUpdate(ObjectiveAction.UNREGISTER, objective);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateObjective(@NonNull Objective objective) {
|
||||
sendObjectiveUpdate(ObjectiveAction.UPDATE, objective);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull Object createTeam(@NonNull String name) {
|
||||
// This implementation does not use team objects
|
||||
return DUMMY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerTeam(@NonNull Team team) {
|
||||
sendTeamUpdate(TeamAction.CREATE, team);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterTeam(@NonNull Team team) {
|
||||
sendTeamUpdate(TeamAction.REMOVE, team);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTeam(@NonNull Team team) {
|
||||
sendTeamUpdate(TeamAction.UPDATE, team);
|
||||
}
|
||||
|
||||
protected void sendObjectiveUpdate(int mode, @NonNull Objective objective) {
|
||||
final PacketWrapper packet = PacketWrapper.create(setObjective, null, connection);
|
||||
|
||||
// Objective name
|
||||
packet.write(Types.STRING, objective.getName());
|
||||
// Mode
|
||||
packet.write(Types.BYTE, (byte) mode);
|
||||
// Optional
|
||||
if (mode == ObjectiveAction.REGISTER || mode == ObjectiveAction.UPDATE) {
|
||||
writeObjectiveDisplay(packet, objective);
|
||||
}
|
||||
|
||||
send(packet);
|
||||
}
|
||||
|
||||
@SuppressWarnings("fallthrough")
|
||||
protected void sendTeamUpdate(int mode, @NonNull Team team) {
|
||||
final PacketWrapper packet = PacketWrapper.create(setPlayerTeam, null, connection);
|
||||
|
||||
// Team name (max 16 characters on pre 1.20.3)
|
||||
packet.write(Types.STRING, team.getName());
|
||||
// Method
|
||||
packet.write(Types.BYTE, (byte) mode);
|
||||
switch (mode) {
|
||||
case TeamAction.REMOVE:
|
||||
break;
|
||||
case TeamAction.CREATE:
|
||||
case TeamAction.UPDATE:
|
||||
// Team display name
|
||||
writeComponent(packet, TabComponent.legacyText(team.getName()));
|
||||
// Friendly flags
|
||||
packet.write(Types.BYTE, (byte) team.getOptions());
|
||||
// Name tag visibility
|
||||
packet.write(Types.STRING, team.getVisibility().toString());
|
||||
// Collision rule
|
||||
packet.write(Types.STRING, team.getCollision().toString());
|
||||
// Team color
|
||||
packet.write(Types.VAR_INT, team.getColor().getLegacyColor().ordinal());
|
||||
// Team prefix
|
||||
writeComponent(packet, team.getPrefix());
|
||||
// Team suffix
|
||||
writeComponent(packet, team.getSuffix());
|
||||
if (mode == TeamAction.UPDATE) {
|
||||
break;
|
||||
}
|
||||
// Intentional fallthrough for CREATE mode
|
||||
case TeamAction.ADD_PLAYER:
|
||||
case TeamAction.REMOVE_PLAYER:
|
||||
// Entities
|
||||
packet.write(Types.VAR_INT, team.getPlayers().size());
|
||||
for (String entity : team.getPlayers()) {
|
||||
// Entity (player username in this case) (max 40 characters on pre 1.20.3)
|
||||
packet.write(Types.STRING, entity);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid team update mode: " + mode);
|
||||
}
|
||||
|
||||
send(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSend(@NonNull Object packet) {
|
||||
((BukkitPlatform) TAB.getInstance().getPlatform()).getServerImplementationProvider().onPacketSend(packet, this);
|
||||
}
|
||||
|
||||
protected abstract void writeComponent(@NonNull PacketWrapper packet, @NonNull TabComponent component);
|
||||
|
||||
protected abstract void writeObjectiveDisplay(@NonNull PacketWrapper packet, @NonNull Objective objective);
|
||||
|
||||
protected void send(@NonNull PacketWrapper packet) {
|
||||
if (!task.isCancelled()) {
|
||||
queuedPackets.add(packet);
|
||||
} else {
|
||||
packet.scheduleSend(protocol);
|
||||
}
|
||||
}
|
||||
}
|
||||
-82
@@ -1,82 +0,0 @@
|
||||
package me.neznamy.tab.platforms.bukkit.provider.viaversion;
|
||||
|
||||
import com.viaversion.viaversion.api.protocol.Protocol;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketType;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.protocols.v1_12_2to1_13.Protocol1_12_2To1_13;
|
||||
import com.viaversion.viaversion.protocols.v1_12_2to1_13.packet.ClientboundPackets1_13;
|
||||
import com.viaversion.viaversion.util.ComponentUtil;
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.chat.component.TabComponent;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
|
||||
/**
|
||||
* Scoreboard implementation using ViaVersion packets
|
||||
* to unlock +1.13 player features on pre 1.13 servers.
|
||||
*/
|
||||
public class ViaScoreboard113 extends ViaScoreboard {
|
||||
|
||||
/**
|
||||
* Constructs new instance with given player.
|
||||
*
|
||||
* @param player Player this scoreboard will belong to
|
||||
*/
|
||||
public ViaScoreboard113(@NonNull BukkitTabPlayer player) {
|
||||
this(player, Protocol1_12_2To1_13.class, ClientboundPackets1_13.SET_DISPLAY_OBJECTIVE, ClientboundPackets1_13.SET_OBJECTIVE, ClientboundPackets1_13.SET_SCORE, ClientboundPackets1_13.SET_PLAYER_TEAM);
|
||||
}
|
||||
|
||||
protected ViaScoreboard113(@NonNull BukkitTabPlayer player, @NonNull Class<? extends Protocol> protocol, @NonNull PacketType setDisplayObjective, @NonNull PacketType setObjective, @NonNull PacketType setScore, @NonNull PacketType setPlayerTeam) {
|
||||
super(player, protocol, setDisplayObjective, setObjective, setScore, setPlayerTeam);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDisplaySlot(@NonNull Objective objective) {
|
||||
PacketWrapper packet = PacketWrapper.create(setDisplayObjective, null, connection);
|
||||
|
||||
packet.write(Types.BYTE, (byte) objective.getDisplaySlot().ordinal());
|
||||
packet.write(Types.STRING, objective.getName());
|
||||
|
||||
send(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScore(@NonNull Score score) {
|
||||
sendScoreUpdate(ScoreAction.CHANGE, score);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeScore(@NonNull Score score) {
|
||||
sendScoreUpdate(ScoreAction.REMOVE, score);
|
||||
}
|
||||
|
||||
protected void sendScoreUpdate(int action, @NonNull Score score) {
|
||||
final PacketWrapper packet = PacketWrapper.create(setScore, null, connection);
|
||||
|
||||
// Entity name (player username in this case)
|
||||
packet.write(Types.STRING, score.getHolder());
|
||||
// Action
|
||||
packet.write(Types.VAR_INT, action);
|
||||
// Objective name (max 16 characters)
|
||||
packet.write(Types.STRING, score.getObjective().getName());
|
||||
if (action == 0) {
|
||||
// Value
|
||||
packet.write(Types.VAR_INT, score.getValue());
|
||||
}
|
||||
|
||||
send(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeComponent(@NonNull PacketWrapper packet, @NonNull TabComponent component) {
|
||||
packet.write(Types.COMPONENT, ComponentUtil.legacyToJson(component.toLegacyText()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeObjectiveDisplay(@NonNull PacketWrapper packet, @NonNull Objective objective) {
|
||||
// Objective value
|
||||
writeComponent(packet, objective.getTitle());
|
||||
// Type
|
||||
packet.write(Types.VAR_INT, objective.getHealthDisplay() == HealthDisplay.INTEGER ? 0 : 1);
|
||||
}
|
||||
}
|
||||
-36
@@ -1,36 +0,0 @@
|
||||
package me.neznamy.tab.platforms.bukkit.provider.viaversion;
|
||||
|
||||
import com.viaversion.viaversion.api.protocol.Protocol;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketType;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.protocols.v1_15_2to1_16.Protocol1_15_2To1_16;
|
||||
import com.viaversion.viaversion.protocols.v1_15_2to1_16.packet.ClientboundPackets1_16;
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.chat.component.TabComponent;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
|
||||
/**
|
||||
* Scoreboard implementation using ViaVersion packets
|
||||
* to unlock +1.16 player features on pre 1.16 servers.
|
||||
*/
|
||||
public class ViaScoreboard116 extends ViaScoreboard113 {
|
||||
|
||||
/**
|
||||
* Constructs new instance with given player.
|
||||
*
|
||||
* @param player Player this scoreboard will belong to
|
||||
*/
|
||||
public ViaScoreboard116(@NonNull BukkitTabPlayer player) {
|
||||
this(player, Protocol1_15_2To1_16.class, ClientboundPackets1_16.SET_DISPLAY_OBJECTIVE, ClientboundPackets1_16.SET_OBJECTIVE, ClientboundPackets1_16.SET_SCORE, ClientboundPackets1_16.SET_PLAYER_TEAM);
|
||||
}
|
||||
|
||||
protected ViaScoreboard116(@NonNull BukkitTabPlayer player, @NonNull Class<? extends Protocol> protocol, @NonNull PacketType setDisplayObjective, @NonNull PacketType setObjective, @NonNull PacketType setScore, @NonNull PacketType setPlayerTeam) {
|
||||
super(player, protocol, setDisplayObjective, setObjective, setScore, setPlayerTeam);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeComponent(@NonNull PacketWrapper packet, @NonNull TabComponent component) {
|
||||
packet.write(Types.COMPONENT, component.toViaVersion());
|
||||
}
|
||||
}
|
||||
-101
@@ -1,101 +0,0 @@
|
||||
package me.neznamy.tab.platforms.bukkit.provider.viaversion;
|
||||
|
||||
import com.viaversion.viaversion.api.protocol.Protocol;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketType;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.Protocol1_20_2To1_20_3;
|
||||
import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.packet.ClientboundPackets1_20_3;
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.chat.component.TabComponent;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Scoreboard implementation using ViaVersion packets
|
||||
* to unlock +1.20.3 player features on pre 1.20.3 servers.
|
||||
*/
|
||||
public class ViaScoreboard1203 extends ViaScoreboard116 {
|
||||
|
||||
private final PacketType resetScore;
|
||||
|
||||
/**
|
||||
* Constructs new instance with given player.
|
||||
*
|
||||
* @param player Player this scoreboard will belong to
|
||||
*/
|
||||
public ViaScoreboard1203(@NonNull BukkitTabPlayer player) {
|
||||
this(player, Protocol1_20_2To1_20_3.class, ClientboundPackets1_20_3.SET_DISPLAY_OBJECTIVE, ClientboundPackets1_20_3.SET_OBJECTIVE, ClientboundPackets1_20_3.SET_SCORE, ClientboundPackets1_20_3.RESET_SCORE, ClientboundPackets1_20_3.SET_PLAYER_TEAM);
|
||||
}
|
||||
|
||||
protected ViaScoreboard1203(@NonNull BukkitTabPlayer player, @NonNull Class<? extends Protocol> protocol, @NonNull PacketType setDisplayObjective, @NonNull PacketType setObjective, @NonNull PacketType setScore, @NonNull PacketType resetScore, @NonNull PacketType setPlayerTeam) {
|
||||
super(player, protocol, setDisplayObjective, setObjective, setScore, setPlayerTeam);
|
||||
this.resetScore = resetScore;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDisplaySlot(@NonNull Objective objective) {
|
||||
PacketWrapper packet = PacketWrapper.create(setDisplayObjective, null, connection);
|
||||
|
||||
packet.write(Types.VAR_INT, objective.getDisplaySlot().ordinal());
|
||||
packet.write(Types.STRING, objective.getName());
|
||||
|
||||
send(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScore(@NonNull Score score) {
|
||||
final PacketWrapper packet = PacketWrapper.create(setScore, null, connection);
|
||||
|
||||
// Entity name (player username in this case)
|
||||
packet.write(Types.STRING, score.getHolder());
|
||||
// Objective name
|
||||
packet.write(Types.STRING, score.getObjective().getName());
|
||||
// Value
|
||||
packet.write(Types.VAR_INT, score.getValue());
|
||||
// Display name
|
||||
packet.write(Types.OPTIONAL_TAG, score.getDisplayName() == null ? null : score.getDisplayName().toViaVersionTag());
|
||||
// Number format
|
||||
writeNumberFormat(packet, score.getNumberFormat());
|
||||
|
||||
send(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeScore(@NonNull Score score) {
|
||||
final PacketWrapper packet = PacketWrapper.create(resetScore, null, connection);
|
||||
|
||||
// Entity name (player username in this case)
|
||||
packet.write(Types.STRING, score.getHolder());
|
||||
// Objective name
|
||||
packet.write(Types.OPTIONAL_STRING, score.getObjective().getName().isEmpty() ? null : score.getObjective().getName());
|
||||
|
||||
send(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeComponent(@NonNull PacketWrapper packet, @NonNull TabComponent component) {
|
||||
packet.write(Types.TAG, component.toViaVersionTag());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeObjectiveDisplay(@NonNull PacketWrapper packet, @NonNull Objective objective) {
|
||||
super.writeObjectiveDisplay(packet, objective);
|
||||
writeNumberFormat(packet, objective.getNumberFormat());
|
||||
}
|
||||
|
||||
protected void writeNumberFormat(@NonNull PacketWrapper packet, @Nullable TabComponent content) {
|
||||
// For now, only fixed format is supported by TAB
|
||||
if (content == null) {
|
||||
// Has number format
|
||||
packet.write(Types.BOOLEAN, false);
|
||||
} else {
|
||||
// Has number format
|
||||
packet.write(Types.BOOLEAN, true);
|
||||
// Fixed format
|
||||
packet.write(Types.VAR_INT, 2);
|
||||
// Content
|
||||
packet.write(Types.TAG, content.toViaVersionTag());
|
||||
}
|
||||
}
|
||||
}
|
||||
-185
@@ -1,185 +0,0 @@
|
||||
package me.neznamy.tab.platforms.bukkit.provider.viaversion;
|
||||
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.protocol.Protocol;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketType;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.protocol.packet.State;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.chat.component.TabComponent;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.platforms.bukkit.platform.BukkitPlatform;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.reflection.PacketTabList;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.platform.decorators.TrackedTabList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.BitSet;
|
||||
import java.util.Queue;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* TabList abstract handler using ViaVersion packets,
|
||||
* focused to unlock new features on older versions,
|
||||
* and also optimize packet conversion between versions.
|
||||
*/
|
||||
public abstract class ViaTabList extends TrackedTabList<BukkitTabPlayer> {
|
||||
|
||||
private static final long CHECK_DELAY = 50;
|
||||
|
||||
protected final Class<? extends Protocol> protocol;
|
||||
private final PacketType playerInfoUpdate;
|
||||
private final PacketType tabList;
|
||||
/** User connection this tablist belongs to */
|
||||
protected final UserConnection connection;
|
||||
|
||||
private transient ScheduledFuture<?> task;
|
||||
private transient final Queue<PacketWrapper> queuedPackets = new ConcurrentLinkedQueue<>();
|
||||
|
||||
/**
|
||||
*
|
||||
* @param player
|
||||
* Player this tablist will belong to
|
||||
* @param protocol
|
||||
* Protocol to be sent packets through
|
||||
* @param playerInfoUpdate
|
||||
* Player information update packet
|
||||
* @param tabList
|
||||
* Tab list packet
|
||||
*/
|
||||
public ViaTabList(@NonNull BukkitTabPlayer player, @NonNull Class<? extends Protocol> protocol, @NonNull PacketType playerInfoUpdate, @NonNull PacketType tabList) {
|
||||
super(player);
|
||||
this.protocol = protocol;
|
||||
this.playerInfoUpdate = playerInfoUpdate;
|
||||
this.tabList = tabList;
|
||||
this.connection = Via.getManager().getConnectionManager().getConnectedClient(player.getUniqueId());
|
||||
|
||||
// Queue packets until connection is available
|
||||
// Is important to use scheduleWithFixedDelay() to avoid task overlap
|
||||
task = connection.getChannel().eventLoop().scheduleWithFixedDelay(() -> {
|
||||
if (connection.getProtocolInfo().getClientState() == State.PLAY) {
|
||||
PacketWrapper packet;
|
||||
while ((packet = queuedPackets.poll()) != null) {
|
||||
packet.send(protocol);
|
||||
}
|
||||
task.cancel(true);
|
||||
}
|
||||
}, 0L, CHECK_DELAY, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsEntry(@NonNull UUID entry) {
|
||||
return true; // TODO?
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEntry0(@NonNull Entry entry) {
|
||||
sendInfoUpdate(Action.ADD_PLAYER, entry.getUniqueId(), entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDisplayName0(@NonNull UUID entry, @Nullable TabComponent displayName) {
|
||||
sendInfoUpdate(Action.UPDATE_DISPLAY_NAME, entry, displayName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLatency(@NonNull UUID entry, int latency) {
|
||||
sendInfoUpdate(Action.UPDATE_LATENCY, entry, latency);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateGameMode(@NonNull UUID entry, int gameMode) {
|
||||
sendInfoUpdate(Action.UPDATE_GAME_MODE, entry, gameMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerListHeaderFooter(@NonNull TabComponent header, @NonNull TabComponent footer) {
|
||||
final PacketWrapper packet = PacketWrapper.create(tabList, null, connection);
|
||||
|
||||
writeComponent(packet, header);
|
||||
writeComponent(packet, footer);
|
||||
|
||||
send(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Skin getSkin() {
|
||||
return PacketTabList.getSkin(player);
|
||||
}
|
||||
|
||||
protected void sendInfoUpdate(@NonNull Action action, @NonNull UUID uniqueId, Object value) {
|
||||
final PacketWrapper packet = PacketWrapper.create(playerInfoUpdate, null, connection);
|
||||
|
||||
// Action
|
||||
writeAction(packet, action);
|
||||
// Players size
|
||||
packet.write(Types.VAR_INT, 1);
|
||||
// Players
|
||||
packet.write(Types.UUID, uniqueId);
|
||||
switch (action) {
|
||||
case ADD_PLAYER:
|
||||
writeEntry(packet, (Entry) value);
|
||||
break;
|
||||
case REMOVE_PLAYER:
|
||||
break;
|
||||
case UPDATE_GAME_MODE:
|
||||
case UPDATE_LATENCY:
|
||||
case UPDATE_LIST_ORDER:
|
||||
packet.write(Types.VAR_INT, (int) value);
|
||||
break;
|
||||
case UPDATE_LISTED:
|
||||
case UPDATE_HAT:
|
||||
packet.write(Types.BOOLEAN, (boolean) value);
|
||||
break;
|
||||
case UPDATE_DISPLAY_NAME:
|
||||
writeOptionalComponent(packet, (TabComponent) value);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Cannot send info update with action " + action.name());
|
||||
}
|
||||
|
||||
send(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSend(@NonNull Object packet) {
|
||||
((BukkitPlatform) TAB.getInstance().getPlatform()).getServerImplementationProvider().onPacketSend(packet, this);
|
||||
}
|
||||
|
||||
protected abstract void writeComponent(@NonNull PacketWrapper packet, @NonNull TabComponent component);
|
||||
|
||||
protected abstract void writeOptionalComponent(@NonNull PacketWrapper packet, @Nullable TabComponent component);
|
||||
|
||||
protected abstract void writeAction(@NonNull PacketWrapper packet, @NonNull Action action);
|
||||
|
||||
protected abstract void writeEntry(@NonNull PacketWrapper packet, @NonNull Entry entry);
|
||||
|
||||
@NotNull
|
||||
protected static BitSet bitSet(int nbits, int action) {
|
||||
final BitSet bitSet = new BitSet(nbits);
|
||||
bitSet.set(action);
|
||||
return bitSet;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected static BitSet bitSet(int nbits, int fromAction, int toAction) {
|
||||
final BitSet bit = new BitSet(nbits);
|
||||
bit.set(fromAction, toAction);
|
||||
return bit;
|
||||
}
|
||||
|
||||
protected void send(@NonNull PacketWrapper packet) {
|
||||
if (!task.isCancelled()) {
|
||||
queuedPackets.add(packet);
|
||||
} else {
|
||||
packet.scheduleSend(protocol);
|
||||
}
|
||||
}
|
||||
}
|
||||
-114
@@ -1,114 +0,0 @@
|
||||
package me.neznamy.tab.platforms.bukkit.provider.viaversion;
|
||||
|
||||
import com.viaversion.viaversion.api.protocol.Protocol;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketType;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.protocols.v1_15_2to1_16.Protocol1_15_2To1_16;
|
||||
import com.viaversion.viaversion.protocols.v1_15_2to1_16.packet.ClientboundPackets1_16;
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.chat.component.TabComponent;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* TabList handler using ViaVersion packets,
|
||||
* to unlock +1.16 player features on pre 1.16 servers.
|
||||
*/
|
||||
public class ViaTabList116 extends ViaTabList {
|
||||
|
||||
private static final int ADD_PLAYER = 0;
|
||||
private static final int UPDATE_GAME_MODE = 1;
|
||||
private static final int UPDATE_LATENCY = 2;
|
||||
private static final int UPDATE_DISPLAY_NAME = 3;
|
||||
private static final int REMOVE_PLAYER = 4;
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters.
|
||||
*
|
||||
* @param player
|
||||
* Player this tablist will belong to
|
||||
*/
|
||||
public ViaTabList116(@NotNull BukkitTabPlayer player) {
|
||||
this(player, Protocol1_15_2To1_16.class, ClientboundPackets1_16.PLAYER_INFO, ClientboundPackets1_16.TAB_LIST);
|
||||
}
|
||||
|
||||
protected ViaTabList116(@NonNull BukkitTabPlayer player, @NonNull Class<? extends Protocol> protocol, @NonNull PacketType playerInfoUpdate, @NonNull PacketType tabList) {
|
||||
super(player, protocol, playerInfoUpdate, tabList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeEntry(@NonNull UUID entry) {
|
||||
sendInfoUpdate(Action.REMOVE_PLAYER, entry, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateListed(@NonNull UUID entry, boolean listed) {
|
||||
// Added on 1.19.3
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateListOrder(@NonNull UUID entry, int listOrder) {
|
||||
// Added in 1.21.2
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateHat(@NonNull UUID entry, boolean showHat) {
|
||||
// Added in 1.21.4
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeComponent(@NonNull PacketWrapper packet, @NonNull TabComponent component) {
|
||||
packet.write(Types.COMPONENT, component.toViaVersion());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeOptionalComponent(@NonNull PacketWrapper packet, @Nullable TabComponent component) {
|
||||
packet.write(Types.OPTIONAL_COMPONENT, component == null ? null : component.toViaVersion());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeAction(@NonNull PacketWrapper packet, @NonNull Action action) {
|
||||
switch (action) {
|
||||
case ADD_PLAYER:
|
||||
packet.write(Types.VAR_INT, ADD_PLAYER);
|
||||
break;
|
||||
case REMOVE_PLAYER:
|
||||
packet.write(Types.VAR_INT, REMOVE_PLAYER);
|
||||
break;
|
||||
case UPDATE_DISPLAY_NAME:
|
||||
packet.write(Types.VAR_INT, UPDATE_DISPLAY_NAME);
|
||||
break;
|
||||
case UPDATE_LATENCY:
|
||||
packet.write(Types.VAR_INT, UPDATE_LATENCY);
|
||||
break;
|
||||
case UPDATE_GAME_MODE:
|
||||
packet.write(Types.VAR_INT, UPDATE_GAME_MODE);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Cannot write " + action.name() + " for 1.16 packet");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeEntry(@NonNull PacketWrapper packet, @NonNull Entry entry) {
|
||||
packet.write(Types.STRING, entry.getName());
|
||||
if (entry.getSkin() == null) {
|
||||
// Properties size
|
||||
packet.write(Types.VAR_INT, 0);
|
||||
} else {
|
||||
// Properties size
|
||||
packet.write(Types.VAR_INT, 1);
|
||||
// Properties
|
||||
packet.write(Types.STRING, entry.getName());
|
||||
packet.write(Types.STRING, entry.getSkin().getValue());
|
||||
packet.write(Types.OPTIONAL_STRING, entry.getSkin().getSignature());
|
||||
}
|
||||
packet.write(Types.VAR_INT, entry.getGameMode());
|
||||
packet.write(Types.VAR_INT, entry.getLatency());
|
||||
writeOptionalComponent(packet, entry.getDisplayName());
|
||||
}
|
||||
}
|
||||
-105
@@ -1,105 +0,0 @@
|
||||
package me.neznamy.tab.platforms.bukkit.provider.viaversion;
|
||||
|
||||
import com.viaversion.viaversion.api.protocol.Protocol;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketType;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.protocols.v1_19_1to1_19_3.packet.ClientboundPackets1_19_3;
|
||||
import com.viaversion.viaversion.protocols.v1_19_1to1_19_3.Protocol1_19_1To1_19_3;
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.BitSet;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* TabList handler using ViaVersion packets,
|
||||
* to unlock +1.19.3 player features on pre 1.19.3 servers.
|
||||
*/
|
||||
public class ViaTabList1193 extends ViaTabList116 {
|
||||
|
||||
private static final BitSet ADD_PLAYER = bitSet(6, 0, 6);
|
||||
//private static final BitSet INITIALIZE_CHAT = bitSet(6, 1);
|
||||
private static final BitSet UPDATE_GAME_MODE = bitSet(6, 2);
|
||||
private static final BitSet UPDATE_LISTED = bitSet(6, 3);
|
||||
private static final BitSet UPDATE_LATENCY = bitSet(6, 4);
|
||||
private static final BitSet UPDATE_DISPLAY_NAME = bitSet(6, 5);
|
||||
|
||||
private final PacketType playerInfoRemove;
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters.
|
||||
*
|
||||
* @param player
|
||||
* Player this tablist will belong to
|
||||
*/
|
||||
public ViaTabList1193(@NotNull BukkitTabPlayer player) {
|
||||
this(player, Protocol1_19_1To1_19_3.class, ClientboundPackets1_19_3.PLAYER_INFO_REMOVE, ClientboundPackets1_19_3.PLAYER_INFO_UPDATE, ClientboundPackets1_19_3.TAB_LIST);
|
||||
}
|
||||
|
||||
protected ViaTabList1193(@NonNull BukkitTabPlayer player, @NonNull Class<? extends Protocol> protocol, @Nullable PacketType playerInfoRemove, @NonNull PacketType playerInfoUpdate, @NonNull PacketType tabList) {
|
||||
super(player, protocol, playerInfoUpdate, tabList);
|
||||
this.playerInfoRemove = playerInfoRemove;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeEntry(@NonNull UUID entry) {
|
||||
final PacketWrapper packet = PacketWrapper.create(playerInfoRemove, null, connection);
|
||||
|
||||
// Players
|
||||
packet.write(Types.UUID_ARRAY, new UUID[] { entry });
|
||||
|
||||
send(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateListed(@NonNull UUID entry, boolean listed) {
|
||||
sendInfoUpdate(Action.UPDATE_LISTED, entry, listed);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeAction(@NonNull PacketWrapper packet, @NonNull Action action) {
|
||||
switch (action) {
|
||||
case ADD_PLAYER:
|
||||
packet.write(Types.PROFILE_ACTIONS_ENUM1_19_3, ADD_PLAYER);
|
||||
break;
|
||||
case UPDATE_DISPLAY_NAME:
|
||||
packet.write(Types.PROFILE_ACTIONS_ENUM1_19_3, UPDATE_DISPLAY_NAME);
|
||||
break;
|
||||
case UPDATE_LATENCY:
|
||||
packet.write(Types.PROFILE_ACTIONS_ENUM1_19_3, UPDATE_LATENCY);
|
||||
break;
|
||||
case UPDATE_GAME_MODE:
|
||||
packet.write(Types.PROFILE_ACTIONS_ENUM1_19_3, UPDATE_GAME_MODE);
|
||||
break;
|
||||
case UPDATE_LISTED:
|
||||
packet.write(Types.PROFILE_ACTIONS_ENUM1_19_3, UPDATE_LISTED);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Cannot write " + action.name() + " for 1.19.3 packet");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeEntry(@NonNull PacketWrapper packet, @NonNull Entry entry) {
|
||||
packet.write(Types.STRING, entry.getName());
|
||||
if (entry.getSkin() == null) {
|
||||
// Properties size
|
||||
packet.write(Types.VAR_INT, 0);
|
||||
} else {
|
||||
// Properties size
|
||||
packet.write(Types.VAR_INT, 1);
|
||||
// Properties
|
||||
packet.write(Types.STRING, entry.getName());
|
||||
packet.write(Types.STRING, entry.getSkin().getValue());
|
||||
packet.write(Types.OPTIONAL_STRING, entry.getSkin().getSignature());
|
||||
}
|
||||
packet.write(Types.BOOLEAN, false); // No chat session data
|
||||
packet.write(Types.VAR_INT, entry.getGameMode());
|
||||
packet.write(Types.BOOLEAN, entry.isListed());
|
||||
packet.write(Types.VAR_INT, entry.getLatency());
|
||||
writeOptionalComponent(packet, entry.getDisplayName());
|
||||
}
|
||||
}
|
||||
-92
@@ -1,92 +0,0 @@
|
||||
package me.neznamy.tab.platforms.bukkit.provider.viaversion;
|
||||
|
||||
import com.viaversion.viaversion.api.protocol.Protocol;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketType;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPackets1_21_2;
|
||||
import com.viaversion.viaversion.protocols.v1_21to1_21_2.Protocol1_21To1_21_2;
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.chat.component.TabComponent;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.BitSet;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* TabList handler using ViaVersion packets,
|
||||
* to unlock +1.21.2 player features on pre 1.21.2 servers.
|
||||
*/
|
||||
public class ViaTabList1212 extends ViaTabList1193 {
|
||||
|
||||
private static final BitSet ADD_PLAYER = bitSet(7, 0, 7);
|
||||
//private static final BitSet INITIALIZE_CHAT = bitSet(7, 1);
|
||||
private static final BitSet UPDATE_GAME_MODE = bitSet(7, 2);
|
||||
private static final BitSet UPDATE_LISTED = bitSet(7, 3);
|
||||
private static final BitSet UPDATE_LATENCY = bitSet(7, 4);
|
||||
private static final BitSet UPDATE_DISPLAY_NAME = bitSet(7, 5);
|
||||
private static final BitSet UPDATE_LIST_ORDER = bitSet(7, 6);
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters.
|
||||
*
|
||||
* @param player
|
||||
* Player this tablist will belong to
|
||||
*/
|
||||
public ViaTabList1212(@NotNull BukkitTabPlayer player) {
|
||||
super(player, Protocol1_21To1_21_2.class, ClientboundPackets1_21_2.PLAYER_INFO_REMOVE, ClientboundPackets1_21_2.PLAYER_INFO_UPDATE, ClientboundPackets1_21_2.TAB_LIST);
|
||||
}
|
||||
|
||||
protected ViaTabList1212(@NonNull BukkitTabPlayer player, @NonNull Class<? extends Protocol> protocol, @Nullable PacketType playerInfoRemove, @NonNull PacketType playerInfoUpdate, @NonNull PacketType tabList) {
|
||||
super(player, protocol, playerInfoRemove, playerInfoUpdate, tabList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateListOrder(@NonNull UUID entry, int listOrder) {
|
||||
sendInfoUpdate(Action.UPDATE_LIST_ORDER, entry, listOrder);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeComponent(@NonNull PacketWrapper packet, @NonNull TabComponent component) {
|
||||
packet.write(Types.TAG, component.toViaVersionTag());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeOptionalComponent(@NonNull PacketWrapper packet, @Nullable TabComponent component) {
|
||||
packet.write(Types.OPTIONAL_TAG, component == null ? null : component.toViaVersionTag());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeAction(@NonNull PacketWrapper packet, @NonNull Action action) {
|
||||
switch (action) {
|
||||
case ADD_PLAYER:
|
||||
packet.write(Types.PROFILE_ACTIONS_ENUM1_21_2, ADD_PLAYER);
|
||||
break;
|
||||
case UPDATE_DISPLAY_NAME:
|
||||
packet.write(Types.PROFILE_ACTIONS_ENUM1_21_2, UPDATE_DISPLAY_NAME);
|
||||
break;
|
||||
case UPDATE_LATENCY:
|
||||
packet.write(Types.PROFILE_ACTIONS_ENUM1_21_2, UPDATE_LATENCY);
|
||||
break;
|
||||
case UPDATE_GAME_MODE:
|
||||
packet.write(Types.PROFILE_ACTIONS_ENUM1_21_2, UPDATE_GAME_MODE);
|
||||
break;
|
||||
case UPDATE_LISTED:
|
||||
packet.write(Types.PROFILE_ACTIONS_ENUM1_21_2, UPDATE_LISTED);
|
||||
break;
|
||||
case UPDATE_LIST_ORDER:
|
||||
packet.write(Types.PROFILE_ACTIONS_ENUM1_21_2, UPDATE_LIST_ORDER);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Cannot write " + action.name() + " for 1.21.2 packet");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeEntry(@NonNull PacketWrapper packet, @NonNull Entry entry) {
|
||||
super.writeEntry(packet, entry);
|
||||
packet.write(Types.VAR_INT, entry.getListOrder());
|
||||
}
|
||||
}
|
||||
-78
@@ -1,78 +0,0 @@
|
||||
package me.neznamy.tab.platforms.bukkit.provider.viaversion;
|
||||
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.Protocol1_21_2To1_21_4;
|
||||
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPackets1_21_2;
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.BitSet;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* TabList handler using ViaVersion packets,
|
||||
* to unlock +1.21.4 player features on pre 1.21.4 servers.
|
||||
*/
|
||||
public class ViaTabList1214 extends ViaTabList1212 {
|
||||
|
||||
private static final BitSet ADD_PLAYER = bitSet(8, 0, 8);
|
||||
//private static final BitSet INITIALIZE_CHAT = bitSet(8, 1);
|
||||
private static final BitSet UPDATE_GAME_MODE = bitSet(8, 2);
|
||||
private static final BitSet UPDATE_LISTED = bitSet(8, 3);
|
||||
private static final BitSet UPDATE_LATENCY = bitSet(8, 4);
|
||||
private static final BitSet UPDATE_DISPLAY_NAME = bitSet(8, 5);
|
||||
private static final BitSet UPDATE_LIST_ORDER = bitSet(8, 6);
|
||||
private static final BitSet UPDATE_HAT = bitSet(8, 7);
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters.
|
||||
*
|
||||
* @param player
|
||||
* Player this tablist will belong to
|
||||
*/
|
||||
public ViaTabList1214(@NotNull BukkitTabPlayer player) {
|
||||
super(player, Protocol1_21_2To1_21_4.class, ClientboundPackets1_21_2.PLAYER_INFO_REMOVE, ClientboundPackets1_21_2.PLAYER_INFO_UPDATE, ClientboundPackets1_21_2.TAB_LIST);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateHat(@NonNull UUID entry, boolean showHat) {
|
||||
sendInfoUpdate(Action.UPDATE_HAT, entry, showHat);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeAction(@NonNull PacketWrapper packet, @NonNull Action action) {
|
||||
switch (action) {
|
||||
case ADD_PLAYER:
|
||||
packet.write(Types.PROFILE_ACTIONS_ENUM1_21_4, ADD_PLAYER);
|
||||
break;
|
||||
case UPDATE_DISPLAY_NAME:
|
||||
packet.write(Types.PROFILE_ACTIONS_ENUM1_21_4, UPDATE_DISPLAY_NAME);
|
||||
break;
|
||||
case UPDATE_LATENCY:
|
||||
packet.write(Types.PROFILE_ACTIONS_ENUM1_21_4, UPDATE_LATENCY);
|
||||
break;
|
||||
case UPDATE_GAME_MODE:
|
||||
packet.write(Types.PROFILE_ACTIONS_ENUM1_21_4, UPDATE_GAME_MODE);
|
||||
break;
|
||||
case UPDATE_LISTED:
|
||||
packet.write(Types.PROFILE_ACTIONS_ENUM1_21_4, UPDATE_LISTED);
|
||||
break;
|
||||
case UPDATE_LIST_ORDER:
|
||||
packet.write(Types.PROFILE_ACTIONS_ENUM1_21_4, UPDATE_LIST_ORDER);
|
||||
break;
|
||||
case UPDATE_HAT:
|
||||
packet.write(Types.PROFILE_ACTIONS_ENUM1_21_4, UPDATE_HAT);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Cannot write " + action.name() + " for 1.21.4 packet");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeEntry(@NonNull PacketWrapper packet, @NonNull Entry entry) {
|
||||
super.writeEntry(packet, entry);
|
||||
packet.write(Types.BOOLEAN, entry.isShowHat());
|
||||
}
|
||||
}
|
||||
-65
@@ -1,65 +0,0 @@
|
||||
package me.neznamy.tab.platforms.bukkit.provider.viaversion;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.shared.ProtocolVersion;
|
||||
import me.neznamy.tab.shared.platform.Scoreboard;
|
||||
import me.neznamy.tab.shared.platform.TabList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Implementation for sending new features on old servers using ViaVersion API.
|
||||
* If no implementation is required for a player, {@code null} is returned.
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class ViaVersionProvider {
|
||||
|
||||
/** Map of tablist implementations by each new version */
|
||||
private static final Map<ProtocolVersion, Function<BukkitTabPlayer, TabList>> TABLIST_IMPLEMENTATIONS = new LinkedHashMap<>();
|
||||
|
||||
/** Map of scoreboard implementations by each new version */
|
||||
private static final Map<ProtocolVersion, Function<BukkitTabPlayer, Scoreboard>> SCOREBOARD_IMPLEMENTATIONS = new LinkedHashMap<>();
|
||||
|
||||
static {
|
||||
TABLIST_IMPLEMENTATIONS.put(ProtocolVersion.V1_21_4, ViaTabList1214::new);
|
||||
TABLIST_IMPLEMENTATIONS.put(ProtocolVersion.V1_21_2, ViaTabList1212::new);
|
||||
TABLIST_IMPLEMENTATIONS.put(ProtocolVersion.V1_19_3, ViaTabList1193::new);
|
||||
TABLIST_IMPLEMENTATIONS.put(ProtocolVersion.V1_16, ViaTabList116::new);
|
||||
|
||||
SCOREBOARD_IMPLEMENTATIONS.put(ProtocolVersion.V1_20_3, ViaScoreboard1203::new);
|
||||
SCOREBOARD_IMPLEMENTATIONS.put(ProtocolVersion.V1_16, ViaScoreboard116::new);
|
||||
SCOREBOARD_IMPLEMENTATIONS.put(ProtocolVersion.V1_13, ViaScoreboard113::new);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private final ProtocolVersion serverVersion;
|
||||
|
||||
@Nullable
|
||||
public Scoreboard newScoreboard(@NotNull BukkitTabPlayer player) {
|
||||
int serverVer = serverVersion.getNetworkId();
|
||||
int playerVer = player.getVersion().getNetworkId();
|
||||
for (Map.Entry<ProtocolVersion, Function<BukkitTabPlayer, Scoreboard>> entry : SCOREBOARD_IMPLEMENTATIONS.entrySet()) {
|
||||
if (serverVer < entry.getKey().getNetworkId() && playerVer >= entry.getKey().getNetworkId()) {
|
||||
return entry.getValue().apply(player);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public TabList newTabList(@NotNull BukkitTabPlayer player) {
|
||||
int serverVer = serverVersion.getNetworkId();
|
||||
int playerVer = player.getVersion().getNetworkId();
|
||||
for (Map.Entry<ProtocolVersion, Function<BukkitTabPlayer, TabList>> entry : TABLIST_IMPLEMENTATIONS.entrySet()) {
|
||||
if (serverVer < entry.getKey().getNetworkId() && playerVer >= entry.getKey().getNetworkId()) {
|
||||
return entry.getValue().apply(player);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -6,11 +6,8 @@ api-version: 1.13 # Defining to avoid legacy plugin warn
|
||||
load: POSTWORLD
|
||||
author: @author@
|
||||
website: "@website@"
|
||||
depend: []
|
||||
softdepend: [PlaceholderAPI, LuckPerms, LibsDisguises, ViaVersion, ViaRewind, floodgate, Vault]
|
||||
loadbefore: []
|
||||
prefix: TAB
|
||||
libraries: []
|
||||
folia-supported: true
|
||||
commands:
|
||||
tab:
|
||||
|
||||
-13
@@ -2,12 +2,9 @@ package me.neznamy.tab.platforms.bukkit.v1_12_R1;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ComponentConverter;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ImplementationProvider;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.viaversion.ViaScoreboard;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.viaversion.ViaTabList;
|
||||
import me.neznamy.tab.shared.platform.Scoreboard;
|
||||
import me.neznamy.tab.shared.platform.TabList;
|
||||
import me.neznamy.tab.shared.util.function.FunctionWithException;
|
||||
@@ -29,16 +26,6 @@ public class NMSImplementationProvider implements ImplementationProvider {
|
||||
return new NMSPacketScoreboard(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSend(@NonNull Object packet, @NonNull ViaScoreboard scoreboard) {
|
||||
NMSPacketScoreboard.onPacketSend(packet, scoreboard);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSend(@NonNull Object packet, @NonNull ViaTabList tabList) {
|
||||
NMSPacketTabList.onPacketSend(packet, tabList);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public TabList newTabList(@NotNull BukkitTabPlayer player) {
|
||||
|
||||
+29
-25
@@ -34,26 +34,6 @@ public class NMSPacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
private static final Field DisplayObjective_OBJECTIVE_NAME = ReflectionUtils.getOnlyField(PacketPlayOutScoreboardDisplayObjective.class, String.class);
|
||||
private static final Field DisplayObjective_POSITION = ReflectionUtils.getOnlyField(PacketPlayOutScoreboardDisplayObjective.class, int.class);
|
||||
|
||||
@SneakyThrows
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void onPacketSend(@NonNull Object packet, @NonNull SafeScoreboard<BukkitTabPlayer> scoreboard) {
|
||||
if (packet instanceof PacketPlayOutScoreboardDisplayObjective) {
|
||||
TAB.getInstance().getFeatureManager().onDisplayObjective(scoreboard.getPlayer(), DisplayObjective_POSITION.getInt(packet),
|
||||
(String) DisplayObjective_OBJECTIVE_NAME.get(packet));
|
||||
}
|
||||
if (packet instanceof PacketPlayOutScoreboardObjective) {
|
||||
TAB.getInstance().getFeatureManager().onObjective(scoreboard.getPlayer(),
|
||||
Objective_METHOD.getInt(packet), (String) Objective_OBJECTIVE_NAME.get(packet));
|
||||
}
|
||||
if (packet instanceof PacketPlayOutScoreboardTeam) {
|
||||
int action = TeamPacket_ACTION.getInt(packet);
|
||||
if (action == TeamAction.UPDATE) return;
|
||||
Collection<String> players = (Collection<String>) TeamPacket_PLAYERS.get(packet);
|
||||
if (players == null) players = Collections.emptyList();
|
||||
TeamPacket_PLAYERS.set(packet, scoreboard.onTeamPacket(action, (String) TeamPacket_NAME.get(packet), players));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance with given player.
|
||||
*
|
||||
@@ -67,7 +47,7 @@ public class NMSPacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
@Override
|
||||
public void registerObjective(@NonNull Objective objective) {
|
||||
ScoreboardObjective obj = new ScoreboardObjective(dummyScoreboard, objective.getName(), IScoreboardCriteria.b);
|
||||
obj.setDisplayName(cutTo(objective.getTitle().toLegacyText(), Limitations.SCOREBOARD_TITLE_PRE_1_13));
|
||||
obj.setDisplayName(maybeCut(objective.getTitle().toLegacyText(), Limitations.SCOREBOARD_TITLE_PRE_1_13));
|
||||
obj.a(IScoreboardCriteria.EnumScoreboardHealthDisplay.valueOf(objective.getHealthDisplay().name()));
|
||||
objective.setPlatformObjective(obj);
|
||||
sendPacket(new PacketPlayOutScoreboardObjective(obj, ObjectiveAction.REGISTER));
|
||||
@@ -86,7 +66,7 @@ public class NMSPacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
@Override
|
||||
public void updateObjective(@NonNull Objective objective) {
|
||||
ScoreboardObjective obj = (ScoreboardObjective) objective.getPlatformObjective();
|
||||
obj.setDisplayName(cutTo(objective.getTitle().toLegacyText(), Limitations.SCOREBOARD_TITLE_PRE_1_13));
|
||||
obj.setDisplayName(maybeCut(objective.getTitle().toLegacyText(), Limitations.SCOREBOARD_TITLE_PRE_1_13));
|
||||
obj.a(IScoreboardCriteria.EnumScoreboardHealthDisplay.valueOf(objective.getHealthDisplay().name()));
|
||||
sendPacket(new PacketPlayOutScoreboardObjective(obj, ObjectiveAction.UPDATE));
|
||||
}
|
||||
@@ -134,13 +114,29 @@ public class NMSPacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
t.setCanSeeFriendlyInvisibles((team.getOptions() & 0x02) != 0);
|
||||
t.setNameTagVisibility(visibilities[team.getVisibility().ordinal()]);
|
||||
t.setCollisionRule(collisions[team.getCollision().ordinal()]);
|
||||
t.setPrefix(cutTo(team.getPrefix().toLegacyText(), Limitations.TEAM_PREFIX_SUFFIX_PRE_1_13));
|
||||
t.setSuffix(cutTo(team.getSuffix().toLegacyText(), Limitations.TEAM_PREFIX_SUFFIX_PRE_1_13));
|
||||
t.setPrefix(maybeCut(team.getPrefix().toLegacyText(), Limitations.TEAM_PREFIX_SUFFIX_PRE_1_13));
|
||||
t.setSuffix(maybeCut(team.getSuffix().toLegacyText(), Limitations.TEAM_PREFIX_SUFFIX_PRE_1_13));
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
@SuppressWarnings("unchecked")
|
||||
public void onPacketSend(@NonNull Object packet) {
|
||||
onPacketSend(packet, this);
|
||||
if (packet instanceof PacketPlayOutScoreboardDisplayObjective) {
|
||||
TAB.getInstance().getFeatureManager().onDisplayObjective(player, DisplayObjective_POSITION.getInt(packet),
|
||||
(String) DisplayObjective_OBJECTIVE_NAME.get(packet));
|
||||
}
|
||||
if (packet instanceof PacketPlayOutScoreboardObjective) {
|
||||
TAB.getInstance().getFeatureManager().onObjective(player,
|
||||
Objective_METHOD.getInt(packet), (String) Objective_OBJECTIVE_NAME.get(packet));
|
||||
}
|
||||
if (packet instanceof PacketPlayOutScoreboardTeam) {
|
||||
int action = TeamPacket_ACTION.getInt(packet);
|
||||
if (action == TeamAction.UPDATE) return;
|
||||
Collection<String> players = (Collection<String>) TeamPacket_PLAYERS.get(packet);
|
||||
if (players == null) players = Collections.emptyList();
|
||||
TeamPacket_PLAYERS.set(packet, onTeamPacket(action, (String) TeamPacket_NAME.get(packet), players));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -152,4 +148,12 @@ public class NMSPacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
private void sendPacket(@NotNull Packet<?> packet) {
|
||||
((CraftPlayer)player.getPlayer()).getHandle().playerConnection.sendPacket(packet);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String maybeCut(@NonNull String string, int length) {
|
||||
if (player.getVersion().getMinorVersion() < 13 || TAB.getInstance().getConfiguration().getConfig().isPacketEventsCompensation()) {
|
||||
return cutTo(string, length);
|
||||
}
|
||||
return string;
|
||||
}
|
||||
}
|
||||
+22
-26
@@ -42,31 +42,6 @@ public class NMSPacketTabList extends TrackedTabList<BukkitTabPlayer> {
|
||||
private static final Field HEADER = ReflectionUtils.getFields(PacketPlayOutPlayerListHeaderFooter.class, IChatBaseComponent.class).get(0);
|
||||
private static final Field FOOTER = ReflectionUtils.getFields(PacketPlayOutPlayerListHeaderFooter.class, IChatBaseComponent.class).get(1);
|
||||
|
||||
@SneakyThrows
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void onPacketSend(@NonNull Object packet, @NonNull TrackedTabList<BukkitTabPlayer> tabList) {
|
||||
if (!(packet instanceof PacketPlayOutPlayerInfo)) return;
|
||||
EnumPlayerInfoAction action = (EnumPlayerInfoAction) ACTION.get(packet);
|
||||
for (Object nmsData : (List<Object>) PLAYERS.get(packet)) {
|
||||
GameProfile profile = (GameProfile) PlayerInfoData_Profile.get(nmsData);
|
||||
UUID id = profile.getId();
|
||||
if (action == EnumPlayerInfoAction.UPDATE_DISPLAY_NAME || action == EnumPlayerInfoAction.ADD_PLAYER) {
|
||||
TabComponent expectedName = tabList.getExpectedDisplayNames().get(id);
|
||||
if (expectedName != null) PlayerInfoData_DisplayName.set(nmsData, expectedName.convert());
|
||||
}
|
||||
if (action == EnumPlayerInfoAction.UPDATE_LATENCY || action == EnumPlayerInfoAction.ADD_PLAYER) {
|
||||
int oldLatency = PlayerInfoData_Latency.getInt(nmsData);
|
||||
int newLatency = TAB.getInstance().getFeatureManager().onLatencyChange(tabList.getPlayer(), id, oldLatency);
|
||||
if (oldLatency != newLatency) {
|
||||
PlayerInfoData_Latency.set(nmsData, newLatency);
|
||||
}
|
||||
}
|
||||
if (action == EnumPlayerInfoAction.ADD_PLAYER) {
|
||||
TAB.getInstance().getFeatureManager().onEntryAdd(tabList.getPlayer(), id, profile.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance.
|
||||
*
|
||||
@@ -143,8 +118,29 @@ public class NMSPacketTabList extends TrackedTabList<BukkitTabPlayer> {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
@SuppressWarnings("unchecked")
|
||||
public void onPacketSend(@NonNull Object packet) {
|
||||
onPacketSend(packet, this);
|
||||
if (!(packet instanceof PacketPlayOutPlayerInfo)) return;
|
||||
EnumPlayerInfoAction action = (EnumPlayerInfoAction) ACTION.get(packet);
|
||||
for (Object nmsData : (List<Object>) PLAYERS.get(packet)) {
|
||||
GameProfile profile = (GameProfile) PlayerInfoData_Profile.get(nmsData);
|
||||
UUID id = profile.getId();
|
||||
if (action == EnumPlayerInfoAction.UPDATE_DISPLAY_NAME || action == EnumPlayerInfoAction.ADD_PLAYER) {
|
||||
TabComponent expectedName = getExpectedDisplayNames().get(id);
|
||||
if (expectedName != null) PlayerInfoData_DisplayName.set(nmsData, expectedName.convert());
|
||||
}
|
||||
if (action == EnumPlayerInfoAction.UPDATE_LATENCY || action == EnumPlayerInfoAction.ADD_PLAYER) {
|
||||
int oldLatency = PlayerInfoData_Latency.getInt(nmsData);
|
||||
int newLatency = TAB.getInstance().getFeatureManager().onLatencyChange(player, id, oldLatency);
|
||||
if (oldLatency != newLatency) {
|
||||
PlayerInfoData_Latency.set(nmsData, newLatency);
|
||||
}
|
||||
}
|
||||
if (action == EnumPlayerInfoAction.ADD_PLAYER) {
|
||||
TAB.getInstance().getFeatureManager().onEntryAdd(player, id, profile.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
|
||||
-13
@@ -2,12 +2,9 @@ package me.neznamy.tab.platforms.bukkit.v1_16_R3;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ComponentConverter;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ImplementationProvider;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.viaversion.ViaScoreboard;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.viaversion.ViaTabList;
|
||||
import me.neznamy.tab.shared.platform.Scoreboard;
|
||||
import me.neznamy.tab.shared.platform.TabList;
|
||||
import me.neznamy.tab.shared.util.function.FunctionWithException;
|
||||
@@ -29,16 +26,6 @@ public class NMSImplementationProvider implements ImplementationProvider {
|
||||
return new NMSPacketScoreboard(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSend(@NonNull Object packet, @NonNull ViaScoreboard scoreboard) {
|
||||
NMSPacketScoreboard.onPacketSend(packet, scoreboard);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSend(@NonNull Object packet, @NonNull ViaTabList tabList) {
|
||||
NMSPacketTabList.onPacketSend(packet, tabList);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public TabList newTabList(@NotNull BukkitTabPlayer player) {
|
||||
|
||||
+17
-21
@@ -33,26 +33,6 @@ public class NMSPacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
private static final Field DisplayObjective_OBJECTIVE_NAME = ReflectionUtils.getOnlyField(PacketPlayOutScoreboardDisplayObjective.class, String.class);
|
||||
private static final Field DisplayObjective_POSITION = ReflectionUtils.getOnlyField(PacketPlayOutScoreboardDisplayObjective.class, int.class);
|
||||
|
||||
@SneakyThrows
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void onPacketSend(@NonNull Object packet, @NonNull SafeScoreboard<BukkitTabPlayer> scoreboard) {
|
||||
if (packet instanceof PacketPlayOutScoreboardDisplayObjective) {
|
||||
TAB.getInstance().getFeatureManager().onDisplayObjective(scoreboard.getPlayer(), DisplayObjective_POSITION.getInt(packet),
|
||||
(String) DisplayObjective_OBJECTIVE_NAME.get(packet));
|
||||
}
|
||||
if (packet instanceof PacketPlayOutScoreboardObjective) {
|
||||
TAB.getInstance().getFeatureManager().onObjective(scoreboard.getPlayer(),
|
||||
Objective_METHOD.getInt(packet), (String) Objective_OBJECTIVE_NAME.get(packet));
|
||||
}
|
||||
if (packet instanceof PacketPlayOutScoreboardTeam) {
|
||||
int action = TeamPacket_ACTION.getInt(packet);
|
||||
if (action == TeamAction.UPDATE) return;
|
||||
Collection<String> players = (Collection<String>) TeamPacket_PLAYERS.get(packet);
|
||||
if (players == null) players = Collections.emptyList();
|
||||
TeamPacket_PLAYERS.set(packet, scoreboard.onTeamPacket(action, (String) TeamPacket_NAME.get(packet), players));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance with given player.
|
||||
*
|
||||
@@ -154,8 +134,24 @@ public class NMSPacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
@SuppressWarnings("unchecked")
|
||||
public void onPacketSend(@NonNull Object packet) {
|
||||
onPacketSend(packet, this);
|
||||
if (packet instanceof PacketPlayOutScoreboardDisplayObjective) {
|
||||
TAB.getInstance().getFeatureManager().onDisplayObjective(player, DisplayObjective_POSITION.getInt(packet),
|
||||
(String) DisplayObjective_OBJECTIVE_NAME.get(packet));
|
||||
}
|
||||
if (packet instanceof PacketPlayOutScoreboardObjective) {
|
||||
TAB.getInstance().getFeatureManager().onObjective(player,
|
||||
Objective_METHOD.getInt(packet), (String) Objective_OBJECTIVE_NAME.get(packet));
|
||||
}
|
||||
if (packet instanceof PacketPlayOutScoreboardTeam) {
|
||||
int action = TeamPacket_ACTION.getInt(packet);
|
||||
if (action == TeamAction.UPDATE) return;
|
||||
Collection<String> players = (Collection<String>) TeamPacket_PLAYERS.get(packet);
|
||||
if (players == null) players = Collections.emptyList();
|
||||
TeamPacket_PLAYERS.set(packet, onTeamPacket(action, (String) TeamPacket_NAME.get(packet), players));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+22
-26
@@ -42,31 +42,6 @@ public class NMSPacketTabList extends TrackedTabList<BukkitTabPlayer> {
|
||||
private static final Field HEADER = ReflectionUtils.getFields(PacketPlayOutPlayerListHeaderFooter.class, IChatBaseComponent.class).get(0);
|
||||
private static final Field FOOTER = ReflectionUtils.getFields(PacketPlayOutPlayerListHeaderFooter.class, IChatBaseComponent.class).get(1);
|
||||
|
||||
@SneakyThrows
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void onPacketSend(@NonNull Object packet, @NonNull TrackedTabList<BukkitTabPlayer> tabList) {
|
||||
if (!(packet instanceof PacketPlayOutPlayerInfo)) return;
|
||||
EnumPlayerInfoAction action = (EnumPlayerInfoAction) ACTION.get(packet);
|
||||
for (Object nmsData : (List<Object>) PLAYERS.get(packet)) {
|
||||
GameProfile profile = (GameProfile) PlayerInfoData_Profile.get(nmsData);
|
||||
UUID id = profile.getId();
|
||||
if (action == EnumPlayerInfoAction.UPDATE_DISPLAY_NAME || action == EnumPlayerInfoAction.ADD_PLAYER) {
|
||||
TabComponent expectedName = tabList.getExpectedDisplayNames().get(id);
|
||||
if (expectedName != null) PlayerInfoData_DisplayName.set(nmsData, expectedName.convert());
|
||||
}
|
||||
if (action == EnumPlayerInfoAction.UPDATE_LATENCY || action == EnumPlayerInfoAction.ADD_PLAYER) {
|
||||
int oldLatency = PlayerInfoData_Latency.getInt(nmsData);
|
||||
int newLatency = TAB.getInstance().getFeatureManager().onLatencyChange(tabList.getPlayer(), id, oldLatency);
|
||||
if (oldLatency != newLatency) {
|
||||
PlayerInfoData_Latency.set(nmsData, newLatency);
|
||||
}
|
||||
}
|
||||
if (action == EnumPlayerInfoAction.ADD_PLAYER) {
|
||||
TAB.getInstance().getFeatureManager().onEntryAdd(tabList.getPlayer(), id, profile.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance.
|
||||
*
|
||||
@@ -143,8 +118,29 @@ public class NMSPacketTabList extends TrackedTabList<BukkitTabPlayer> {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
@SuppressWarnings("unchecked")
|
||||
public void onPacketSend(@NonNull Object packet) {
|
||||
onPacketSend(packet, this);
|
||||
if (!(packet instanceof PacketPlayOutPlayerInfo)) return;
|
||||
EnumPlayerInfoAction action = (EnumPlayerInfoAction) ACTION.get(packet);
|
||||
for (Object nmsData : (List<Object>) PLAYERS.get(packet)) {
|
||||
GameProfile profile = (GameProfile) PlayerInfoData_Profile.get(nmsData);
|
||||
UUID id = profile.getId();
|
||||
if (action == EnumPlayerInfoAction.UPDATE_DISPLAY_NAME || action == EnumPlayerInfoAction.ADD_PLAYER) {
|
||||
TabComponent expectedName = getExpectedDisplayNames().get(id);
|
||||
if (expectedName != null) PlayerInfoData_DisplayName.set(nmsData, expectedName.convert());
|
||||
}
|
||||
if (action == EnumPlayerInfoAction.UPDATE_LATENCY || action == EnumPlayerInfoAction.ADD_PLAYER) {
|
||||
int oldLatency = PlayerInfoData_Latency.getInt(nmsData);
|
||||
int newLatency = TAB.getInstance().getFeatureManager().onLatencyChange(player, id, oldLatency);
|
||||
if (oldLatency != newLatency) {
|
||||
PlayerInfoData_Latency.set(nmsData, newLatency);
|
||||
}
|
||||
}
|
||||
if (action == EnumPlayerInfoAction.ADD_PLAYER) {
|
||||
TAB.getInstance().getFeatureManager().onEntryAdd(player, id, profile.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
|
||||
-13
@@ -2,12 +2,9 @@ package me.neznamy.tab.platforms.bukkit.v1_17_R1;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ComponentConverter;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ImplementationProvider;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.viaversion.ViaScoreboard;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.viaversion.ViaTabList;
|
||||
import me.neznamy.tab.shared.platform.Scoreboard;
|
||||
import me.neznamy.tab.shared.platform.TabList;
|
||||
import me.neznamy.tab.shared.util.function.FunctionWithException;
|
||||
@@ -29,16 +26,6 @@ public class NMSImplementationProvider implements ImplementationProvider {
|
||||
return new NMSPacketScoreboard(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSend(@NonNull Object packet, @NonNull ViaScoreboard scoreboard) {
|
||||
NMSPacketScoreboard.onPacketSend(packet, scoreboard);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSend(@NonNull Object packet, @NonNull ViaTabList tabList) {
|
||||
NMSPacketTabList.onPacketSend(packet, tabList);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public TabList newTabList(@NotNull BukkitTabPlayer player) {
|
||||
|
||||
+37
-41
@@ -36,46 +36,6 @@ public class NMSPacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
|
||||
private static final Field TeamPacket_PLAYERS = ReflectionUtils.getOnlyField(PacketPlayOutScoreboardTeam.class, Collection.class);
|
||||
|
||||
@SneakyThrows
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void onPacketSend(@NonNull Object packet, @NonNull SafeScoreboard<BukkitTabPlayer> scoreboard) {
|
||||
if (packet instanceof PacketPlayOutScoreboardDisplayObjective) {
|
||||
TAB.getInstance().getFeatureManager().onDisplayObjective(
|
||||
scoreboard.getPlayer(),
|
||||
((PacketPlayOutScoreboardDisplayObjective)packet).b(),
|
||||
((PacketPlayOutScoreboardDisplayObjective)packet).c()
|
||||
);
|
||||
}
|
||||
if (packet instanceof PacketPlayOutScoreboardObjective) {
|
||||
TAB.getInstance().getFeatureManager().onObjective(
|
||||
scoreboard.getPlayer(),
|
||||
((PacketPlayOutScoreboardObjective)packet).d(),
|
||||
((PacketPlayOutScoreboardObjective)packet).b()
|
||||
);
|
||||
}
|
||||
if (packet instanceof PacketPlayOutScoreboardTeam) {
|
||||
int action = getMethod((PacketPlayOutScoreboardTeam) packet);
|
||||
if (action == TeamAction.UPDATE) return;
|
||||
Collection<String> players = (Collection<String>) TeamPacket_PLAYERS.get(packet);
|
||||
if (players == null) players = Collections.emptyList();
|
||||
TeamPacket_PLAYERS.set(packet, scoreboard.onTeamPacket(action, ((PacketPlayOutScoreboardTeam)packet).d(), players));
|
||||
}
|
||||
}
|
||||
|
||||
private static int getMethod(@NonNull PacketPlayOutScoreboardTeam team) {
|
||||
if (team.c() == PacketPlayOutScoreboardTeam.a.a) {
|
||||
return 0;
|
||||
} else if (team.c() == PacketPlayOutScoreboardTeam.a.b) {
|
||||
return 1;
|
||||
} else if (team.b() == PacketPlayOutScoreboardTeam.a.a) {
|
||||
return 3;
|
||||
} else if (team.b() == PacketPlayOutScoreboardTeam.a.b) {
|
||||
return 4;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance with given player.
|
||||
*
|
||||
@@ -177,8 +137,44 @@ public class NMSPacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
@SuppressWarnings("unchecked")
|
||||
public void onPacketSend(@NonNull Object packet) {
|
||||
onPacketSend(packet, this);
|
||||
if (packet instanceof PacketPlayOutScoreboardDisplayObjective) {
|
||||
TAB.getInstance().getFeatureManager().onDisplayObjective(
|
||||
player,
|
||||
((PacketPlayOutScoreboardDisplayObjective)packet).b(),
|
||||
((PacketPlayOutScoreboardDisplayObjective)packet).c()
|
||||
);
|
||||
}
|
||||
if (packet instanceof PacketPlayOutScoreboardObjective) {
|
||||
TAB.getInstance().getFeatureManager().onObjective(
|
||||
player,
|
||||
((PacketPlayOutScoreboardObjective)packet).d(),
|
||||
((PacketPlayOutScoreboardObjective)packet).b()
|
||||
);
|
||||
}
|
||||
if (packet instanceof PacketPlayOutScoreboardTeam) {
|
||||
int action = getMethod((PacketPlayOutScoreboardTeam) packet);
|
||||
if (action == TeamAction.UPDATE) return;
|
||||
Collection<String> players = (Collection<String>) TeamPacket_PLAYERS.get(packet);
|
||||
if (players == null) players = Collections.emptyList();
|
||||
TeamPacket_PLAYERS.set(packet, onTeamPacket(action, ((PacketPlayOutScoreboardTeam)packet).d(), players));
|
||||
}
|
||||
}
|
||||
|
||||
private int getMethod(@NonNull PacketPlayOutScoreboardTeam team) {
|
||||
if (team.c() == PacketPlayOutScoreboardTeam.a.a) {
|
||||
return 0;
|
||||
} else if (team.c() == PacketPlayOutScoreboardTeam.a.b) {
|
||||
return 1;
|
||||
} else if (team.b() == PacketPlayOutScoreboardTeam.a.a) {
|
||||
return 3;
|
||||
} else if (team.b() == PacketPlayOutScoreboardTeam.a.b) {
|
||||
return 4;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+9
-4
@@ -61,6 +61,14 @@ public class NMSPacketTabList extends TrackedTabList<BukkitTabPlayer> {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Skin getSkin(@NonNull BukkitTabPlayer player) {
|
||||
Collection<Property> properties = ((CraftPlayer)player.getPlayer()).getProfile().getProperties().get(TEXTURES_PROPERTY);
|
||||
if (properties.isEmpty()) return null; // Offline mode
|
||||
Property property = properties.iterator().next();
|
||||
return new Skin(property.getValue(), property.getSignature());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance.
|
||||
*
|
||||
@@ -127,10 +135,7 @@ public class NMSPacketTabList extends TrackedTabList<BukkitTabPlayer> {
|
||||
@Override
|
||||
@Nullable
|
||||
public Skin getSkin() {
|
||||
Collection<Property> properties = ((CraftPlayer)player.getPlayer()).getProfile().getProperties().get(TEXTURES_PROPERTY);
|
||||
if (properties.isEmpty()) return null; // Offline mode
|
||||
Property property = properties.iterator().next();
|
||||
return new Skin(property.getValue(), property.getSignature());
|
||||
return getSkin(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
-13
@@ -2,12 +2,9 @@ package me.neznamy.tab.platforms.bukkit.v1_18_R2;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ComponentConverter;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ImplementationProvider;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.viaversion.ViaScoreboard;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.viaversion.ViaTabList;
|
||||
import me.neznamy.tab.shared.platform.Scoreboard;
|
||||
import me.neznamy.tab.shared.platform.TabList;
|
||||
import me.neznamy.tab.shared.util.function.FunctionWithException;
|
||||
@@ -29,16 +26,6 @@ public class NMSImplementationProvider implements ImplementationProvider {
|
||||
return new NMSPacketScoreboard(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSend(@NonNull Object packet, @NonNull ViaScoreboard scoreboard) {
|
||||
NMSPacketScoreboard.onPacketSend(packet, scoreboard);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSend(@NonNull Object packet, @NonNull ViaTabList tabList) {
|
||||
NMSPacketTabList.onPacketSend(packet, tabList);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public TabList newTabList(@NotNull BukkitTabPlayer player) {
|
||||
|
||||
+37
-41
@@ -37,46 +37,6 @@ public class NMSPacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
|
||||
private static final Field TeamPacket_PLAYERS = ReflectionUtils.getOnlyField(PacketPlayOutScoreboardTeam.class, Collection.class);
|
||||
|
||||
@SneakyThrows
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void onPacketSend(@NonNull Object packet, @NonNull SafeScoreboard<BukkitTabPlayer> scoreboard) {
|
||||
if (packet instanceof PacketPlayOutScoreboardDisplayObjective) {
|
||||
TAB.getInstance().getFeatureManager().onDisplayObjective(
|
||||
scoreboard.getPlayer(),
|
||||
((PacketPlayOutScoreboardDisplayObjective)packet).b(),
|
||||
((PacketPlayOutScoreboardDisplayObjective)packet).c()
|
||||
);
|
||||
}
|
||||
if (packet instanceof PacketPlayOutScoreboardObjective) {
|
||||
TAB.getInstance().getFeatureManager().onObjective(
|
||||
scoreboard.getPlayer(),
|
||||
((PacketPlayOutScoreboardObjective)packet).d(),
|
||||
((PacketPlayOutScoreboardObjective)packet).b()
|
||||
);
|
||||
}
|
||||
if (packet instanceof PacketPlayOutScoreboardTeam) {
|
||||
int action = getMethod((PacketPlayOutScoreboardTeam) packet);
|
||||
if (action == TeamAction.UPDATE) return;
|
||||
Collection<String> players = (Collection<String>) TeamPacket_PLAYERS.get(packet);
|
||||
if (players == null) players = Collections.emptyList();
|
||||
TeamPacket_PLAYERS.set(packet, scoreboard.onTeamPacket(action, ((PacketPlayOutScoreboardTeam)packet).d(), players));
|
||||
}
|
||||
}
|
||||
|
||||
private static int getMethod(@NonNull PacketPlayOutScoreboardTeam team) {
|
||||
if (team.c() == PacketPlayOutScoreboardTeam.a.a) {
|
||||
return 0;
|
||||
} else if (team.c() == PacketPlayOutScoreboardTeam.a.b) {
|
||||
return 1;
|
||||
} else if (team.b() == PacketPlayOutScoreboardTeam.a.a) {
|
||||
return 3;
|
||||
} else if (team.b() == PacketPlayOutScoreboardTeam.a.b) {
|
||||
return 4;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance with given player.
|
||||
*
|
||||
@@ -178,8 +138,44 @@ public class NMSPacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
@SuppressWarnings("unchecked")
|
||||
public void onPacketSend(@NonNull Object packet) {
|
||||
onPacketSend(packet, this);
|
||||
if (packet instanceof PacketPlayOutScoreboardDisplayObjective) {
|
||||
TAB.getInstance().getFeatureManager().onDisplayObjective(
|
||||
player,
|
||||
((PacketPlayOutScoreboardDisplayObjective)packet).b(),
|
||||
((PacketPlayOutScoreboardDisplayObjective)packet).c()
|
||||
);
|
||||
}
|
||||
if (packet instanceof PacketPlayOutScoreboardObjective) {
|
||||
TAB.getInstance().getFeatureManager().onObjective(
|
||||
player,
|
||||
((PacketPlayOutScoreboardObjective)packet).d(),
|
||||
((PacketPlayOutScoreboardObjective)packet).b()
|
||||
);
|
||||
}
|
||||
if (packet instanceof PacketPlayOutScoreboardTeam) {
|
||||
int action = getMethod((PacketPlayOutScoreboardTeam) packet);
|
||||
if (action == TeamAction.UPDATE) return;
|
||||
Collection<String> players = (Collection<String>) TeamPacket_PLAYERS.get(packet);
|
||||
if (players == null) players = Collections.emptyList();
|
||||
TeamPacket_PLAYERS.set(packet, onTeamPacket(action, ((PacketPlayOutScoreboardTeam)packet).d(), players));
|
||||
}
|
||||
}
|
||||
|
||||
private int getMethod(@NonNull PacketPlayOutScoreboardTeam team) {
|
||||
if (team.c() == PacketPlayOutScoreboardTeam.a.a) {
|
||||
return 0;
|
||||
} else if (team.c() == PacketPlayOutScoreboardTeam.a.b) {
|
||||
return 1;
|
||||
} else if (team.b() == PacketPlayOutScoreboardTeam.a.a) {
|
||||
return 3;
|
||||
} else if (team.b() == PacketPlayOutScoreboardTeam.a.b) {
|
||||
return 4;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+21
-25
@@ -37,30 +37,6 @@ public class NMSPacketTabList extends TrackedTabList<BukkitTabPlayer> {
|
||||
private static final Field PlayerInfoData_Latency = ReflectionUtils.getFields(PlayerInfoData.class, int.class).get(0);
|
||||
private static final Field PlayerInfoData_DisplayName = ReflectionUtils.getOnlyField(PlayerInfoData.class, IChatBaseComponent.class);
|
||||
|
||||
@SneakyThrows
|
||||
public static void onPacketSend(@NonNull Object packet, @NonNull TrackedTabList<BukkitTabPlayer> tabList) {
|
||||
if (!(packet instanceof PacketPlayOutPlayerInfo)) return;
|
||||
EnumPlayerInfoAction action = ((PacketPlayOutPlayerInfo)packet).c();
|
||||
for (PlayerInfoData nmsData : ((PacketPlayOutPlayerInfo)packet).b()) {
|
||||
GameProfile profile = nmsData.a();
|
||||
UUID id = profile.getId();
|
||||
if (action == EnumPlayerInfoAction.d || action == EnumPlayerInfoAction.a) {
|
||||
TabComponent expectedName = tabList.getExpectedDisplayNames().get(id);
|
||||
if (expectedName != null) PlayerInfoData_DisplayName.set(nmsData, expectedName.convert());
|
||||
}
|
||||
if (action == EnumPlayerInfoAction.c || action == EnumPlayerInfoAction.a) {
|
||||
int oldLatency = nmsData.b();
|
||||
int newLatency = TAB.getInstance().getFeatureManager().onLatencyChange(tabList.getPlayer(), id, oldLatency);
|
||||
if (oldLatency != newLatency) {
|
||||
PlayerInfoData_Latency.set(nmsData, newLatency);
|
||||
}
|
||||
}
|
||||
if (action == EnumPlayerInfoAction.a) {
|
||||
TAB.getInstance().getFeatureManager().onEntryAdd(tabList.getPlayer(), id, profile.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance.
|
||||
*
|
||||
@@ -134,8 +110,28 @@ public class NMSPacketTabList extends TrackedTabList<BukkitTabPlayer> {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void onPacketSend(@NonNull Object packet) {
|
||||
onPacketSend(packet, this);
|
||||
if (!(packet instanceof PacketPlayOutPlayerInfo)) return;
|
||||
EnumPlayerInfoAction action = ((PacketPlayOutPlayerInfo)packet).c();
|
||||
for (PlayerInfoData nmsData : ((PacketPlayOutPlayerInfo)packet).b()) {
|
||||
GameProfile profile = nmsData.a();
|
||||
UUID id = profile.getId();
|
||||
if (action == EnumPlayerInfoAction.d || action == EnumPlayerInfoAction.a) {
|
||||
TabComponent expectedName = getExpectedDisplayNames().get(id);
|
||||
if (expectedName != null) PlayerInfoData_DisplayName.set(nmsData, expectedName.convert());
|
||||
}
|
||||
if (action == EnumPlayerInfoAction.c || action == EnumPlayerInfoAction.a) {
|
||||
int oldLatency = nmsData.b();
|
||||
int newLatency = TAB.getInstance().getFeatureManager().onLatencyChange(player, id, oldLatency);
|
||||
if (oldLatency != newLatency) {
|
||||
PlayerInfoData_Latency.set(nmsData, newLatency);
|
||||
}
|
||||
}
|
||||
if (action == EnumPlayerInfoAction.a) {
|
||||
TAB.getInstance().getFeatureManager().onEntryAdd(player, id, profile.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
|
||||
-13
@@ -2,12 +2,9 @@ package me.neznamy.tab.platforms.bukkit.v1_19_R1;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ComponentConverter;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ImplementationProvider;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.viaversion.ViaScoreboard;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.viaversion.ViaTabList;
|
||||
import me.neznamy.tab.shared.platform.Scoreboard;
|
||||
import me.neznamy.tab.shared.platform.TabList;
|
||||
import me.neznamy.tab.shared.util.function.FunctionWithException;
|
||||
@@ -29,16 +26,6 @@ public class NMSImplementationProvider implements ImplementationProvider {
|
||||
return new NMSPacketScoreboard(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSend(@NonNull Object packet, @NonNull ViaScoreboard scoreboard) {
|
||||
NMSPacketScoreboard.onPacketSend(packet, scoreboard);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSend(@NonNull Object packet, @NonNull ViaTabList tabList) {
|
||||
NMSPacketTabList.onPacketSend(packet, tabList);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public TabList newTabList(@NotNull BukkitTabPlayer player) {
|
||||
|
||||
+37
-41
@@ -37,46 +37,6 @@ public class NMSPacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
|
||||
private static final Field TeamPacket_PLAYERS = ReflectionUtils.getOnlyField(PacketPlayOutScoreboardTeam.class, Collection.class);
|
||||
|
||||
@SneakyThrows
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void onPacketSend(@NonNull Object packet, @NonNull SafeScoreboard<BukkitTabPlayer> scoreboard) {
|
||||
if (packet instanceof PacketPlayOutScoreboardDisplayObjective) {
|
||||
TAB.getInstance().getFeatureManager().onDisplayObjective(
|
||||
scoreboard.getPlayer(),
|
||||
((PacketPlayOutScoreboardDisplayObjective)packet).b(),
|
||||
((PacketPlayOutScoreboardDisplayObjective)packet).c()
|
||||
);
|
||||
}
|
||||
if (packet instanceof PacketPlayOutScoreboardObjective) {
|
||||
TAB.getInstance().getFeatureManager().onObjective(
|
||||
scoreboard.getPlayer(),
|
||||
((PacketPlayOutScoreboardObjective)packet).d(),
|
||||
((PacketPlayOutScoreboardObjective)packet).b()
|
||||
);
|
||||
}
|
||||
if (packet instanceof PacketPlayOutScoreboardTeam) {
|
||||
int action = getMethod((PacketPlayOutScoreboardTeam) packet);
|
||||
if (action == TeamAction.UPDATE) return;
|
||||
Collection<String> players = (Collection<String>) TeamPacket_PLAYERS.get(packet);
|
||||
if (players == null) players = Collections.emptyList();
|
||||
TeamPacket_PLAYERS.set(packet, scoreboard.onTeamPacket(action, ((PacketPlayOutScoreboardTeam)packet).d(), players));
|
||||
}
|
||||
}
|
||||
|
||||
private static int getMethod(@NonNull PacketPlayOutScoreboardTeam team) {
|
||||
if (team.c() == PacketPlayOutScoreboardTeam.a.a) {
|
||||
return 0;
|
||||
} else if (team.c() == PacketPlayOutScoreboardTeam.a.b) {
|
||||
return 1;
|
||||
} else if (team.b() == PacketPlayOutScoreboardTeam.a.a) {
|
||||
return 3;
|
||||
} else if (team.b() == PacketPlayOutScoreboardTeam.a.b) {
|
||||
return 4;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance with given player.
|
||||
*
|
||||
@@ -178,8 +138,44 @@ public class NMSPacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
@SuppressWarnings("unchecked")
|
||||
public void onPacketSend(@NonNull Object packet) {
|
||||
onPacketSend(packet, this);
|
||||
if (packet instanceof PacketPlayOutScoreboardDisplayObjective) {
|
||||
TAB.getInstance().getFeatureManager().onDisplayObjective(
|
||||
player,
|
||||
((PacketPlayOutScoreboardDisplayObjective)packet).b(),
|
||||
((PacketPlayOutScoreboardDisplayObjective)packet).c()
|
||||
);
|
||||
}
|
||||
if (packet instanceof PacketPlayOutScoreboardObjective) {
|
||||
TAB.getInstance().getFeatureManager().onObjective(
|
||||
player,
|
||||
((PacketPlayOutScoreboardObjective)packet).d(),
|
||||
((PacketPlayOutScoreboardObjective)packet).b()
|
||||
);
|
||||
}
|
||||
if (packet instanceof PacketPlayOutScoreboardTeam) {
|
||||
int action = getMethod((PacketPlayOutScoreboardTeam) packet);
|
||||
if (action == TeamAction.UPDATE) return;
|
||||
Collection<String> players = (Collection<String>) TeamPacket_PLAYERS.get(packet);
|
||||
if (players == null) players = Collections.emptyList();
|
||||
TeamPacket_PLAYERS.set(packet, onTeamPacket(action, ((PacketPlayOutScoreboardTeam)packet).d(), players));
|
||||
}
|
||||
}
|
||||
|
||||
private int getMethod(@NonNull PacketPlayOutScoreboardTeam team) {
|
||||
if (team.c() == PacketPlayOutScoreboardTeam.a.a) {
|
||||
return 0;
|
||||
} else if (team.c() == PacketPlayOutScoreboardTeam.a.b) {
|
||||
return 1;
|
||||
} else if (team.b() == PacketPlayOutScoreboardTeam.a.a) {
|
||||
return 3;
|
||||
} else if (team.b() == PacketPlayOutScoreboardTeam.a.b) {
|
||||
return 4;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+21
-25
@@ -37,30 +37,6 @@ public class NMSPacketTabList extends TrackedTabList<BukkitTabPlayer> {
|
||||
private static final Field PlayerInfoData_Latency = ReflectionUtils.getFields(PlayerInfoData.class, int.class).get(0);
|
||||
private static final Field PlayerInfoData_DisplayName = ReflectionUtils.getOnlyField(PlayerInfoData.class, IChatBaseComponent.class);
|
||||
|
||||
@SneakyThrows
|
||||
public static void onPacketSend(@NonNull Object packet, @NonNull TrackedTabList<BukkitTabPlayer> tabList) {
|
||||
if (!(packet instanceof PacketPlayOutPlayerInfo)) return;
|
||||
EnumPlayerInfoAction action = ((PacketPlayOutPlayerInfo)packet).c();
|
||||
for (PlayerInfoData nmsData : ((PacketPlayOutPlayerInfo)packet).b()) {
|
||||
GameProfile profile = nmsData.a();
|
||||
UUID id = profile.getId();
|
||||
if (action == EnumPlayerInfoAction.d || action == EnumPlayerInfoAction.a) {
|
||||
TabComponent expectedName = tabList.getExpectedDisplayNames().get(id);
|
||||
if (expectedName != null) PlayerInfoData_DisplayName.set(nmsData, expectedName.convert());
|
||||
}
|
||||
if (action == EnumPlayerInfoAction.c || action == EnumPlayerInfoAction.a) {
|
||||
int oldLatency = nmsData.b();
|
||||
int newLatency = TAB.getInstance().getFeatureManager().onLatencyChange(tabList.getPlayer(), id, oldLatency);
|
||||
if (oldLatency != newLatency) {
|
||||
PlayerInfoData_Latency.set(nmsData, newLatency);
|
||||
}
|
||||
}
|
||||
if (action == EnumPlayerInfoAction.a) {
|
||||
TAB.getInstance().getFeatureManager().onEntryAdd(tabList.getPlayer(), id, profile.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance.
|
||||
*
|
||||
@@ -134,8 +110,28 @@ public class NMSPacketTabList extends TrackedTabList<BukkitTabPlayer> {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void onPacketSend(@NonNull Object packet) {
|
||||
onPacketSend(packet, this);
|
||||
if (!(packet instanceof PacketPlayOutPlayerInfo)) return;
|
||||
EnumPlayerInfoAction action = ((PacketPlayOutPlayerInfo)packet).c();
|
||||
for (PlayerInfoData nmsData : ((PacketPlayOutPlayerInfo)packet).b()) {
|
||||
GameProfile profile = nmsData.a();
|
||||
UUID id = profile.getId();
|
||||
if (action == EnumPlayerInfoAction.d || action == EnumPlayerInfoAction.a) {
|
||||
TabComponent expectedName = getExpectedDisplayNames().get(id);
|
||||
if (expectedName != null) PlayerInfoData_DisplayName.set(nmsData, expectedName.convert());
|
||||
}
|
||||
if (action == EnumPlayerInfoAction.c || action == EnumPlayerInfoAction.a) {
|
||||
int oldLatency = nmsData.b();
|
||||
int newLatency = TAB.getInstance().getFeatureManager().onLatencyChange(player, id, oldLatency);
|
||||
if (oldLatency != newLatency) {
|
||||
PlayerInfoData_Latency.set(nmsData, newLatency);
|
||||
}
|
||||
}
|
||||
if (action == EnumPlayerInfoAction.a) {
|
||||
TAB.getInstance().getFeatureManager().onEntryAdd(player, id, profile.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
|
||||
-13
@@ -2,12 +2,9 @@ package me.neznamy.tab.platforms.bukkit.v1_8_R3;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ComponentConverter;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ImplementationProvider;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.viaversion.ViaScoreboard;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.viaversion.ViaTabList;
|
||||
import me.neznamy.tab.shared.platform.Scoreboard;
|
||||
import me.neznamy.tab.shared.platform.TabList;
|
||||
import me.neznamy.tab.shared.util.function.FunctionWithException;
|
||||
@@ -29,16 +26,6 @@ public class NMSImplementationProvider implements ImplementationProvider {
|
||||
return new NMSPacketScoreboard(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSend(@NonNull Object packet, @NonNull ViaScoreboard scoreboard) {
|
||||
NMSPacketScoreboard.onPacketSend(packet, scoreboard);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSend(@NonNull Object packet, @NonNull ViaTabList tabList) {
|
||||
NMSPacketTabList.onPacketSend(packet, tabList);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public TabList newTabList(@NotNull BukkitTabPlayer player) {
|
||||
|
||||
+29
-25
@@ -33,26 +33,6 @@ public class NMSPacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
private static final Field DisplayObjective_OBJECTIVE_NAME = ReflectionUtils.getOnlyField(PacketPlayOutScoreboardDisplayObjective.class, String.class);
|
||||
private static final Field DisplayObjective_POSITION = ReflectionUtils.getOnlyField(PacketPlayOutScoreboardDisplayObjective.class, int.class);
|
||||
|
||||
@SneakyThrows
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void onPacketSend(@NonNull Object packet, @NonNull SafeScoreboard<BukkitTabPlayer> scoreboard) {
|
||||
if (packet instanceof PacketPlayOutScoreboardDisplayObjective) {
|
||||
TAB.getInstance().getFeatureManager().onDisplayObjective(scoreboard.getPlayer(), DisplayObjective_POSITION.getInt(packet),
|
||||
(String) DisplayObjective_OBJECTIVE_NAME.get(packet));
|
||||
}
|
||||
if (packet instanceof PacketPlayOutScoreboardObjective) {
|
||||
TAB.getInstance().getFeatureManager().onObjective(scoreboard.getPlayer(),
|
||||
Objective_METHOD.getInt(packet), (String) Objective_OBJECTIVE_NAME.get(packet));
|
||||
}
|
||||
if (packet instanceof PacketPlayOutScoreboardTeam) {
|
||||
int action = TeamPacket_ACTION.getInt(packet);
|
||||
if (action == TeamAction.UPDATE) return;
|
||||
Collection<String> players = (Collection<String>) TeamPacket_PLAYERS.get(packet);
|
||||
if (players == null) players = Collections.emptyList();
|
||||
TeamPacket_PLAYERS.set(packet, scoreboard.onTeamPacket(action, (String) TeamPacket_NAME.get(packet), players));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance with given player.
|
||||
*
|
||||
@@ -66,7 +46,7 @@ public class NMSPacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
@Override
|
||||
public void registerObjective(@NonNull Objective objective) {
|
||||
ScoreboardObjective obj = new ScoreboardObjective(dummyScoreboard, objective.getName(), IScoreboardCriteria.b);
|
||||
obj.setDisplayName(cutTo(objective.getTitle().toLegacyText(), Limitations.SCOREBOARD_TITLE_PRE_1_13));
|
||||
obj.setDisplayName(maybeCut(objective.getTitle().toLegacyText(), Limitations.SCOREBOARD_TITLE_PRE_1_13));
|
||||
obj.a(IScoreboardCriteria.EnumScoreboardHealthDisplay.valueOf(objective.getHealthDisplay().name()));
|
||||
objective.setPlatformObjective(obj);
|
||||
sendPacket(new PacketPlayOutScoreboardObjective(obj, ObjectiveAction.REGISTER));
|
||||
@@ -85,7 +65,7 @@ public class NMSPacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
@Override
|
||||
public void updateObjective(@NonNull Objective objective) {
|
||||
ScoreboardObjective obj = (ScoreboardObjective) objective.getPlatformObjective();
|
||||
obj.setDisplayName(cutTo(objective.getTitle().toLegacyText(), Limitations.SCOREBOARD_TITLE_PRE_1_13));
|
||||
obj.setDisplayName(maybeCut(objective.getTitle().toLegacyText(), Limitations.SCOREBOARD_TITLE_PRE_1_13));
|
||||
obj.a(IScoreboardCriteria.EnumScoreboardHealthDisplay.valueOf(objective.getHealthDisplay().name()));
|
||||
sendPacket(new PacketPlayOutScoreboardObjective(obj, ObjectiveAction.UPDATE));
|
||||
}
|
||||
@@ -132,13 +112,29 @@ public class NMSPacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
t.setAllowFriendlyFire((team.getOptions() & 0x01) != 0);
|
||||
t.setCanSeeFriendlyInvisibles((team.getOptions() & 0x02) != 0);
|
||||
t.setNameTagVisibility(visibilities[team.getVisibility().ordinal()]);
|
||||
t.setPrefix(cutTo(team.getPrefix().toLegacyText(), Limitations.TEAM_PREFIX_SUFFIX_PRE_1_13));
|
||||
t.setSuffix(cutTo(team.getSuffix().toLegacyText(), Limitations.TEAM_PREFIX_SUFFIX_PRE_1_13));
|
||||
t.setPrefix(maybeCut(team.getPrefix().toLegacyText(), Limitations.TEAM_PREFIX_SUFFIX_PRE_1_13));
|
||||
t.setSuffix(maybeCut(team.getSuffix().toLegacyText(), Limitations.TEAM_PREFIX_SUFFIX_PRE_1_13));
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
@SuppressWarnings("unchecked")
|
||||
public void onPacketSend(@NonNull Object packet) {
|
||||
onPacketSend(packet, this);
|
||||
if (packet instanceof PacketPlayOutScoreboardDisplayObjective) {
|
||||
TAB.getInstance().getFeatureManager().onDisplayObjective(player, DisplayObjective_POSITION.getInt(packet),
|
||||
(String) DisplayObjective_OBJECTIVE_NAME.get(packet));
|
||||
}
|
||||
if (packet instanceof PacketPlayOutScoreboardObjective) {
|
||||
TAB.getInstance().getFeatureManager().onObjective(player,
|
||||
Objective_METHOD.getInt(packet), (String) Objective_OBJECTIVE_NAME.get(packet));
|
||||
}
|
||||
if (packet instanceof PacketPlayOutScoreboardTeam) {
|
||||
int action = TeamPacket_ACTION.getInt(packet);
|
||||
if (action == TeamAction.UPDATE) return;
|
||||
Collection<String> players = (Collection<String>) TeamPacket_PLAYERS.get(packet);
|
||||
if (players == null) players = Collections.emptyList();
|
||||
TeamPacket_PLAYERS.set(packet, onTeamPacket(action, (String) TeamPacket_NAME.get(packet), players));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,4 +146,12 @@ public class NMSPacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
private void sendPacket(@NotNull Packet<?> packet) {
|
||||
((CraftPlayer)player.getPlayer()).getHandle().playerConnection.sendPacket(packet);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String maybeCut(@NonNull String string, int length) {
|
||||
if (player.getVersion().getMinorVersion() < 13 || TAB.getInstance().getConfiguration().getConfig().isPacketEventsCompensation()) {
|
||||
return cutTo(string, length);
|
||||
}
|
||||
return string;
|
||||
}
|
||||
}
|
||||
+22
-26
@@ -36,31 +36,6 @@ public class NMSPacketTabList extends TrackedTabList<BukkitTabPlayer> {
|
||||
|
||||
private static final Field FOOTER = ReflectionUtils.getFields(PacketPlayOutPlayerListHeaderFooter.class, IChatBaseComponent.class).get(1);
|
||||
|
||||
@SneakyThrows
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void onPacketSend(@NonNull Object packet, TrackedTabList<BukkitTabPlayer> tabList) {
|
||||
if (!(packet instanceof PacketPlayOutPlayerInfo)) return;
|
||||
EnumPlayerInfoAction action = (EnumPlayerInfoAction) ACTION.get(packet);
|
||||
for (PlayerInfoData nmsData : (List<PlayerInfoData>) PLAYERS.get(packet)) {
|
||||
GameProfile profile = nmsData.a();
|
||||
UUID id = profile.getId();
|
||||
if (action == EnumPlayerInfoAction.UPDATE_DISPLAY_NAME || action == EnumPlayerInfoAction.ADD_PLAYER) {
|
||||
TabComponent expectedName = tabList.getExpectedDisplayNames().get(id);
|
||||
if (expectedName != null) PlayerInfoData_DisplayName.set(nmsData, expectedName.convert());
|
||||
}
|
||||
if (action == EnumPlayerInfoAction.UPDATE_LATENCY || action == EnumPlayerInfoAction.ADD_PLAYER) {
|
||||
int oldLatency = PlayerInfoData_Latency.getInt(nmsData);
|
||||
int newLatency = TAB.getInstance().getFeatureManager().onLatencyChange(tabList.getPlayer(), id, oldLatency);
|
||||
if (oldLatency != newLatency) {
|
||||
PlayerInfoData_Latency.set(nmsData, newLatency);
|
||||
}
|
||||
}
|
||||
if (action == EnumPlayerInfoAction.ADD_PLAYER) {
|
||||
TAB.getInstance().getFeatureManager().onEntryAdd(tabList.getPlayer(), id, profile.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance.
|
||||
*
|
||||
@@ -136,8 +111,29 @@ public class NMSPacketTabList extends TrackedTabList<BukkitTabPlayer> {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
@SuppressWarnings("unchecked")
|
||||
public void onPacketSend(@NonNull Object packet) {
|
||||
onPacketSend(packet, this);
|
||||
if (!(packet instanceof PacketPlayOutPlayerInfo)) return;
|
||||
EnumPlayerInfoAction action = (EnumPlayerInfoAction) ACTION.get(packet);
|
||||
for (PlayerInfoData nmsData : (List<PlayerInfoData>) PLAYERS.get(packet)) {
|
||||
GameProfile profile = nmsData.a();
|
||||
UUID id = profile.getId();
|
||||
if (action == EnumPlayerInfoAction.UPDATE_DISPLAY_NAME || action == EnumPlayerInfoAction.ADD_PLAYER) {
|
||||
TabComponent expectedName = getExpectedDisplayNames().get(id);
|
||||
if (expectedName != null) PlayerInfoData_DisplayName.set(nmsData, expectedName.convert());
|
||||
}
|
||||
if (action == EnumPlayerInfoAction.UPDATE_LATENCY || action == EnumPlayerInfoAction.ADD_PLAYER) {
|
||||
int oldLatency = PlayerInfoData_Latency.getInt(nmsData);
|
||||
int newLatency = TAB.getInstance().getFeatureManager().onLatencyChange(player, id, oldLatency);
|
||||
if (oldLatency != newLatency) {
|
||||
PlayerInfoData_Latency.set(nmsData, newLatency);
|
||||
}
|
||||
}
|
||||
if (action == EnumPlayerInfoAction.ADD_PLAYER) {
|
||||
TAB.getInstance().getFeatureManager().onEntryAdd(player, id, profile.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
dependencies {
|
||||
implementation(projects.shared)
|
||||
implementation("org.bstats:bstats-bungeecord:3.1.0")
|
||||
compileOnly("net.md-5:bungeecord-proxy:1.21-R0.1-SNAPSHOT")
|
||||
compileOnly("net.md-5:bungeecord-proxy:1.21-R0.4-SNAPSHOT")
|
||||
compileOnly("com.github.limework.redisbungee:RedisBungee-Bungee:0.11.0")
|
||||
compileOnly("com.github.LeonMangler:PremiumVanishAPI:2.8.8")
|
||||
}
|
||||
@@ -8,12 +8,13 @@ import me.neznamy.tab.shared.ProtocolVersion;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.platform.decorators.SafeScoreboard;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.protocol.Either;
|
||||
import net.md_5.bungee.protocol.NumberFormat;
|
||||
import net.md_5.bungee.protocol.data.NumberFormat;
|
||||
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.ScoreboardScoreReset;
|
||||
import net.md_5.bungee.protocol.packet.Team.NameTagVisibility;
|
||||
import net.md_5.bungee.protocol.util.Either;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -119,14 +120,32 @@ public class BungeeScoreboard extends SafeScoreboard<BungeeTabPlayer> {
|
||||
either(TabComponent.legacyText(team.getName()), Limitations.TEAM_PREFIX_SUFFIX_PRE_1_13),
|
||||
either(team.getPrefix(), Limitations.TEAM_PREFIX_SUFFIX_PRE_1_13),
|
||||
either(team.getSuffix(), Limitations.TEAM_PREFIX_SUFFIX_PRE_1_13),
|
||||
net.md_5.bungee.protocol.packet.Team.NameTagVisibility.valueOf(team.getVisibility().name()),
|
||||
net.md_5.bungee.protocol.packet.Team.CollisionRule.valueOf(team.getCollision().name()),
|
||||
convertVisibility(team.getVisibility()),
|
||||
convertCollision(team.getCollision()),
|
||||
player.getVersion().getMinorVersion() >= TEAM_REWORK_VERSION ? team.getColor().getLegacyColor().ordinal() : 0,
|
||||
(byte) team.getOptions(),
|
||||
team.getPlayers().toArray(new String[0])
|
||||
));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Either<String, NameTagVisibility> convertVisibility(@NotNull NameVisibility visibility) {
|
||||
if (player.getVersion().getNetworkId() >= ProtocolVersion.V1_21_5.getNetworkId()) {
|
||||
return Either.right(NameTagVisibility.valueOf(visibility.name()));
|
||||
} else {
|
||||
return Either.left(visibility.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Either<String, net.md_5.bungee.protocol.packet.Team.CollisionRule> convertCollision(@NotNull CollisionRule collision) {
|
||||
if (player.getVersion().getNetworkId() >= ProtocolVersion.V1_21_5.getNetworkId()) {
|
||||
return Either.right(net.md_5.bungee.protocol.packet.Team.CollisionRule.valueOf(collision.name()));
|
||||
} else {
|
||||
return Either.left(collision.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSend(@NonNull Object packet) {
|
||||
if (packet instanceof ScoreboardDisplay) {
|
||||
|
||||
@@ -11,17 +11,27 @@ public class BungeeTAB extends Plugin {
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
if (ReflectionUtils.classExists("net.md_5.bungee.protocol.packet.Team$NameTagVisibility")) {
|
||||
if (isCompatible()) {
|
||||
TAB.create(new BungeePlatform(this));
|
||||
} else {
|
||||
getLogger().warning("§c====================================================================================================");
|
||||
getLogger().warning("§cThe plugin requires BungeeCord build #1899 " +
|
||||
"(released on February 1st, 2025) and up (or an equivalent fork) to work. If you are using a fork that did not" +
|
||||
" update to the new BungeeCord version yet, stay on TAB v5.0.5, which supports older builds.");
|
||||
getLogger().warning("§c====================================================================================================");
|
||||
logIncompatibleVersionWarning();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isCompatible() {
|
||||
return ReflectionUtils.classExists("net.md_5.bungee.protocol.util.Either");
|
||||
}
|
||||
|
||||
private void logIncompatibleVersionWarning() {
|
||||
int buildNumber = 1990;
|
||||
String releaseDate = "July 14th, 2025";
|
||||
String oldTabVersion = "5.2.4";
|
||||
getLogger().warning("§c====================================================================================================");
|
||||
getLogger().warning(String.format("§cThe plugin requires BungeeCord build #%d (released on %s) and up (or an equivalent fork) to work.", buildNumber, releaseDate));
|
||||
getLogger().warning(String.format("§cIf you are using a fork that did not update to the new BungeeCord version yet, stay on TAB v%s, which supports older builds.", oldTabVersion));
|
||||
getLogger().warning("§c====================================================================================================");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
if (TAB.getInstance() != null) TAB.getInstance().unload();
|
||||
|
||||
+2
-3
@@ -11,8 +11,7 @@ import net.md_5.bungee.UserConnection;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.connection.InitialHandler;
|
||||
import net.md_5.bungee.connection.LoginResult;
|
||||
import net.md_5.bungee.protocol.Property;
|
||||
import net.md_5.bungee.protocol.packet.PlayerListHeaderFooter;
|
||||
import net.md_5.bungee.protocol.data.Property;
|
||||
import net.md_5.bungee.protocol.packet.PlayerListItem;
|
||||
import net.md_5.bungee.protocol.packet.PlayerListItem.Item;
|
||||
import net.md_5.bungee.protocol.packet.PlayerListItemUpdate;
|
||||
@@ -47,7 +46,7 @@ public abstract class BungeeTabList extends TrackedTabList<BungeeTabPlayer> {
|
||||
|
||||
@Override
|
||||
public void setPlayerListHeaderFooter(@NonNull TabComponent header, @NonNull TabComponent footer) {
|
||||
player.sendPacket(new PlayerListHeaderFooter(toComponent(header), toComponent(footer)));
|
||||
player.getPlayer().setTabHeader(toComponent(header), toComponent(footer));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
dependencies {
|
||||
compileOnlyApi("net.kyori:adventure-api:4.18.0")
|
||||
compileOnlyApi("com.viaversion:viaversion-api:5.2.1")
|
||||
compileOnlyApi("com.viaversion:viaversion-common:5.2.1")
|
||||
}
|
||||
@@ -1,8 +1,5 @@
|
||||
package me.neznamy.chat.component;
|
||||
|
||||
import com.viaversion.nbt.tag.Tag;
|
||||
import com.viaversion.viaversion.libs.gson.JsonElement;
|
||||
import com.viaversion.viaversion.util.ComponentUtil;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.Setter;
|
||||
@@ -11,7 +8,6 @@ import me.neznamy.chat.ChatModifier;
|
||||
import me.neznamy.chat.EnumChatFormat;
|
||||
import me.neznamy.chat.TextColor;
|
||||
import me.neznamy.chat.hook.AdventureHook;
|
||||
import me.neznamy.chat.hook.ViaVersionHook;
|
||||
import me.neznamy.chat.rgb.RGBUtils;
|
||||
import me.neznamy.chat.util.TriFunction;
|
||||
import net.kyori.adventure.text.Component;
|
||||
@@ -112,15 +108,6 @@ public abstract class TabComponent {
|
||||
@Setter
|
||||
private Component adventureComponent;
|
||||
|
||||
/** ViaVersion component from this component */
|
||||
@Nullable
|
||||
@Setter
|
||||
private JsonElement viaComponent;
|
||||
/** ViaVersion tag from this component */
|
||||
@Nullable
|
||||
@Setter
|
||||
private Tag viaTag;
|
||||
|
||||
@Nullable
|
||||
private Object fixedFormat;
|
||||
|
||||
@@ -191,26 +178,6 @@ public abstract class TabComponent {
|
||||
return adventureComponent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this component to an ViaVersion component.
|
||||
* @return Converted component
|
||||
*/
|
||||
@NotNull
|
||||
public JsonElement toViaVersion() {
|
||||
if (viaComponent == null) viaComponent = ViaVersionHook.convert(this);
|
||||
return viaComponent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this component to an ViaVersion tag.
|
||||
* @return Converted component
|
||||
*/
|
||||
@NotNull
|
||||
public Tag toViaVersionTag() {
|
||||
if (viaTag == null) viaTag = ComponentUtil.jsonToTag(toViaVersion());
|
||||
return viaTag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a FixedFormat using given platform-specific create function.
|
||||
* If the value is already initialized, it is returned immediately instead.
|
||||
@@ -334,7 +301,7 @@ public abstract class TabComponent {
|
||||
break;
|
||||
}
|
||||
}
|
||||
final TextComponent component = new TextComponent("", components);
|
||||
TextComponent component = new TextComponent("", components);
|
||||
// Safe check to avoid rare mojang "bug" that display text as italic by default
|
||||
// This doesn't affect #toLegacyText() method at all
|
||||
component.modifier.setItalic(false);
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
package me.neznamy.chat.hook;
|
||||
|
||||
import com.viaversion.viaversion.libs.gson.JsonArray;
|
||||
import com.viaversion.viaversion.libs.gson.JsonElement;
|
||||
import com.viaversion.viaversion.libs.gson.JsonObject;
|
||||
import com.viaversion.viaversion.util.ComponentUtil;
|
||||
import me.neznamy.chat.ChatModifier;
|
||||
import me.neznamy.chat.component.KeybindComponent;
|
||||
import me.neznamy.chat.component.LegacyTextComponent;
|
||||
import me.neznamy.chat.component.TabComponent;
|
||||
import me.neznamy.chat.component.TextComponent;
|
||||
import me.neznamy.chat.component.TranslatableComponent;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public class ViaVersionHook {
|
||||
|
||||
@NotNull
|
||||
public static JsonElement convert(@NotNull TabComponent component) {
|
||||
if (component instanceof LegacyTextComponent) {
|
||||
return ComponentUtil.legacyToJson(component.toLegacyText());
|
||||
}
|
||||
|
||||
final JsonObject object = new JsonObject();
|
||||
|
||||
// Root
|
||||
if (component instanceof TextComponent) {
|
||||
object.addProperty("type", "text"); // +1.20.3 optimization
|
||||
object.addProperty("text", ((TextComponent) component).getText());
|
||||
} else if (component instanceof TranslatableComponent) {
|
||||
object.addProperty("type", "translatable"); // +1.20.3 optimization
|
||||
object.addProperty("translate", ((TranslatableComponent) component).getKey());
|
||||
} else if (component instanceof KeybindComponent) {
|
||||
object.addProperty("type", "keybind"); // +1.20.3 optimization
|
||||
object.addProperty("keybind", ((KeybindComponent) component).getKeybind());
|
||||
} else {
|
||||
throw new IllegalStateException("Unknown component type: " + component.getClass().getName());
|
||||
}
|
||||
|
||||
// Color
|
||||
final ChatModifier modifier = component.getModifier();
|
||||
if (modifier.getColor() != null) {
|
||||
object.addProperty("color", "#" + modifier.getColor().getHexCode());
|
||||
}
|
||||
if (modifier.getShadowColor() != null) {
|
||||
object.addProperty("shadow_color", modifier.getShadowColor());
|
||||
}
|
||||
|
||||
// Render
|
||||
if (Boolean.TRUE.equals(modifier.getBold())) {
|
||||
object.addProperty("bold", true);
|
||||
}
|
||||
if (modifier.getItalic() != null) {
|
||||
object.addProperty("italic", modifier.getItalic());
|
||||
}
|
||||
if (Boolean.TRUE.equals(modifier.getObfuscated())) {
|
||||
object.addProperty("obfuscated", true);
|
||||
}
|
||||
if (Boolean.TRUE.equals(modifier.getStrikethrough())) {
|
||||
object.addProperty("strikethrough", true);
|
||||
}
|
||||
if (Boolean.TRUE.equals(modifier.getUnderlined())) {
|
||||
object.addProperty("underlined", true);
|
||||
}
|
||||
if (modifier.getFont() != null) {
|
||||
object.addProperty("font", modifier.getFont());
|
||||
}
|
||||
|
||||
// Extra
|
||||
if (!component.getExtra().isEmpty()) {
|
||||
final JsonArray extra = new JsonArray();
|
||||
for (TabComponent sub : component.getExtra()) {
|
||||
extra.add((JsonElement) convert(sub));
|
||||
}
|
||||
object.add("extra", extra);
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
}
|
||||
@@ -11,10 +11,12 @@ repositories {
|
||||
maven("https://maven.nucleoid.xyz/")
|
||||
}
|
||||
|
||||
val minecraftVersion = "1.21.6"
|
||||
val minecraftVersion = "1.21.8"
|
||||
|
||||
// Fabric API versions for each Minecraft version for easier backporting
|
||||
val fabricApiVersions = mapOf(
|
||||
"1.21.8" to "0.129.0+1.21.8",
|
||||
"1.21.7" to "0.128.1+1.21.7",
|
||||
"1.21.6" to "0.125.1+1.21.6",
|
||||
"1.21.5" to "0.119.9+1.21.5",
|
||||
"1.21.4" to "0.119.2+1.21.4",
|
||||
|
||||
@@ -14,7 +14,9 @@
|
||||
"fabric-api-base": "*",
|
||||
"java": ">=17",
|
||||
"minecraft": [
|
||||
"1.21.6"
|
||||
"1.21.6",
|
||||
"1.21.7",
|
||||
"1.21.8"
|
||||
]
|
||||
},
|
||||
"recommends": {
|
||||
|
||||
@@ -12,10 +12,13 @@ repositories {
|
||||
maven("https://maven.neoforged.net/releases")
|
||||
}
|
||||
|
||||
val minecraftVersion = "1.21.6"
|
||||
val minecraftVersion = "1.21.8"
|
||||
|
||||
// Forge API versions for each Minecraft version for easier backporting
|
||||
// Official website (for updating in the future): https://files.minecraftforge.net/net/minecraftforge/forge/
|
||||
val forgeApiVersions = mapOf(
|
||||
"1.21.8" to "1.21.8-58.0.0",
|
||||
"1.21.7" to "1.21.7-57.0.0",
|
||||
"1.21.6" to "1.21.6-56.0.0",
|
||||
"1.21.5" to "1.21.5-55.0.3",
|
||||
"1.21.4" to "1.21.4-54.1.3",
|
||||
|
||||
@@ -22,6 +22,6 @@ side = "SERVER"
|
||||
[[dependencies.tab]]
|
||||
modId = "minecraft"
|
||||
mandatory = true
|
||||
versionRange = "[1.21.6]"
|
||||
versionRange = "[1.21.6],[1.21.7],[1.21.8]"
|
||||
ordering = "NONE"
|
||||
side = "SERVER"
|
||||
@@ -12,10 +12,13 @@ repositories {
|
||||
maven("https://maven.neoforged.net/releases")
|
||||
}
|
||||
|
||||
val minecraftVersion = "1.21.6"
|
||||
val minecraftVersion = "1.21.8"
|
||||
|
||||
// NeoForge API versions for each Minecraft version for easier backporting
|
||||
// Official website (for updating in the future): https://projects.neoforged.net/neoforged/neoforge
|
||||
val neoforgeApiVersions = mapOf(
|
||||
"1.21.8" to "21.8.2-beta",
|
||||
"1.21.7" to "21.7.1-beta",
|
||||
"1.21.6" to "21.6.5-beta",
|
||||
"1.21.5" to "21.5.77",
|
||||
"1.21.4" to "21.4.138",
|
||||
|
||||
@@ -21,6 +21,6 @@ side = "SERVER"
|
||||
[[dependencies.tab]]
|
||||
modId = "minecraft"
|
||||
type = "required"
|
||||
versionRange = "[1.21.6]"
|
||||
versionRange = "[1.21.6],[1.21.7],[1.21.8]"
|
||||
ordering = "NONE"
|
||||
side = "SERVER"
|
||||
@@ -1,19 +1,18 @@
|
||||
package me.neznamy.tab.shared;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Getter;
|
||||
import me.neznamy.chat.EnumChatFormat;
|
||||
import me.neznamy.tab.shared.features.PlaceholderManagerImpl;
|
||||
import me.neznamy.tab.shared.features.types.RefreshableFeature;
|
||||
import me.neznamy.chat.EnumChatFormat;
|
||||
import me.neznamy.chat.rgb.RGBUtils;
|
||||
import me.neznamy.tab.shared.placeholders.expansion.TabExpansion;
|
||||
import me.neznamy.tab.shared.placeholders.types.RelationalPlaceholderImpl;
|
||||
import me.neznamy.tab.shared.platform.TabPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A dynamic text with placeholder support. If any placeholder
|
||||
* used in this text changes value, feature defining this text
|
||||
@@ -315,4 +314,18 @@ public class Property {
|
||||
}
|
||||
return format;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns original raw value with placeholders replaced by their values.
|
||||
*
|
||||
* @return original raw value with placeholders replaced
|
||||
*/
|
||||
@NotNull
|
||||
public String getOriginalReplacedValue() {
|
||||
String value = originalRawValue;
|
||||
for (String identifier : PlaceholderManagerImpl.detectPlaceholders(value)) {
|
||||
value = TAB.getInstance().getPlaceholderManager().getPlaceholder(identifier).set(identifier, owner);
|
||||
}
|
||||
return EnumChatFormat.color(value);
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,8 @@ import org.jetbrains.annotations.NotNull;
|
||||
public enum ProtocolVersion {
|
||||
|
||||
UNKNOWN,
|
||||
V1_21_8 (772),
|
||||
V1_21_7 (772),
|
||||
V1_21_6 (771),
|
||||
V1_21_5 (770),
|
||||
V1_21_4 (769),
|
||||
|
||||
@@ -33,7 +33,7 @@ public class MySQLConfiguration {
|
||||
@NotNull
|
||||
public static MySQLConfiguration fromSection(@NonNull ConfigurationSection section) {
|
||||
// Check keys
|
||||
section.checkForUnknownKey(Arrays.asList("enabled", "host", "port", "database", "username", "password", "useSSL"));
|
||||
section.checkForUnknownKey(Arrays.asList("enabled", "host", "port", "database", "username", "password", "usessl"));
|
||||
|
||||
return new MySQLConfiguration(
|
||||
section.getString("host", "127.0.0.1"),
|
||||
|
||||
@@ -93,6 +93,7 @@ public class BossBarManagerImpl extends RefreshableFeature implements BossBarMan
|
||||
|
||||
@Override
|
||||
public void onJoin(@NotNull TabPlayer connectedPlayer) {
|
||||
TAB.getInstance().getPlaceholderManager().getTabExpansion().setBossBarVisible(connectedPlayer, false);
|
||||
if (toggleManager != null) toggleManager.convert(connectedPlayer);
|
||||
setBossBarVisible(connectedPlayer, configuration.isHiddenByDefault() == (toggleManager != null && toggleManager.contains(connectedPlayer)), false);
|
||||
}
|
||||
@@ -186,6 +187,32 @@ public class BossBarManagerImpl extends RefreshableFeature implements BossBarMan
|
||||
return Collections.unmodifiableMap(registeredBossBars);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeBossBar(@NonNull String name) {
|
||||
ensureActive();
|
||||
BossBar bar = registeredBossBars.remove(name);
|
||||
if (bar == null) throw new IllegalArgumentException("No registered BossBar found with name " + name);
|
||||
lineValues = registeredBossBars.values().toArray(new BossBarLine[0]);
|
||||
for (TabPlayer player : TAB.getInstance().getOnlinePlayers()) {
|
||||
bar.removePlayer(player);
|
||||
player.bossbarData.visibleBossBars.remove(bar);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeBossBar(@NonNull BossBar bossBar) {
|
||||
ensureActive();
|
||||
BossBarLine bar = (BossBarLine) bossBar;
|
||||
if (!registeredBossBars.remove(bar.getName(), bar)) {
|
||||
throw new IllegalArgumentException("This bossbar (" + bar.getName() + ") is not registered.");
|
||||
}
|
||||
lineValues = registeredBossBars.values().toArray(new BossBarLine[0]);
|
||||
for (TabPlayer player : TAB.getInstance().getOnlinePlayers()) {
|
||||
bar.removePlayer(player);
|
||||
player.bossbarData.visibleBossBars.remove(bar);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toggleBossBar(@NonNull me.neznamy.tab.api.TabPlayer player, boolean sendToggleMessage) {
|
||||
ensureActive();
|
||||
|
||||
@@ -4,6 +4,7 @@ import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import me.neznamy.chat.EnumChatFormat;
|
||||
import me.neznamy.tab.shared.ProtocolVersion;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.config.file.ConfigurationSection;
|
||||
import me.neznamy.tab.shared.platform.TabPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -107,14 +108,16 @@ public class LayoutConfiguration {
|
||||
}
|
||||
|
||||
public String getEntryName(@NotNull TabPlayer viewer, int slot, boolean teamsEnabled) {
|
||||
if (viewer.getVersion().getNetworkId() >= ProtocolVersion.V1_19_3.getNetworkId() && viewer.getVersion().getNetworkId() < ProtocolVersion.V1_21_2.getNetworkId()) {
|
||||
boolean legacySorting = viewer.getVersion().getNetworkId() < ProtocolVersion.V1_19_3.getNetworkId();
|
||||
boolean modernSorting = viewer.getVersion().getNetworkId() >= ProtocolVersion.V1_21_2.getNetworkId() && TAB.getInstance().getPlatform().supportsListOrder();
|
||||
if (legacySorting || modernSorting) {
|
||||
return "";
|
||||
} else {
|
||||
if (teamsEnabled) {
|
||||
return "|slot_" + (10+slotTranslator.apply(slot));
|
||||
} else {
|
||||
return " slot_" + (10+slotTranslator.apply(slot));
|
||||
}
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,10 +34,14 @@ public class ParentGroup {
|
||||
public void tick(@NotNull List<TabPlayer> remainingPlayers) {
|
||||
players.clear();
|
||||
List<TabPlayer> meetingCondition = new ArrayList<>();
|
||||
for (TabPlayer p : remainingPlayers) {
|
||||
if (condition == null || condition.isMet(p)) meetingCondition.add(p);
|
||||
}
|
||||
remainingPlayers.removeAll(meetingCondition);
|
||||
|
||||
// High-performance way to filter players
|
||||
remainingPlayers.removeIf(p -> {
|
||||
boolean met = (condition == null || condition.isMet(p));
|
||||
if (met) meetingCondition.add(p);
|
||||
return met;
|
||||
});
|
||||
|
||||
for (int index = 0; index < slots.length; index++) {
|
||||
int slot = slots[index];
|
||||
if (layout.getManager().getConfiguration().isRemainingPlayersTextEnabled() && index == slots.length - 1 && playerSlots.size() < meetingCondition.size()) {
|
||||
|
||||
@@ -665,7 +665,7 @@ public class NameTag extends RefreshableFeature implements NameTagManager, JoinL
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getOriginalPrefix(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
public String getOriginalRawPrefix(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
ensureActive();
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
@@ -674,13 +674,43 @@ public class NameTag extends RefreshableFeature implements NameTagManager, JoinL
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getOriginalSuffix(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
public String getOriginalRawSuffix(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
ensureActive();
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
return p.teamData.suffix.getOriginalRawValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getOriginalReplacedPrefix(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
ensureActive();
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
return p.teamData.prefix.getOriginalReplacedValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getOriginalReplacedSuffix(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
ensureActive();
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
return p.teamData.suffix.getOriginalReplacedValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getOriginalPrefix(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
return getOriginalRawPrefix(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getOriginalSuffix(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
return getOriginalRawSuffix(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toggleNameTagVisibilityView(@NonNull me.neznamy.tab.api.TabPlayer p, boolean sendToggleMessage) {
|
||||
setNameTagVisibilityView((TabPlayer) p, ((TabPlayer) p).teamData.invisibleNameTagView, sendToggleMessage);
|
||||
|
||||
@@ -335,26 +335,71 @@ public class PlayerList extends RefreshableFeature implements TabListFormatManag
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getOriginalPrefix(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
@NotNull
|
||||
public String getOriginalPrefix(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
return getOriginalRawPrefix(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getOriginalName(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
return getOriginalRawName(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getOriginalSuffix(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
return getOriginalRawSuffix(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getOriginalRawPrefix(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
ensureActive();
|
||||
((TabPlayer)player).ensureLoaded();
|
||||
return ((TabPlayer)player).tablistData.prefix.getOriginalRawValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getOriginalName(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
@NotNull
|
||||
public String getOriginalRawName(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
ensureActive();
|
||||
((TabPlayer)player).ensureLoaded();
|
||||
return ((TabPlayer)player).tablistData.name.getOriginalRawValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getOriginalSuffix(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
@NotNull
|
||||
public String getOriginalRawSuffix(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
ensureActive();
|
||||
((TabPlayer)player).ensureLoaded();
|
||||
return ((TabPlayer)player).tablistData.suffix.getOriginalRawValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getOriginalReplacedPrefix(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
ensureActive();
|
||||
((TabPlayer)player).ensureLoaded();
|
||||
return ((TabPlayer)player).tablistData.prefix.getOriginalReplacedValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getOriginalReplacedName(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
ensureActive();
|
||||
((TabPlayer)player).ensureLoaded();
|
||||
return ((TabPlayer)player).tablistData.name.getOriginalReplacedValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getOriginalReplacedSuffix(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
ensureActive();
|
||||
((TabPlayer)player).ensureLoaded();
|
||||
return ((TabPlayer)player).tablistData.suffix.getOriginalReplacedValue();
|
||||
}
|
||||
|
||||
// ------------------
|
||||
// ProxySupport
|
||||
// ------------------
|
||||
|
||||
@@ -77,8 +77,14 @@ public abstract class ProxySupport extends TabFeature implements JoinListener, Q
|
||||
TAB.getInstance().getErrorManager().unknownProxyMessage(action);
|
||||
return;
|
||||
}
|
||||
ProxyMessage proxyMessage = function.apply(in);
|
||||
TAB.getInstance().debug("[Proxy Support] Decoded message " + proxyMessage);
|
||||
ProxyMessage proxyMessage;
|
||||
try {
|
||||
proxyMessage = function.apply(in);
|
||||
TAB.getInstance().debug("[Proxy Support] Decoded message " + proxyMessage);
|
||||
} catch (Exception e) {
|
||||
TAB.getInstance().getErrorManager().printError("Failed to decode proxy message \"" + new String(Base64.getDecoder().decode(msg)) + "\" ", e);
|
||||
return;
|
||||
}
|
||||
|
||||
// Queue the task to make sure it does not execute before plugin fully loads, causing NPE
|
||||
TAB.getInstance().getCpu().runMeasuredTask(getFeatureName(), CpuUsageCategory.PROXY_MESSAGE, () -> {
|
||||
|
||||
+43
-9
@@ -24,6 +24,7 @@ import java.util.Map.Entry;
|
||||
/**
|
||||
* Feature handler for scoreboard feature.
|
||||
*/
|
||||
@Getter
|
||||
public class ScoreboardManagerImpl extends RefreshableFeature implements ScoreboardManager, JoinListener,
|
||||
CommandListener, DisplayObjectiveListener, ObjectiveListener, Loadable,
|
||||
QuitListener, CustomThreaded, ServerSwitchListener {
|
||||
@@ -31,18 +32,17 @@ public class ScoreboardManagerImpl extends RefreshableFeature implements Scorebo
|
||||
/** Objective name used by this feature */
|
||||
public static final String OBJECTIVE_NAME = "TAB-Scoreboard";
|
||||
|
||||
@Getter
|
||||
private final StringToComponentCache cache = new StringToComponentCache("Scoreboard", 1000);
|
||||
|
||||
@Getter
|
||||
private final ThreadExecutor customThread = new ThreadExecutor("TAB Scoreboard Thread");
|
||||
|
||||
@Getter
|
||||
private final ScoreboardConfiguration configuration;
|
||||
|
||||
//defined scoreboards
|
||||
@Getter private final Map<String, me.neznamy.tab.api.scoreboard.Scoreboard> registeredScoreboards = new LinkedHashMap<>();
|
||||
private me.neznamy.tab.api.scoreboard.Scoreboard[] definedScoreboards;
|
||||
/** All registered scoreboards, both in config and using the API */
|
||||
private final Map<String, ScoreboardImpl> registeredScoreboards = new LinkedHashMap<>();
|
||||
|
||||
/** Scoreboards defined in the config. This does not include scoreboards creating using API. */
|
||||
private ScoreboardImpl[] definedScoreboards;
|
||||
|
||||
/** Manager for toggled players if remembering is enabled in config */
|
||||
@Nullable
|
||||
@@ -73,7 +73,7 @@ public class ScoreboardManagerImpl extends RefreshableFeature implements Scorebo
|
||||
registeredScoreboards.put(scoreboardName, sb);
|
||||
TAB.getInstance().getFeatureManager().registerFeature(TabConstants.Feature.scoreboardLine(scoreboardName), sb);
|
||||
}
|
||||
definedScoreboards = registeredScoreboards.values().stream().filter(s -> !((ScoreboardImpl)s).isApi()).toArray(me.neznamy.tab.api.scoreboard.Scoreboard[]::new);
|
||||
definedScoreboards = registeredScoreboards.values().stream().filter(s -> !s.isApi()).toArray(ScoreboardImpl[]::new);
|
||||
for (TabPlayer p : TAB.getInstance().getOnlinePlayers()) {
|
||||
onJoin(p);
|
||||
}
|
||||
@@ -151,8 +151,8 @@ public class ScoreboardManagerImpl extends RefreshableFeature implements Scorebo
|
||||
*/
|
||||
public @Nullable me.neznamy.tab.api.scoreboard.Scoreboard detectHighestScoreboard(@NonNull TabPlayer p) {
|
||||
if (p.scoreboardData.forcedScoreboard != null) return p.scoreboardData.forcedScoreboard;
|
||||
for (me.neznamy.tab.api.scoreboard.Scoreboard sb : definedScoreboards) {
|
||||
if (((ScoreboardImpl)sb).isConditionMet(p)) return sb;
|
||||
for (ScoreboardImpl sb : definedScoreboards) {
|
||||
if (sb.isConditionMet(p)) return sb;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -214,6 +214,35 @@ public class ScoreboardManagerImpl extends RefreshableFeature implements Scorebo
|
||||
return sb;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeScoreboard(@NonNull String name) {
|
||||
ScoreboardImpl removed = registeredScoreboards.remove(name);
|
||||
if (removed == null) {
|
||||
throw new IllegalArgumentException("No registered scoreboard found with name " + name);
|
||||
}
|
||||
|
||||
Set<TabPlayer> players = removed.getPlayers();
|
||||
removed.unregister();
|
||||
for (TabPlayer p : players) {
|
||||
p.scoreboardData.forcedScoreboard = null;
|
||||
sendHighestScoreboard(p);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeScoreboard(@NonNull me.neznamy.tab.api.scoreboard.Scoreboard scoreboard) {
|
||||
if (!registeredScoreboards.remove(scoreboard.getName(), (ScoreboardImpl) scoreboard)) {
|
||||
throw new IllegalArgumentException("This scoreboard (" + scoreboard.getName() + ") is not registered.");
|
||||
}
|
||||
|
||||
Set<TabPlayer> players = ((ScoreboardImpl)scoreboard).getPlayers();
|
||||
scoreboard.unregister();
|
||||
for (TabPlayer p : players) {
|
||||
p.scoreboardData.forcedScoreboard = null;
|
||||
sendHighestScoreboard(p);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showScoreboard(@NonNull me.neznamy.tab.api.TabPlayer player, @NonNull me.neznamy.tab.api.scoreboard.Scoreboard scoreboard) {
|
||||
ensureActive();
|
||||
@@ -352,6 +381,11 @@ public class ScoreboardManagerImpl extends RefreshableFeature implements Scorebo
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Map<String, me.neznamy.tab.api.scoreboard.Scoreboard> getRegisteredScoreboards() {
|
||||
return Collections.unmodifiableMap(registeredScoreboards);
|
||||
}
|
||||
|
||||
/**
|
||||
* Class storing scoreboard data of players.
|
||||
*/
|
||||
|
||||
+2
-1
@@ -106,8 +106,9 @@ public class PlayerPlaceholderImpl extends TabPlaceholder implements PlayerPlace
|
||||
if (value == null) return false; //bridge placeholders, they are updated using updateValue method
|
||||
if (ERROR_VALUE.equals(value)) return false;
|
||||
String newValue = replacements.findReplacement(setPlaceholders(value, p));
|
||||
if (newValue.equals(identifier)) return false;
|
||||
String lastValue = p.lastPlaceholderValues.put(this, newValue);
|
||||
if (lastValue == null || (!identifier.equals(newValue) && !newValue.equals(lastValue))) {
|
||||
if (!newValue.equals(lastValue)) {
|
||||
if (updateParents) updateParents(p);
|
||||
TAB.getInstance().getPlaceholderManager().getTabExpansion().setPlaceholderValue(p, identifier, newValue);
|
||||
return true;
|
||||
|
||||
@@ -180,6 +180,15 @@ public interface Platform {
|
||||
*/
|
||||
boolean supportsScoreboards();
|
||||
|
||||
/**
|
||||
* Returns {@code true} if server supports list order option (1.21.2+), {@code false} if not.
|
||||
*
|
||||
* @return {@code true} if server supports list order option (1.21.2+), {@code false} if not
|
||||
*/
|
||||
default boolean supportsListOrder() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the server is safe from being affected by the packetevents bug with limitations, {@code false} if not.
|
||||
*
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package me.neznamy.tab.shared.util.function;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* An interface for Function which can throw an exception.
|
||||
* @param <A>
|
||||
@@ -12,24 +10,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
@FunctionalInterface
|
||||
public interface FunctionWithException<A, B> {
|
||||
|
||||
/**
|
||||
* Empty immutable instance.
|
||||
*/
|
||||
FunctionWithException<?, ?> EMPTY = a -> null;
|
||||
|
||||
/**
|
||||
* Get an empty function instance that always return null.
|
||||
*
|
||||
* @return a function with null result.
|
||||
* @param <A> Function argument
|
||||
* @param <B> Function return type
|
||||
*/
|
||||
@NotNull
|
||||
@SuppressWarnings("unchecked")
|
||||
static <A, B> FunctionWithException<A, B> empty() {
|
||||
return (FunctionWithException<A, B>) EMPTY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the function and returns the result
|
||||
*
|
||||
@@ -40,23 +20,4 @@ public interface FunctionWithException<A, B> {
|
||||
* If thrown by function
|
||||
*/
|
||||
B apply(A a) throws Exception;
|
||||
|
||||
/**
|
||||
* Provide a fallback function if current function result into null value.
|
||||
*
|
||||
* @param fallback the fallback function.
|
||||
* @return a newly generated function with fallback provider.
|
||||
* @param <T> function argument.
|
||||
* @param <R> function return type.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
default <T extends A, R extends B> FunctionWithException<T, R> fallback(FunctionWithException<T, R> fallback) {
|
||||
if (this == EMPTY) {
|
||||
return fallback;
|
||||
}
|
||||
return a -> {
|
||||
final B b = apply(a);
|
||||
return b != null ? (R) b : fallback.apply(a);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -131,6 +131,11 @@ public class SpongePlatform implements BackendPlatform {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsListOrder() {
|
||||
return false; // Maybe add it in the future when LTS bumps
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getTPS() {
|
||||
return Sponge.server().ticksPerSecond();
|
||||
|
||||
@@ -22,16 +22,20 @@ public class SpongeScoreboard extends SafeScoreboard<SpongeTabPlayer> {
|
||||
private static final org.spongepowered.api.scoreboard.CollisionRule[] collisionRules = {
|
||||
CollisionRules.ALWAYS.get(),
|
||||
CollisionRules.NEVER.get(),
|
||||
CollisionRules.PUSH_OTHER_TEAMS.get(),
|
||||
CollisionRules.PUSH_OWN_TEAM.get()
|
||||
// Commenting these out to avoid 1.21.5+ error
|
||||
// org.spongepowered.api.registry.ValueNotFoundException: No value was found for key 'sponge:hide_for_own_team'!
|
||||
// They are not used by TAB anyway, so not a problem
|
||||
// Also literally no one uses sponge anymore anyway
|
||||
//CollisionRules.PUSH_OTHER_TEAMS.get(),
|
||||
//CollisionRules.PUSH_OWN_TEAM.get()
|
||||
};
|
||||
|
||||
/** Visibility array for fast access */
|
||||
private static final Visibility[] visibilities = {
|
||||
Visibilities.ALWAYS.get(),
|
||||
Visibilities.NEVER.get(),
|
||||
Visibilities.HIDE_FOR_OTHER_TEAMS.get(),
|
||||
Visibilities.HIDE_FOR_OWN_TEAM.get()
|
||||
//Visibilities.HIDE_FOR_OTHER_TEAMS.get(),
|
||||
//Visibilities.HIDE_FOR_OWN_TEAM.get()
|
||||
};
|
||||
|
||||
/** DisplaySlot array for fast access */
|
||||
|
||||
@@ -56,7 +56,7 @@ public class SpongeTabList extends TrackedTabList<SpongeTabPlayer> {
|
||||
|
||||
@Override
|
||||
public void updateListed(@NonNull UUID entry, boolean listed) {
|
||||
// TODO
|
||||
player.getPlayer().tabList().entry(entry).ifPresent(e -> e.setListed(listed));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -74,13 +74,14 @@ public class SpongeTabList extends TrackedTabList<SpongeTabPlayer> {
|
||||
GameProfile profile = GameProfile.of(entry.getUniqueId(), entry.getName());
|
||||
if (entry.getSkin() != null) profile = profile.withProperty(ProfileProperty.of(
|
||||
TEXTURES_PROPERTY, entry.getSkin().getValue(), entry.getSkin().getSignature()));
|
||||
//TODO listed, listOrder, showHat
|
||||
//TODO listOrder, showHat
|
||||
TabListEntry tabListEntry = TabListEntry.builder()
|
||||
.list(player.getPlayer().tabList())
|
||||
.profile(profile)
|
||||
.latency(entry.getLatency())
|
||||
.gameMode(gameModes[entry.getGameMode()])
|
||||
.displayName(entry.getDisplayName() == null ? null : entry.getDisplayName().toAdventure())
|
||||
.listed(entry.isListed())
|
||||
.build();
|
||||
player.getPlayer().tabList().addEntry(tabListEntry);
|
||||
}
|
||||
|
||||
@@ -84,10 +84,17 @@ public class VelocityPlatform extends ProxyPlatform {
|
||||
// Scoreboard API failed to enable due to an error
|
||||
}
|
||||
} else {
|
||||
logInfo(new TextComponent("As of version 5.0.0, TAB no longer uses TAB-Bridge to encode scoreboard packets on Velocity. " +
|
||||
"Instead, it uses a custom made plugin that adds scoreboard API directly to Velocity, which offers better performance and reliability. " +
|
||||
"You can download the plugin from https://github.com/NEZNAMY/VelocityScoreboardAPI/releases/. " +
|
||||
"Until then, the following features will not work: scoreboard-teams, belowname-objective, playerlist-objective, scoreboard", TextColor.RED));
|
||||
logInfo(new TextComponent("==============================================================================", TextColor.RED));
|
||||
logInfo(new TextComponent("Velocity does not have any sort of scoreboard API.", TextColor.RED));
|
||||
logInfo(new TextComponent("As a result, many features cannot be implemented using the standard Velocity API.", TextColor.RED));
|
||||
logInfo(new TextComponent("In order to enhance your experience, please consider installing VelocityScoreboardAPI " +
|
||||
"(https://github.com/NEZNAMY/VelocityScoreboardAPI/releases/) plugin.", TextColor.RED));
|
||||
logInfo(new TextComponent("Until then, the following features will not work:", TextColor.RED));
|
||||
logInfo(new TextComponent("- scoreboard-teams", TextColor.RED));
|
||||
logInfo(new TextComponent("- belowname-objective", TextColor.RED));
|
||||
logInfo(new TextComponent("- playerlist-objective", TextColor.RED));
|
||||
logInfo(new TextComponent("- scoreboard", TextColor.RED));
|
||||
logInfo(new TextComponent("==============================================================================", TextColor.RED));
|
||||
}
|
||||
if (plugin.getServer().getPluginManager().isLoaded("premiumvanish")) {
|
||||
new VelocityPremiumVanishHook().register();
|
||||
|
||||
Reference in new issue
Block a user