mirror of
https://github.com/NEZNAMY/TAB.git
synced 2026-11-13 12:42:06 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9a7a105e7b | ||
|
|
f54d024d97 | ||
|
|
94338bd53f | ||
|
|
1a9ecc0313 | ||
|
|
4baeb7b945 | ||
|
|
baee479fb5 | ||
|
|
5ad4b2e9c4 | ||
|
|
26657cddfc | ||
|
|
947a922f8c | ||
|
|
a2be76184e | ||
|
|
8ddb733dc3 | ||
|
|
94e016129b | ||
|
|
5e653ded5d | ||
|
|
1bf8097c3f | ||
|
|
3d2f11ffd2 | ||
|
|
5e77a22d7a | ||
|
|
1dffcb1dc3 | ||
|
|
edc18cbafb | ||
|
|
2f23194432 | ||
|
|
20709472be | ||
|
|
7a8c6a0cec | ||
|
|
88558e40a7 | ||
|
|
79386b2b6b | ||
|
|
3aad8d3cb5 | ||
|
|
272a6f37ad | ||
|
|
e10081025d | ||
|
|
e03a6d8f11 | ||
|
|
98e7dc0321 | ||
|
|
74438c5d74 | ||
|
|
0c4e548565 | ||
|
|
cc70e01e96 | ||
|
|
7c635748af | ||
|
|
0c874ad56d | ||
|
|
2fb7f80b71 | ||
|
|
3f7c3414ce | ||
|
|
97165db44d | ||
|
|
82cdf04cf0 | ||
|
|
171d899609 | ||
|
|
6432278d5d | ||
|
|
ccaff12451 | ||
|
|
11347c080b | ||
|
|
553676c3f9 | ||
|
|
40b70e7418 | ||
|
|
0ea75019ae | ||
|
|
dbc092df77 | ||
|
|
68049f0dca | ||
|
|
9db5dfc175 | ||
|
|
039a316b3b | ||
|
|
f4b529f1ce | ||
|
|
9c6d606103 | ||
|
|
6cdc06aae7 | ||
|
|
2684654e7b | ||
|
|
25bcc33204 | ||
|
|
e5b3f6215b | ||
|
|
9306eadd90 | ||
|
|
a27fbb5b8b | ||
|
|
cd4c82b0b8 | ||
|
|
aa6179ee9e | ||
|
|
6594b8c2dc | ||
|
|
d4c2cdf003 | ||
|
|
2b529c37f5 | ||
|
|
8599cd925b | ||
|
|
89f37b4b9e | ||
|
|
f3136e85ee | ||
|
|
845743073c | ||
|
|
b2c7bacaf9 | ||
|
|
ed1673f032 | ||
|
|
bac9d443ea | ||
|
|
90e3868c08 | ||
|
|
c428572e01 | ||
|
|
884b5755ec | ||
|
|
32d7366795 | ||
|
|
21bf4a5450 | ||
|
|
8042b02cf5 | ||
|
|
ae7cdd3982 | ||
|
|
9ba945ad76 | ||
|
|
9cd04c3660 | ||
|
|
444bc19781 | ||
|
|
eb08c4ba04 | ||
|
|
5846e24a29 | ||
|
|
9c2c09e433 | ||
|
|
3c4329697b | ||
|
|
af9951d993 | ||
|
|
630f6df2f5 | ||
|
|
fcf07b8e7b | ||
|
|
4824c2f626 | ||
|
|
2b6b2e1b63 | ||
|
|
6926c1e57f | ||
|
|
6a00a7f1ca | ||
|
|
288c3d4c87 | ||
|
|
ac497bcc41 | ||
|
|
7b8d0d6845 | ||
|
|
a9a4589fae | ||
|
|
b8f972a774 | ||
|
|
305e388478 | ||
|
|
97e7848a78 | ||
|
|
d33058a924 | ||
|
|
eda3cc1f17 | ||
|
|
47043ad4ad | ||
|
|
acf20088cc | ||
|
|
374cb2766c | ||
|
|
31685b9ba5 | ||
|
|
722ff4ce52 | ||
|
|
161b375043 | ||
|
|
2c14191cde | ||
|
|
486546918f | ||
|
|
23d08e58a4 | ||
|
|
4c4c34ecaa | ||
|
|
bd3f2fd70a | ||
|
|
b80e42a635 | ||
|
|
9446a034d0 | ||
|
|
da0c6ab3fd | ||
|
|
c1adb27ee5 | ||
|
|
980d3027e3 | ||
|
|
53ba533f9b | ||
|
|
e40827da65 | ||
|
|
b9848b6a96 | ||
|
|
147593b11a | ||
|
|
21652f928b | ||
|
|
5b0352aff0 | ||
|
|
b2da2fa096 | ||
|
|
0cbb01a2a8 | ||
|
|
179840968d | ||
|
|
3b9c1649a1 | ||
|
|
5750c7dbe1 | ||
|
|
7ceca359be | ||
|
|
0f8152a6ed | ||
|
|
b3258bb020 | ||
|
|
4b2e705cbc | ||
|
|
31e41382f8 | ||
|
|
ecda7192dc | ||
|
|
9a48562b9f | ||
|
|
c181b58bc1 | ||
|
|
2624afa2ed | ||
|
|
3690af1e35 | ||
|
|
98966d3b38 | ||
|
|
41fdd16ce1 | ||
|
|
1bc94859c0 | ||
|
|
60f6f36437 | ||
|
|
82267ba16a | ||
|
|
14260deef8 | ||
|
|
8ba7342ccf | ||
|
|
f6b935d78e | ||
|
|
8cf3ae2091 | ||
|
|
e02b997521 | ||
|
|
229cef13c9 | ||
|
|
f503d6f896 | ||
|
|
d851166bb7 | ||
|
|
638a861350 | ||
|
|
20d7e4cbb0 | ||
|
|
36ccedd7c6 | ||
|
|
31854ba7a6 | ||
|
|
2639f07f5c | ||
|
|
b6e13f557f | ||
|
|
6333d90059 | ||
|
|
fea5d0ec56 | ||
|
|
c77f02d1fd | ||
|
|
c498965cae | ||
|
|
cdaa77071d | ||
|
|
6a72678c8d | ||
|
|
bb67fc622f | ||
|
|
5b50c02d93 | ||
|
|
ffec7e3266 | ||
|
|
039c1e7027 | ||
|
|
b27a21b3b8 | ||
|
|
2bcb5f617e | ||
|
|
7bf5294f9f | ||
|
|
c2fd1940f0 | ||
|
|
2d095ce6db | ||
|
|
e88bc36fca | ||
|
|
5613ea4f77 | ||
|
|
9c41599d60 | ||
|
|
5f8dd869e0 | ||
|
|
fb17df0b7e | ||
|
|
900ae83028 | ||
|
|
2c09db25b7 | ||
|
|
004e53fa29 | ||
|
|
e285b143d5 | ||
|
|
f78eb0ffed | ||
|
|
4d761e1d6e | ||
|
|
4a8c975319 | ||
|
|
fe56b7ed2d | ||
|
|
5a74654807 | ||
|
|
533ce4a529 | ||
|
|
4ea3780114 | ||
|
|
0d229ee26c | ||
|
|
29079ecad5 | ||
|
|
ea88401a58 | ||
|
|
298cef4d1f | ||
|
|
a51e9495de | ||
|
|
eead8ca1e2 | ||
|
|
a30712bc38 | ||
|
|
07b443fb21 | ||
|
|
61d927305c | ||
|
|
8f21c2f27d | ||
|
|
9fcf76e0c4 | ||
|
|
773afe2fb5 | ||
|
|
83ce5bd476 | ||
|
|
75a341c240 | ||
|
|
921a793b5c | ||
|
|
c1b92868cd | ||
|
|
94d19d728d | ||
|
|
8ef518f7e2 | ||
|
|
79fd1148a9 | ||
|
|
313ba8d765 | ||
|
|
c12c422357 | ||
|
|
b14c97d18a | ||
|
|
2fe345cb65 | ||
|
|
96ff81370c | ||
|
|
c4a1f41673 | ||
|
|
ca4c8ccb20 | ||
|
|
7471006f8a | ||
|
|
896c709824 | ||
|
|
473a37cb6a | ||
|
|
9e84d96051 | ||
|
|
019466d84d | ||
|
|
c222061529 | ||
|
|
acdd99404c | ||
|
|
799381bff3 | ||
|
|
b3654977ca | ||
|
|
b67d1928b5 | ||
|
|
052748d2b9 | ||
|
|
e265187ff8 | ||
|
|
c622a95550 | ||
|
|
94d71a245b | ||
|
|
a9403269be | ||
|
|
dfe6768eb5 | ||
|
|
d88bf65806 | ||
|
|
30929062d6 | ||
|
|
747e3d692d | ||
|
|
1d3ecbb7ed | ||
|
|
39b88b0dd5 | ||
|
|
d13d3eb055 | ||
|
|
f8f72b9074 | ||
|
|
a9d0b0a0ae | ||
|
|
37bd624537 | ||
|
|
e19f4ed771 | ||
|
|
c828fa8d52 | ||
|
|
9e080a5f5c | ||
|
|
7d7d4c05ab | ||
|
|
d4c7044708 | ||
|
|
52dd8c7c8b | ||
|
|
398ac8b6cf | ||
|
|
911792b214 | ||
|
|
8e54989502 | ||
|
|
4f16579063 | ||
|
|
e1f1698413 | ||
|
|
5eb999b98a | ||
|
|
5e7af835d8 | ||
|
|
f19f2c5a20 | ||
|
|
ff2aceb781 |
No files matched your search
@@ -37,3 +37,8 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
|
||||
run: ./gradlew clean build
|
||||
- name: Upload a Build Artifact
|
||||
uses: actions/upload-artifact@v2.3.1
|
||||
with:
|
||||
name: Jar
|
||||
path: jar/build/libs/TAB-**.jar
|
||||
@@ -35,6 +35,7 @@ hs_err_pid*
|
||||
# other
|
||||
.gitattributes
|
||||
*.iml
|
||||
run/
|
||||
|
||||
# Gradle
|
||||
.gradle/
|
||||
|
||||
@@ -1,18 +1,41 @@
|
||||
# About
|
||||
This is where you can download the plugin for free without needing to buy me a coffee or just grab some code inspiration for your plugin. God bless opensource.
|
||||
|
||||
# Compiling from source
|
||||
TAB aims to be a superior all-in-one minecraft plugin for displaying information that outperforms all
|
||||
similar plugins in terms of features, performance, compatibility and support.
|
||||
More information can be found at [Why TAB?](https://github.com/NEZNAMY/TAB/wiki/Why-TAB%3F) wiki page.
|
||||
|
||||
# Distribution
|
||||
As of TAB 3.0.0, released with MC 1.18 (November 30th, 2021), there is no free / premium
|
||||
version anymore. Only one version of the plugin exists now, which contains all implemented features
|
||||
and is available to everyone for free. However, official support on discord is only provided to
|
||||
those who have purchased the plugin.
|
||||
|
||||
# Compiling
|
||||
Compilation requires JDK 8 and up.
|
||||
To compile the plugin, run `./gradlew build` from the terminal.
|
||||
Once the plugin compiles, you can grab the jar from `jar/build/libs/` folder.
|
||||
Once the plugin compiles, grab the jar from `/jar/build/libs/` folder.
|
||||
|
||||
# Links
|
||||
See [releases](https://github.com/NEZNAMY/TAB/releases) for precompiled jar.
|
||||
|
||||
Has the plugin helped you in any way and you wish to support the development?
|
||||
You can purchase the plugin on [MC-Market](https://www.mc-market.org/resources/20631/), [Polymart](https://polymart.org/resource/484) or just [send a donation](https://paypal.me/neznamy1).
|
||||
The precompiled JAR can be downloaded for free from
|
||||
[github releases](https://github.com/NEZNAMY/TAB/releases)
|
||||
and [MC-Market](https://www.mc-market.org/resources/20631/).
|
||||
|
||||
Supporters have access to high-quality [discord support](https://discord.gg/EaSvdk6).
|
||||
|
||||
Want to know more about the plugin's functions? Check out the [wiki](https://github.com/NEZNAMY/TAB/wiki).
|
||||
If you want to show your appreciation for my work, you can purchase the plugin on
|
||||
[MC-Market](https://www.mc-market.org/resources/14009/),
|
||||
[Polymart](https://polymart.org/resource/484) or just [send a donation](https://paypal.me/neznamy1).
|
||||
|
||||
Support is provided to buyers on [discord](https://discord.gg/EaSvdk6).
|
||||
|
||||
A detailed explanation of all the plugin's functions can be found on the
|
||||
[wiki](https://github.com/NEZNAMY/TAB/wiki).
|
||||
|
||||
# Issues
|
||||
The [Issues](https://github.com/NEZNAMY/TAB/issues) section is **only** available for **bug reports**
|
||||
or other issues which are not directly a bug (performance issues, errors, etc.).
|
||||
Support is provided on discord and feature requests are currently not accepted due to high demand and
|
||||
being busy with bug reports, which take priority over new features.
|
||||
We are not looking to add any new major features anymore.
|
||||
We would rather spend time improving existing features instead.
|
||||
|
||||
When opening a bug report, make sure you provide all necessary information to reproduce the bug,
|
||||
otherwise we will not able to fix it. Saying "it only occurs randomly" or "I don't know how to
|
||||
reproduce it" has no value and cannot be converted into actual code.
|
||||
@@ -1,7 +1,3 @@
|
||||
plugins {
|
||||
id("tab.publishing")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnlyApi(libs.netty)
|
||||
api(libs.jsonSimple) {
|
||||
|
||||
@@ -6,77 +6,77 @@ public interface ArmorStand {
|
||||
* Returns true if offset is static, false if not
|
||||
* @return true if static, false if dynamic
|
||||
*/
|
||||
public boolean hasStaticOffset();
|
||||
boolean hasStaticOffset();
|
||||
|
||||
/**
|
||||
* Changes offset of the armor stand
|
||||
* @param offset - new offset
|
||||
*/
|
||||
public void setOffset(double offset);
|
||||
|
||||
void setOffset(double offset);
|
||||
|
||||
/**
|
||||
* Returns offset of the armor stand
|
||||
* @return offset from base
|
||||
*/
|
||||
public double getOffset();
|
||||
double getOffset();
|
||||
|
||||
/**
|
||||
* Returns property for armor stand's name
|
||||
* @return property for armor stand's name
|
||||
*/
|
||||
public Property getProperty();
|
||||
Property getProperty();
|
||||
|
||||
/**
|
||||
* Teleports armor stand to owner's current location for everyone in range
|
||||
*/
|
||||
public void teleport();
|
||||
void teleport();
|
||||
|
||||
/**
|
||||
* Teleports armor stand to owner's current location for specified player
|
||||
* @param viewer - player to send packet to
|
||||
*/
|
||||
public void teleport(TabPlayer viewer);
|
||||
void teleport(TabPlayer viewer);
|
||||
|
||||
/**
|
||||
* Changes sneaking flag and sends packets to everyone in range
|
||||
* @param sneaking
|
||||
* @param sneaking
|
||||
* new sneaking status
|
||||
*/
|
||||
public void sneak(boolean sneaking);
|
||||
void sneak(boolean sneaking);
|
||||
|
||||
/**
|
||||
* Despawns armor stand for everyone
|
||||
* DeSpawns armor stand for everyone
|
||||
*/
|
||||
public void destroy();
|
||||
void destroy();
|
||||
|
||||
/**
|
||||
* Despawns armor stand for specified player
|
||||
* DeSpawns armor stand for specified player
|
||||
* @param viewer - player to send packet to
|
||||
*/
|
||||
public void destroy(TabPlayer viewer);
|
||||
void destroy(TabPlayer viewer);
|
||||
|
||||
/**
|
||||
* Updates armor stand's name if needed
|
||||
*/
|
||||
public void refresh();
|
||||
void refresh();
|
||||
|
||||
/**
|
||||
* Updates visibility if needed
|
||||
* @param force - if refresh should be forced
|
||||
*/
|
||||
public void updateVisibility(boolean force);
|
||||
void updateVisibility(boolean force);
|
||||
|
||||
/**
|
||||
* Returns entity ID of this armor stand
|
||||
* @return entity ID of this armor stand
|
||||
*/
|
||||
public int getEntityId();
|
||||
int getEntityId();
|
||||
|
||||
/**
|
||||
* Spawns armor stand for specified player
|
||||
* @param viewer - player to spawn for
|
||||
* @param addToRegistered - if player should be added to players in range
|
||||
*/
|
||||
public void spawn(TabPlayer viewer);
|
||||
void spawn(TabPlayer viewer);
|
||||
|
||||
public void respawn(TabPlayer viewer);
|
||||
void respawn(TabPlayer viewer);
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package me.neznamy.tab.api;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -15,7 +14,7 @@ public class ArmorStandManager {
|
||||
private final Map<String, ArmorStand> armorStands = new LinkedHashMap<>();
|
||||
|
||||
//players in entity tracking range
|
||||
private final List<TabPlayer> nearbyPlayers = Collections.synchronizedList(new ArrayList<>());
|
||||
private final List<TabPlayer> nearbyPlayers = new ArrayList<>();
|
||||
|
||||
//array to iterate over to avoid concurrent modification and slightly boost performance & memory
|
||||
private ArmorStand[] armorStandArray = new ArmorStand[0];
|
||||
@@ -27,7 +26,7 @@ public class ArmorStandManager {
|
||||
* @param name - key name of the armor stand
|
||||
* @param as - armor stand to add
|
||||
*/
|
||||
public synchronized void addArmorStand(String name, ArmorStand as) {
|
||||
public void addArmorStand(String name, ArmorStand as) {
|
||||
armorStands.put(name, as);
|
||||
armorStandArray = armorStands.values().toArray(new ArmorStand[0]);
|
||||
for (TabPlayer p : nearbyPlayerArray) as.spawn(p);
|
||||
@@ -57,10 +56,8 @@ public class ArmorStandManager {
|
||||
* @param viewer - player to spawn armor stands for
|
||||
*/
|
||||
public void spawn(TabPlayer viewer) {
|
||||
synchronized (nearbyPlayers) {
|
||||
nearbyPlayers.add(viewer);
|
||||
nearbyPlayerArray = nearbyPlayers.toArray(new TabPlayer[0]);
|
||||
}
|
||||
nearbyPlayers.add(viewer);
|
||||
nearbyPlayerArray = nearbyPlayers.toArray(new TabPlayer[0]);
|
||||
if (viewer.getVersion().getMinorVersion() < 8) return;
|
||||
for (ArmorStand a : armorStandArray) a.spawn(viewer);
|
||||
}
|
||||
@@ -108,10 +105,7 @@ public class ArmorStandManager {
|
||||
* @param viewer - player to remove
|
||||
*/
|
||||
public void unregisterPlayer(TabPlayer viewer) {
|
||||
synchronized (nearbyPlayers) {
|
||||
nearbyPlayers.remove(viewer);
|
||||
nearbyPlayerArray = nearbyPlayers.toArray(new TabPlayer[0]);
|
||||
}
|
||||
if (nearbyPlayers.remove(viewer)) nearbyPlayerArray = nearbyPlayers.toArray(new TabPlayer[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -119,10 +113,8 @@ public class ArmorStandManager {
|
||||
*/
|
||||
public void destroy() {
|
||||
for (ArmorStand a : armorStandArray) a.destroy();
|
||||
synchronized (nearbyPlayers) {
|
||||
nearbyPlayers.clear();
|
||||
nearbyPlayerArray = new TabPlayer[0];
|
||||
}
|
||||
nearbyPlayers.clear();
|
||||
nearbyPlayerArray = new TabPlayer[0];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,19 +3,19 @@ package me.neznamy.tab.api;
|
||||
public interface FeatureManager {
|
||||
|
||||
/**
|
||||
* Registers a feature, which will start recieiving events
|
||||
* Registers a feature, which will start receiving events
|
||||
*
|
||||
* @param featureName - name of feature
|
||||
* @param featureHandler - the handler
|
||||
* @param name - name of feature
|
||||
* @param feature - the handler
|
||||
*/
|
||||
public void registerFeature(String name, TabFeature feature);
|
||||
void registerFeature(String name, TabFeature feature);
|
||||
|
||||
/**
|
||||
* Unregisters feature making it no longer receive events. This does not run unload method nor cancel
|
||||
* tasks created by the feature
|
||||
* @param name - feature name defined in registerFeature
|
||||
*/
|
||||
public void unregisterFeature(String name);
|
||||
void unregisterFeature(String name);
|
||||
|
||||
/**
|
||||
* Returns whether a feature with said name is registered or not
|
||||
@@ -23,13 +23,13 @@ public interface FeatureManager {
|
||||
* @param name - name of feature defined in registerFeature method
|
||||
* @return true if feature exists, false if not
|
||||
*/
|
||||
public boolean isFeatureEnabled(String name);
|
||||
boolean isFeatureEnabled(String name);
|
||||
|
||||
/**
|
||||
* Returns feature handler by it's name
|
||||
* Returns feature handler by its name
|
||||
*
|
||||
* @param name - name of feature defined in registerFeature method
|
||||
* @return the feature or null if feature does not exist
|
||||
*/
|
||||
public TabFeature getFeature(String name);
|
||||
TabFeature getFeature(String name);
|
||||
}
|
||||
@@ -2,15 +2,15 @@ package me.neznamy.tab.api;
|
||||
|
||||
public interface HeaderFooterManager {
|
||||
|
||||
public void setHeader(TabPlayer player, String header);
|
||||
void setHeader(TabPlayer player, String header);
|
||||
|
||||
public void setFooter(TabPlayer player, String footer);
|
||||
void setFooter(TabPlayer player, String footer);
|
||||
|
||||
public void setHeaderAndFooter(TabPlayer player, String header, String footer);
|
||||
void setHeaderAndFooter(TabPlayer player, String header, String footer);
|
||||
|
||||
public void resetHeader(TabPlayer player);
|
||||
void resetHeader(TabPlayer player);
|
||||
|
||||
public void resetFooter(TabPlayer player);
|
||||
void resetFooter(TabPlayer player);
|
||||
|
||||
public void resetHeaderAndFooter(TabPlayer player);
|
||||
void resetHeaderAndFooter(TabPlayer player);
|
||||
}
|
||||
@@ -4,57 +4,57 @@ public interface Property {
|
||||
|
||||
/**
|
||||
* Changes raw value to new one
|
||||
* @param newValue - new value to be used
|
||||
* @param rawValue - new value to be used
|
||||
*/
|
||||
public void changeRawValue(String rawValue);
|
||||
void changeRawValue(String rawValue);
|
||||
|
||||
/**
|
||||
* Returns original raw value ignoring API calls
|
||||
* @return original raw value
|
||||
*/
|
||||
public String getOriginalRawValue();
|
||||
String getOriginalRawValue();
|
||||
|
||||
/**
|
||||
* Temporarily overrides current raw value with an API call
|
||||
* @param temporaryValue - temporary value to be assigned
|
||||
*/
|
||||
public void setTemporaryValue(String temporaryValue);
|
||||
void setTemporaryValue(String temporaryValue);
|
||||
|
||||
/**
|
||||
* Returns current temporary value
|
||||
* @return temporary value or null if not set
|
||||
*/
|
||||
public String getTemporaryValue();
|
||||
String getTemporaryValue();
|
||||
|
||||
/**
|
||||
* Returns temporary value (via API) if present, raw value otherwise
|
||||
* @return current raw value
|
||||
*/
|
||||
public String getCurrentRawValue();
|
||||
String getCurrentRawValue();
|
||||
|
||||
/**
|
||||
* Returns last known value
|
||||
* @return last known value
|
||||
*/
|
||||
public String get();
|
||||
String get();
|
||||
|
||||
/**
|
||||
* Replaces all placeholders in current raw value, colorizes it, removes remove-strings and returns whether value changed or not
|
||||
* @return if updating changed value or not
|
||||
*/
|
||||
public boolean update();
|
||||
boolean update();
|
||||
|
||||
/**
|
||||
* Replaces all placeholders in current raw value, colorizes it, removes remove-strings and returns it.
|
||||
* Equal to calling update() and then get().
|
||||
* @return updated value
|
||||
*/
|
||||
public String updateAndGet();
|
||||
String updateAndGet();
|
||||
|
||||
/**
|
||||
* Returns value for defined viewer by applying relational placeholders to last known value
|
||||
* @param viewer - the viewer
|
||||
* @return format for the viewer
|
||||
*/
|
||||
public String getFormat(TabPlayer viewer);
|
||||
String getFormat(TabPlayer viewer);
|
||||
}
|
||||
@@ -2,9 +2,9 @@ package me.neznamy.tab.api;
|
||||
|
||||
public interface PropertyConfiguration {
|
||||
|
||||
public void setProperty(String name, String property, String server, String world, String value);
|
||||
void setProperty(String name, String property, String server, String world, String value);
|
||||
|
||||
public String[] getProperty(String name, String property, String server, String world);
|
||||
String[] getProperty(String name, String property, String server, String world);
|
||||
|
||||
public void remove(String name);
|
||||
void remove(String name);
|
||||
}
|
||||
@@ -5,8 +5,9 @@ package me.neznamy.tab.api;
|
||||
*/
|
||||
public enum ProtocolVersion {
|
||||
|
||||
UNKNOWN (999, "Unknown"),
|
||||
PROXY (999, "Proxy"),
|
||||
UNKNOWN ("Unknown"),
|
||||
PROXY ("Proxy"),
|
||||
V1_18_1 (757),
|
||||
V1_18 (757),
|
||||
V1_17_1 (756),
|
||||
V1_17 (755),
|
||||
@@ -63,7 +64,7 @@ public enum ProtocolVersion {
|
||||
private final int networkId;
|
||||
|
||||
//minor version, such as 16
|
||||
private final int minorVersion;
|
||||
private int minorVersion;
|
||||
|
||||
//friendly name displayed in %player-version% placeholder
|
||||
private final String friendlyName;
|
||||
@@ -72,25 +73,24 @@ public enum ProtocolVersion {
|
||||
* Constructs new instance with given network id
|
||||
* @param networkId - network id of this version
|
||||
*/
|
||||
private ProtocolVersion(int networkId){
|
||||
ProtocolVersion(int networkId){
|
||||
this.networkId = networkId;
|
||||
this.minorVersion = Integer.parseInt(toString().split("_")[1]);
|
||||
this.friendlyName = toString().substring(1).replace("_", ".");
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance with given network id and friendly name
|
||||
* @param networkId - network id of this version
|
||||
* Constructs new instance with given friendly name
|
||||
* @param friendlyName - friendly name to display
|
||||
*/
|
||||
private ProtocolVersion(int networkId, String friendlyName){
|
||||
this.networkId = networkId;
|
||||
this.minorVersion = 17;
|
||||
ProtocolVersion(String friendlyName){
|
||||
this.networkId = 999;
|
||||
this.minorVersion = 18;
|
||||
this.friendlyName = friendlyName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the vesion's network id
|
||||
* Returns the version's network id
|
||||
* @return version's network id
|
||||
*/
|
||||
public int getNetworkId() {
|
||||
@@ -99,7 +99,7 @@ public enum ProtocolVersion {
|
||||
|
||||
/**
|
||||
* Returns user-friendly name of the version (such as 1.16.2 instead of V1_16_2)
|
||||
* @return
|
||||
* @return user-friendly name of the version
|
||||
*/
|
||||
public String getFriendlyName() {
|
||||
return friendlyName;
|
||||
@@ -113,6 +113,17 @@ public enum ProtocolVersion {
|
||||
return minorVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides minor version of the version instance. This is used internally to
|
||||
* set minor version of UNKNOWN value to value from package to fix compatibility
|
||||
* with server forks that set bukkit version field value to "Unknown".
|
||||
* @param minorVersion
|
||||
* minor version to change value to
|
||||
*/
|
||||
public void setMinorVersion(int minorVersion) {
|
||||
this.minorVersion = minorVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns enum constant of entered version or UNKNOWN if unknown version
|
||||
* @param friendlyName - friendly name of the version
|
||||
|
||||
@@ -4,6 +4,7 @@ import java.util.UUID;
|
||||
|
||||
import me.neznamy.tab.api.bossbar.BossBarManager;
|
||||
import me.neznamy.tab.api.config.ConfigurationFile;
|
||||
import me.neznamy.tab.api.event.EventBus;
|
||||
import me.neznamy.tab.api.placeholder.PlaceholderManager;
|
||||
import me.neznamy.tab.api.scoreboard.ScoreboardManager;
|
||||
import me.neznamy.tab.api.task.ThreadManager;
|
||||
@@ -45,8 +46,8 @@ public abstract class TabAPI {
|
||||
public abstract TabPlayer[] getOnlinePlayers();
|
||||
|
||||
/**
|
||||
* Return bossbar manager instance if the feature is enabled. Returns null otherwise.
|
||||
* @return bossbar manager
|
||||
* Return BossBar manager instance if the feature is enabled. Returns null otherwise.
|
||||
* @return BossBar manager
|
||||
*/
|
||||
public abstract BossBarManager getBossBarManager();
|
||||
|
||||
@@ -78,6 +79,13 @@ public abstract class TabAPI {
|
||||
|
||||
public abstract TablistFormatManager getTablistFormatManager();
|
||||
|
||||
/**
|
||||
* Gets the event bus for registering listeners for TAB events.
|
||||
*
|
||||
* @return the event bus
|
||||
*/
|
||||
public abstract EventBus getEventBus();
|
||||
|
||||
/**
|
||||
* Returns server version. On proxy installation returns PROXY.
|
||||
* @return server version
|
||||
@@ -104,4 +112,4 @@ public abstract class TabAPI {
|
||||
public abstract void debug(String message);
|
||||
|
||||
public abstract void logError(String message, Throwable t);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
package me.neznamy.tab.api;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
import me.neznamy.tab.api.protocol.PacketPlayOutPlayerInfo;
|
||||
import me.neznamy.tab.api.protocol.PacketPlayOutScoreboardDisplayObjective;
|
||||
@@ -16,7 +14,7 @@ public abstract class TabFeature {
|
||||
private final boolean serverWhitelistMode;
|
||||
protected final String[] disabledWorlds;
|
||||
private final boolean worldWhitelistMode;
|
||||
private final List<TabPlayer> disabledPlayers = new ArrayList<>();
|
||||
private final Set<TabPlayer> disabledPlayers = Collections.newSetFromMap(new WeakHashMap<>());
|
||||
private final List<String> methodOverrides = new ArrayList<>();
|
||||
|
||||
protected TabFeature(String featureName, String refreshDisplayName) {
|
||||
@@ -49,6 +47,8 @@ public abstract class TabFeature {
|
||||
methodOverrides.add("onQuit");
|
||||
if (getClass().getMethod("onWorldChange", TabPlayer.class, String.class, String.class).getDeclaringClass() != TabFeature.class)
|
||||
methodOverrides.add("onWorldChange");
|
||||
if (getClass().getMethod("onServerChange", TabPlayer.class, String.class, String.class).getDeclaringClass() != TabFeature.class)
|
||||
methodOverrides.add("onServerChange");
|
||||
if (getClass().getMethod("onDisplayObjective", TabPlayer.class, PacketPlayOutScoreboardDisplayObjective.class).getDeclaringClass() != TabFeature.class)
|
||||
methodOverrides.add("onDisplayObjective");
|
||||
if (getClass().getMethod("onLoginPacket", TabPlayer.class).getDeclaringClass() != TabFeature.class)
|
||||
@@ -105,7 +105,6 @@ public abstract class TabFeature {
|
||||
* @param disconnectedPlayer - player who disconnected
|
||||
*/
|
||||
public void onQuit(TabPlayer disconnectedPlayer) {
|
||||
disabledPlayers.remove(disconnectedPlayer);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -125,21 +124,20 @@ public abstract class TabFeature {
|
||||
* @param to - server player changed to
|
||||
*/
|
||||
public void onServerChange(TabPlayer changed, String from, String to) {
|
||||
onWorldChange(changed, null, null);
|
||||
//empty by default
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the packet send and returns true if packet should be cancelled
|
||||
* @param receiver - player receiving packet
|
||||
* @param packet - received packet
|
||||
* @return true if packet should be cancelled, false if not
|
||||
*/
|
||||
public boolean onDisplayObjective(TabPlayer receiver, PacketPlayOutScoreboardDisplayObjective packet) {
|
||||
return false;
|
||||
public void onDisplayObjective(TabPlayer receiver, PacketPlayOutScoreboardDisplayObjective packet) {
|
||||
//empty by default
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes login packet, only available on bungeecord
|
||||
* Processes login packet, only available on BungeeCord
|
||||
* @param packetReceiver - player receiving client reset packet
|
||||
*/
|
||||
public void onLoginPacket(TabPlayer packetReceiver) {
|
||||
@@ -158,7 +156,7 @@ public abstract class TabFeature {
|
||||
/**
|
||||
* Processes the packet send and possibly modifies it
|
||||
* @param receiver - player receiving packet
|
||||
* @param packet - received packet
|
||||
* @param info - received packet
|
||||
*/
|
||||
public void onPlayerInfo(TabPlayer receiver, PacketPlayOutPlayerInfo info) {
|
||||
//empty by default
|
||||
@@ -169,7 +167,8 @@ public abstract class TabFeature {
|
||||
* @param sender - packet sender
|
||||
* @param packet - packet received
|
||||
* @return true if false should be cancelled, false if not
|
||||
* @throws ReflectiveOperationException
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public boolean onPacketReceive(TabPlayer sender, Object packet) throws ReflectiveOperationException {
|
||||
return false;
|
||||
@@ -179,7 +178,8 @@ public abstract class TabFeature {
|
||||
* Processes raw packet sent to client
|
||||
* @param receiver - packet receiver
|
||||
* @param packet - the packet
|
||||
* @throws ReflectiveOperationException
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public void onPacketSend(TabPlayer receiver, Object packet) throws ReflectiveOperationException {
|
||||
//empty by default
|
||||
@@ -251,8 +251,8 @@ public abstract class TabFeature {
|
||||
disabledPlayers.add(p);
|
||||
}
|
||||
|
||||
public boolean removeDisabledPlayer(TabPlayer p) {
|
||||
return disabledPlayers.remove(p);
|
||||
public void removeDisabledPlayer(TabPlayer p) {
|
||||
disabledPlayers.remove(p);
|
||||
}
|
||||
|
||||
public String getRefreshDisplayName() {
|
||||
|
||||
@@ -14,63 +14,63 @@ public interface TabPlayer {
|
||||
/**
|
||||
* Refreshes all visuals on the player
|
||||
*/
|
||||
public void forceRefresh();
|
||||
void forceRefresh();
|
||||
|
||||
/**
|
||||
* Returns player's name
|
||||
* @return Player's name
|
||||
*/
|
||||
public String getName();
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Returns player's UUID
|
||||
* @return Player's UUID
|
||||
*/
|
||||
public UUID getUniqueId();
|
||||
UUID getUniqueId();
|
||||
|
||||
/**
|
||||
* Returns player's uuid used in tablist. This may only be different than real uuid if
|
||||
* Returns player's uuid used in TabList. This may only be different from real uuid if
|
||||
* TAB is installed on velocity with some specific velocity setup
|
||||
* @return player's uuid in tablist
|
||||
* @return player's uuid in TabList
|
||||
*/
|
||||
public UUID getTablistUUID();
|
||||
UUID getTablistUUID();
|
||||
|
||||
/**
|
||||
* Returns player's protocol version
|
||||
* @return player's protocol version
|
||||
*/
|
||||
public ProtocolVersion getVersion();
|
||||
ProtocolVersion getVersion();
|
||||
|
||||
/**
|
||||
* Returns platform-specific entity
|
||||
* @return an instance of bukkit/bungee player depending on platform
|
||||
*/
|
||||
public Object getPlayer();
|
||||
Object getPlayer();
|
||||
|
||||
/**
|
||||
* Returns player's current world name (on bungeecord this requires bridge installed)
|
||||
* @return name of world where player is currently in, null on bungeecord if bridge is not installed
|
||||
* Returns player's current world name (on BungeeCord this requires bridge installed)
|
||||
* @return name of world where player is currently in, null on BungeeCord if bridge is not installed
|
||||
*/
|
||||
public String getWorld();
|
||||
String getWorld();
|
||||
|
||||
/**
|
||||
* Returns player's current server name on bungeecord (on bukkit this returns null)
|
||||
* Returns player's current server name on BungeeCord (on bukkit this returns null)
|
||||
* @return name of server where player is currently in, null on bukkit
|
||||
*/
|
||||
public String getServer();
|
||||
String getServer();
|
||||
|
||||
/**
|
||||
* Performs platform-specific API call to check for permission and returns the result
|
||||
* @param permission - the permission to check for
|
||||
* @return - true if has, false if not
|
||||
* @return - true if player has permission, false if not
|
||||
*/
|
||||
public boolean hasPermission(String permission);
|
||||
boolean hasPermission(String permission);
|
||||
|
||||
/**
|
||||
* Sends the player a custom universal packet
|
||||
* @param packet - packet to send
|
||||
*/
|
||||
public void sendCustomPacket(TabPacket packet);
|
||||
void sendCustomPacket(TabPacket packet);
|
||||
|
||||
/**
|
||||
* Sends the player a custom universal packet and adds that packet into counter that
|
||||
@@ -78,7 +78,7 @@ public interface TabPlayer {
|
||||
* @param packet - packet to send
|
||||
* @param feature - feature to increment sent packet counter of
|
||||
*/
|
||||
public void sendCustomPacket(TabPacket packet, TabFeature feature);
|
||||
void sendCustomPacket(TabPacket packet, TabFeature feature);
|
||||
|
||||
/**
|
||||
* Sends the player a custom universal packet and adds that packet into counter that
|
||||
@@ -86,13 +86,13 @@ public interface TabPlayer {
|
||||
* @param packet - packet to send
|
||||
* @param feature - feature to increment sent packet counter of
|
||||
*/
|
||||
public void sendCustomPacket(TabPacket packet, String feature);
|
||||
void sendCustomPacket(TabPacket packet, String feature);
|
||||
|
||||
/**
|
||||
* Sends the player a platform-specific packet
|
||||
* @param packet - an instance of packet depending on platform
|
||||
*/
|
||||
public void sendPacket(Object packet);
|
||||
void sendPacket(Object packet);
|
||||
|
||||
/**
|
||||
* Sends the player a platform-specific packet and adds that packet into counter that
|
||||
@@ -100,7 +100,7 @@ public interface TabPlayer {
|
||||
* @param packet - an instance of packet depending on platform
|
||||
* @param feature - feature to increment sent packet counter of
|
||||
*/
|
||||
public void sendPacket(Object packet, TabFeature feature);
|
||||
void sendPacket(Object packet, TabFeature feature);
|
||||
|
||||
/**
|
||||
* Sends the player a platform-specific packet and adds that packet into counter that
|
||||
@@ -108,149 +108,156 @@ public interface TabPlayer {
|
||||
* @param packet - an instance of packet depending on platform
|
||||
* @param feature - feature to increment sent packet counter of
|
||||
*/
|
||||
public void sendPacket(Object packet, String feature);
|
||||
void sendPacket(Object packet, String feature);
|
||||
|
||||
/**
|
||||
* Returns player's property by name
|
||||
* @param name - name of property
|
||||
* @return the property or null if not found
|
||||
*/
|
||||
public Property getProperty(String name);
|
||||
Property getProperty(String name);
|
||||
|
||||
/**
|
||||
* Sends a message to the player
|
||||
* @param message - message to be sent
|
||||
* @param translateColors - whether colors should be translated or not
|
||||
*/
|
||||
public void sendMessage(String message, boolean translateColors);
|
||||
void sendMessage(String message, boolean translateColors);
|
||||
|
||||
/**
|
||||
* Sends specified component as a chat message
|
||||
* @param message - message to send
|
||||
*/
|
||||
public void sendMessage(IChatBaseComponent message);
|
||||
void sendMessage(IChatBaseComponent message);
|
||||
|
||||
/**
|
||||
* Returns player's primary permission group
|
||||
* @return player's group depending on configuration
|
||||
*/
|
||||
public String getGroup();
|
||||
String getGroup();
|
||||
|
||||
/**
|
||||
* Toggles armor stands preview mode for the player
|
||||
*/
|
||||
public void toggleNametagPreview();
|
||||
void toggleNametagPreview();
|
||||
|
||||
/**
|
||||
* Returns whether player is previewing nametag or not
|
||||
* Returns whether player is previewing NameTag or not
|
||||
* @return true if previewing, false if not
|
||||
*/
|
||||
public boolean isPreviewingNametag();
|
||||
boolean isPreviewingNametag();
|
||||
|
||||
/**
|
||||
* Returns player's channel or null if server is 1.7 or older
|
||||
* @return player's channel
|
||||
*/
|
||||
public Channel getChannel();
|
||||
Channel getChannel();
|
||||
|
||||
/**
|
||||
* Returns player's ping calculated by server
|
||||
* @return player's ping
|
||||
*/
|
||||
public int getPing();
|
||||
int getPing();
|
||||
|
||||
/**
|
||||
* Returns player's platform-specific skin data
|
||||
* @return player's skin
|
||||
*/
|
||||
public Object getSkin();
|
||||
Object getSkin();
|
||||
|
||||
/**
|
||||
* Returns true once the player is successfully loaded (onJoin method ran through all methods)
|
||||
* @return true if player is fully loaded, false otherwise
|
||||
*/
|
||||
public boolean isLoaded();
|
||||
boolean isLoaded();
|
||||
|
||||
/**
|
||||
* Sets property with specified name to new value. If property did no exist before, it is
|
||||
* created and true is returned. If it existed, it is overridden and true is returned. False is returned othewise.
|
||||
* Sets property with specified name to new value. If property did not exist before, it is
|
||||
* created and true is returned. If it existed, it is overridden and true is returned. False is returned otherwise.
|
||||
* @param feature - feature using this property to get placeholders registered
|
||||
* @param identifier - property name
|
||||
* @param rawValue - new raw value
|
||||
* @return true if value changed / did not exist, false if value did not change
|
||||
*/
|
||||
public boolean setProperty(TabFeature feature, String identifier, String rawValue);
|
||||
boolean setProperty(TabFeature feature, String identifier, String rawValue);
|
||||
|
||||
/**
|
||||
* Loads property from config using standard property loading algorithm
|
||||
* @param property - property name to load
|
||||
* @return true if value did not exist or changed, false otherwise
|
||||
*/
|
||||
public void loadPropertyFromConfig(TabFeature feature, String property);
|
||||
boolean loadPropertyFromConfig(TabFeature feature, String property);
|
||||
|
||||
/**
|
||||
* Loads property from config using standard property loading algorithm. If the property is
|
||||
* not set in config, sets it to ifNotSet value
|
||||
* @param property - property name to load
|
||||
* @param ifNotSet - value to use if property is not defined in config
|
||||
* @return true if value did not exist or changed, false otherwise
|
||||
*/
|
||||
public void loadPropertyFromConfig(TabFeature feature, String property, String ifNotSet);
|
||||
boolean loadPropertyFromConfig(TabFeature feature, String property, String ifNotSet);
|
||||
|
||||
/**
|
||||
* Returns name of player's scoreboard team or null if nametag feature is disabled
|
||||
* Returns name of player's scoreboard team or null if NameTag feature is disabled
|
||||
* @return name of player's team
|
||||
*/
|
||||
public String getTeamName();
|
||||
String getTeamName();
|
||||
|
||||
/**
|
||||
* Returns user-friendly explanation of team name
|
||||
* @return explanation behind team name
|
||||
*/
|
||||
public String getTeamNameNote();
|
||||
String getTeamNameNote();
|
||||
|
||||
/**
|
||||
* Returns true if player is disguised using iDisguide or LibsDisguises on bukkit, LibsDisguises
|
||||
* only on bungeecord via bukkit bridge
|
||||
* Returns true if player is disguised using LibsDisguises
|
||||
* @return true if player is disguised, false if not
|
||||
*/
|
||||
public boolean isDisguised();
|
||||
boolean isDisguised();
|
||||
|
||||
/**
|
||||
* Returns true if player has invisiblity potion, false if not. For bukkit, API is used, for bungeecord
|
||||
* Returns true if player has invisibility potion, false if not. For bukkit, API is used, for BungeeCord
|
||||
* bukkit bridge is used
|
||||
* @return true if has invisiblity potion, false if not
|
||||
* @return true if player has invisibility potion, false if not
|
||||
*/
|
||||
public boolean hasInvisibilityPotion();
|
||||
boolean hasInvisibilityPotion();
|
||||
|
||||
/**
|
||||
* Currently only PV hook on bungeecord for global playerlist function. Looking to expand this
|
||||
* Currently only PV hook on BungeeCord for global PlayerList function. Looking to expand this
|
||||
* in the future
|
||||
* @return true if vanished with PV on bungeecord
|
||||
* @return true if vanished with PV on BungeeCord
|
||||
*/
|
||||
public boolean isVanished();
|
||||
boolean isVanished();
|
||||
|
||||
/**
|
||||
* Returns true if player is online according to server
|
||||
* @return true if online, false if not
|
||||
*/
|
||||
public boolean isOnline();
|
||||
boolean isOnline();
|
||||
|
||||
/**
|
||||
* Returns player's armor stand manager if unlimited nametag mode is enabled, null if disabled
|
||||
* Returns player's armor stand manager if unlimited GameMode mode is enabled, null if disabled
|
||||
* @return player's armor stand manager
|
||||
*/
|
||||
public ArmorStandManager getArmorStandManager();
|
||||
ArmorStandManager getArmorStandManager();
|
||||
|
||||
/**
|
||||
* Sets player's armor stands manager to new instance
|
||||
* @param armorStandManager - new instance
|
||||
*/
|
||||
public void setArmorStandManager(ArmorStandManager armorStandManager);
|
||||
void setArmorStandManager(ArmorStandManager armorStandManager);
|
||||
|
||||
/**
|
||||
* Returns gamemode of the player (0 for survival, 1 creative, 2 adventure, 3 spectator)
|
||||
* @return gamemode of the player
|
||||
* Returns GameMode of the player (0 for survival, 1 creative, 2 adventure, 3 spectator)
|
||||
* @return GameMode of the player
|
||||
*/
|
||||
public int getGamemode();
|
||||
int getGamemode();
|
||||
|
||||
public boolean isBedrockPlayer();
|
||||
boolean isBedrockPlayer();
|
||||
|
||||
void setTemporaryGroup(String group);
|
||||
|
||||
boolean hasTemporaryGroup();
|
||||
|
||||
void resetTemporaryGroup();
|
||||
}
|
||||
@@ -2,28 +2,28 @@ package me.neznamy.tab.api;
|
||||
|
||||
public interface TablistFormatManager {
|
||||
|
||||
public void setPrefix(TabPlayer player, String prefix);
|
||||
void setPrefix(TabPlayer player, String prefix);
|
||||
|
||||
public void setName(TabPlayer player, String customname);
|
||||
void setName(TabPlayer player, String customName);
|
||||
|
||||
public void setSuffix(TabPlayer player, String suffix);
|
||||
void setSuffix(TabPlayer player, String suffix);
|
||||
|
||||
public void resetPrefix(TabPlayer player);
|
||||
void resetPrefix(TabPlayer player);
|
||||
|
||||
public void resetName(TabPlayer player);
|
||||
void resetName(TabPlayer player);
|
||||
|
||||
public void resetSuffix(TabPlayer player);
|
||||
void resetSuffix(TabPlayer player);
|
||||
|
||||
public String getCustomPrefix(TabPlayer player);
|
||||
String getCustomPrefix(TabPlayer player);
|
||||
|
||||
public String getCustomName(TabPlayer player);
|
||||
String getCustomName(TabPlayer player);
|
||||
|
||||
public String getCustomSuffix(TabPlayer player);
|
||||
String getCustomSuffix(TabPlayer player);
|
||||
|
||||
public String getOriginalPrefix(TabPlayer player);
|
||||
String getOriginalPrefix(TabPlayer player);
|
||||
|
||||
public String getOriginalName(TabPlayer player);
|
||||
String getOriginalName(TabPlayer player);
|
||||
|
||||
public String getOriginalSuffix(TabPlayer player);
|
||||
String getOriginalSuffix(TabPlayer player);
|
||||
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package me.neznamy.tab.api.bossbar;
|
||||
|
||||
/**
|
||||
* An enum representing all available bossbar colors.
|
||||
* An enum representing all available BossBar colors.
|
||||
* Calling ordinal() will return color's network ID.
|
||||
*/
|
||||
public enum BarColor {
|
||||
@@ -12,5 +12,5 @@ public enum BarColor {
|
||||
GREEN,
|
||||
YELLOW,
|
||||
PURPLE,
|
||||
WHITE;
|
||||
WHITE
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package me.neznamy.tab.api.bossbar;
|
||||
|
||||
/**
|
||||
* An enum representing all available bossbar styles.
|
||||
* An enum representing all available BossBar styles.
|
||||
* Calling ordinal() will return style's network ID.
|
||||
* Style names are equal to NMS names.
|
||||
*/
|
||||
@@ -14,7 +14,7 @@ public enum BarStyle {
|
||||
NOTCHED_20("SEGMENTED_20");
|
||||
|
||||
/** Style's name used in Bukkit API */
|
||||
private String bukkitName;
|
||||
private final String bukkitName;
|
||||
|
||||
/**
|
||||
* Initializes enum constant with given bukkit name
|
||||
@@ -22,7 +22,7 @@ public enum BarStyle {
|
||||
* @param bukkitName
|
||||
* Name of color to be returned in {@code getBukkitName()}
|
||||
*/
|
||||
private BarStyle(String bukkitName){
|
||||
BarStyle(String bukkitName){
|
||||
this.bukkitName = bukkitName;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,36 +6,36 @@ import java.util.UUID;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
|
||||
/**
|
||||
* An interface representing a bossbar line.
|
||||
* An interface representing a BossBar line.
|
||||
* <p>
|
||||
* For clients 1.8 and lower it uses wither, which only allows 1 bar
|
||||
* to be displayed at a time. Entity packets are not available on bungeecord,
|
||||
* to be displayed at a time. Entity packets are not available on BungeeCord,
|
||||
* where nothing will be displayed for these players.
|
||||
* <p>
|
||||
* For 1.9+ it uses the new bossbar feature, allowing configurable styles
|
||||
* For 1.9+ it uses the new BossBar feature, allowing configurable styles
|
||||
* and colors, as well as display several bars at once. Limit of maximum
|
||||
* displayed bossbars depends on client resolution and GUI scale, up to
|
||||
* 9 concurrent bossbars displayed at once.
|
||||
* displayed BossBars depends on client resolution and GUI scale, up to
|
||||
* 9 concurrent BossBars displayed at once.
|
||||
*/
|
||||
public interface BossBar {
|
||||
|
||||
/**
|
||||
* Returns name of this bossbar. If it was defined in config, returns
|
||||
* Returns name of this BossBar. If it was defined in config, returns
|
||||
* the name specified in config. If it was made using the API, returns
|
||||
* randomly generated ID given to this bossbar when creating.
|
||||
* @return name of bossbar
|
||||
* randomly generated ID given to this BossBar when creating.
|
||||
* @return name of BossBar
|
||||
*/
|
||||
public String getName();
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Returns randomly generated uuid of this bossbar used internally to match
|
||||
* the bossbar in client with packets or with Bukkit API bossbar instances.
|
||||
* @return uuid of this bossbar
|
||||
* Returns randomly generated uuid of this BossBar used internally to match
|
||||
* the BossBar in client with packets or with Bukkit API BossBar instances.
|
||||
* @return uuid of this BossBar
|
||||
*/
|
||||
public UUID getUniqueId();
|
||||
UUID getUniqueId();
|
||||
|
||||
/**
|
||||
* Changes bossbar title to specified string, supporting placeholders.
|
||||
* Changes BossBar title to specified string, supporting placeholders.
|
||||
* <p>
|
||||
* If title contains new placeholders not used before, they are registered using
|
||||
* standard registration logic and refreshed periodically. No need to call
|
||||
@@ -44,12 +44,12 @@ public interface BossBar {
|
||||
* If specified title is equal to the current one, nothing happens.
|
||||
*
|
||||
* @param title
|
||||
* New title to display in this bossbar
|
||||
* New title to display in this BossBar
|
||||
*/
|
||||
public void setTitle(String title);
|
||||
void setTitle(String title);
|
||||
|
||||
/**
|
||||
* Changes bossbar progress to specified string, supporting placeholders.
|
||||
* Changes BossBar progress to specified string, supporting placeholders.
|
||||
* The string must be a string version of a float value, or a placeholder that
|
||||
* outputs a float value with range 0-100.
|
||||
* <p>
|
||||
@@ -60,21 +60,21 @@ public interface BossBar {
|
||||
* If specified progress is equal to the current one, nothing happens.
|
||||
*
|
||||
* @param progress
|
||||
* New progress to use in this bossbar
|
||||
* New progress to use in this BossBar
|
||||
*/
|
||||
public void setProgress(String progress);
|
||||
void setProgress(String progress);
|
||||
|
||||
/**
|
||||
* Changes bossbar progress to specified value ranging from 0 to 100.
|
||||
* Changes BossBar progress to specified value ranging from 0 to 100.
|
||||
* <p>
|
||||
* If specified progress is equal to the current one, nothing happens.
|
||||
* @param progress
|
||||
* New progress to use in this bossbar
|
||||
* New progress to use in this BossBar
|
||||
*/
|
||||
public void setProgress(float progress);
|
||||
void setProgress(float progress);
|
||||
|
||||
/**
|
||||
* Changes bossbar color to specified string, supporting placeholders.
|
||||
* Changes BossBar color to specified string, supporting placeholders.
|
||||
* The string must be a string version of one of the supported values,
|
||||
* or a placeholder that outputs one of them.
|
||||
* <p>
|
||||
@@ -85,22 +85,22 @@ public interface BossBar {
|
||||
* If specified color is equal to the current one, nothing happens.
|
||||
*
|
||||
* @param color
|
||||
* New color to use in this bossbar
|
||||
* New color to use in this BossBar
|
||||
*/
|
||||
public void setColor(String color);
|
||||
void setColor(String color);
|
||||
|
||||
/**
|
||||
* Changes bossbar color to specified enum constant.
|
||||
* Changes BossBar color to specified enum constant.
|
||||
* <p>
|
||||
* If specified color is equal to the current one, nothing happens.
|
||||
*
|
||||
* @param color
|
||||
* New color to use in this bossbar
|
||||
* New color to use in this BossBar
|
||||
*/
|
||||
public void setColor(BarColor color);
|
||||
void setColor(BarColor color);
|
||||
|
||||
/**
|
||||
* Changes bossbar style to specified string, supporting placeholders.
|
||||
* Changes BossBar style to specified string, supporting placeholders.
|
||||
* The string must be a string version of one of the supported values,
|
||||
* or a placeholder that outputs one of them.
|
||||
* <p>
|
||||
@@ -111,75 +111,75 @@ public interface BossBar {
|
||||
* If specified style is equal to the current one, nothing happens.
|
||||
*
|
||||
* @param style
|
||||
* New style to use in this bossbar
|
||||
* New style to use in this BossBar
|
||||
*/
|
||||
public void setStyle(String style);
|
||||
void setStyle(String style);
|
||||
|
||||
/**
|
||||
* Changes bossbar style to specified enum constant.
|
||||
* Changes BossBar style to specified enum constant.
|
||||
* <p>
|
||||
* If specified style is equal to the current one, nothing happens.
|
||||
*
|
||||
* @param style
|
||||
* New style to use in this bossbar
|
||||
* New style to use in this BossBar
|
||||
*/
|
||||
public void setStyle(BarStyle style);
|
||||
void setStyle(BarStyle style);
|
||||
|
||||
/**
|
||||
* Returns current title of the bossbar in raw format. If it contains placeholders,
|
||||
* Returns current title of the BossBar in raw format. If it contains placeholders,
|
||||
* their raw identifiers are used in the result.
|
||||
* @return title of the bossbar
|
||||
* @return title of the BossBar
|
||||
*/
|
||||
public String getTitle();
|
||||
String getTitle();
|
||||
|
||||
/**
|
||||
* Returns progress of the bossbar as a string, which is either entered string
|
||||
* Returns progress of the BossBar as a string, which is either entered string
|
||||
* containing placeholders or entered number converted to string
|
||||
* @return entered progress as a string
|
||||
*/
|
||||
public String getProgress();
|
||||
String getProgress();
|
||||
|
||||
/**
|
||||
* Returns color of the bossbar as a string, which is either entered string
|
||||
* Returns color of the BossBar as a string, which is either entered string
|
||||
* containing placeholders or entered enum value converted to string
|
||||
* @return entered color as a string
|
||||
*/
|
||||
public String getColor();
|
||||
String getColor();
|
||||
|
||||
/**
|
||||
* Returns style of the bossbar as a string, which is either entered string
|
||||
* Returns style of the BossBar as a string, which is either entered string
|
||||
* containing placeholders or entered enum value converted to string
|
||||
* @return entered style as a string
|
||||
*/
|
||||
public String getStyle();
|
||||
String getStyle();
|
||||
|
||||
/**
|
||||
* Registers this bossbar to specified player.
|
||||
* Registers this BossBar to specified player.
|
||||
* <p>
|
||||
* If the player already sees this bossbar, nothing happens.
|
||||
* If the player already sees this BossBar, nothing happens.
|
||||
*
|
||||
* @param player
|
||||
* Player to register this bossbar to
|
||||
* Player to register this BossBar to
|
||||
*/
|
||||
public void addPlayer(TabPlayer player);
|
||||
void addPlayer(TabPlayer player);
|
||||
|
||||
/**
|
||||
* Unregisters this bossbar from specified player.
|
||||
* Unregisters this BossBar from specified player.
|
||||
* <p>
|
||||
* If the player does not see this bossbar, nothing happens.
|
||||
* If the player does not see this BossBar, nothing happens.
|
||||
*
|
||||
* @param player
|
||||
* Player to unregister this bossbar from
|
||||
* Player to unregister this BossBar from
|
||||
*/
|
||||
public void removePlayer(TabPlayer player);
|
||||
void removePlayer(TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns list of players who can see this bossbar.
|
||||
* Returns list of players who can see this BossBar.
|
||||
* <p>
|
||||
* The returned list can only be used to read. Writing
|
||||
* will not work properly. For adding/removing playes see {@link #addPlayer(TabPlayer)}
|
||||
* will not work properly. For adding/removing players see {@link #addPlayer(TabPlayer)}
|
||||
* and {@link #removePlayer(TabPlayer)}.
|
||||
* @return List of players seeing this bossbar
|
||||
* @return List of players seeing this BossBar
|
||||
*/
|
||||
public List<TabPlayer> getPlayers();
|
||||
List<TabPlayer> getPlayers();
|
||||
}
|
||||
@@ -7,17 +7,17 @@ import java.util.UUID;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
|
||||
/**
|
||||
* An interface allowing work with bossbars such as creating, sending
|
||||
* An interface allowing work with BossBars such as creating, sending
|
||||
* and toggling.
|
||||
* <p>
|
||||
* Instance can be obtained using {@link me.neznamy.tab.api.TabAPI#getBossBarManager()}.
|
||||
* This requires the bossbar feature to be enabled in config, otherwise the method will
|
||||
* This requires the BossBar feature to be enabled in config, otherwise the method will
|
||||
* return null.
|
||||
*/
|
||||
public interface BossBarManager {
|
||||
|
||||
/**
|
||||
* Creates bossbar with specified parameters and registers it to bossbar manager,
|
||||
* Creates BossBar with specified parameters and registers it to BossBar manager,
|
||||
* allowing to retrieve it later.
|
||||
*
|
||||
* @param title
|
||||
@@ -31,12 +31,12 @@ public interface BossBarManager {
|
||||
*
|
||||
* @param style
|
||||
* Style to use
|
||||
* @return The newly created bossbar
|
||||
* @return The newly created BossBar
|
||||
*/
|
||||
public BossBar createBossBar(String title, float progress, BarColor color, BarStyle style);
|
||||
BossBar createBossBar(String title, float progress, BarColor color, BarStyle style);
|
||||
|
||||
/**
|
||||
* Creates bossbar with specified parameters and registers it to bossbar manager,
|
||||
* Creates BossBar with specified parameters and registers it to BossBar manager,
|
||||
* allowing to retrieve it later.
|
||||
*
|
||||
* @param title
|
||||
@@ -53,58 +53,58 @@ public interface BossBarManager {
|
||||
* @param style
|
||||
* Style to use. Must be a string version of one of enum constants, or
|
||||
* a placeholder that returns one of them
|
||||
* @return The newly created bossbar
|
||||
* @return The newly created BossBar
|
||||
*/
|
||||
public BossBar createBossBar(String title, String progress, String color, String style);
|
||||
BossBar createBossBar(String title, String progress, String color, String style);
|
||||
|
||||
/**
|
||||
* Returns registered bossbar with given name. For bossbars from config it is the name
|
||||
* they were created with, for API bossbars their randomly generated name, which can be
|
||||
* Returns registered BossBar with given name. For BossBars from config it is the name
|
||||
* they were created with, for API BossBars their randomly generated name, which can be
|
||||
* retrieved using {@link me.neznamy.tab.api.bossbar.BossBar#getName()}.
|
||||
* Returns null if no such bossbar exists.
|
||||
* Returns null if no such BossBar exists.
|
||||
*
|
||||
* @param name
|
||||
* Name of registered bossbar
|
||||
* @return bossbar with specified name
|
||||
* Name of registered BossBar
|
||||
* @return BossBar with specified name
|
||||
*/
|
||||
public BossBar getBossBar(String name);
|
||||
BossBar getBossBar(String name);
|
||||
|
||||
/**
|
||||
* Returns registered bossbar with specified UUID. This UUID is randomly generated when
|
||||
* bossbar is created and used in packets / to match which the one from Bukkit API.
|
||||
* Returns null if no such bossbar exists.
|
||||
* Returns registered BossBar with specified UUID. This UUID is randomly generated when
|
||||
* BossBar is created and used in packets / to match which the one from Bukkit API.
|
||||
* Returns null if no such BossBar exists.
|
||||
*
|
||||
* @param id
|
||||
* UUID to return bossbar by
|
||||
* @return bossbar with specified uuid
|
||||
* UUID to return BossBar by
|
||||
* @return BossBar with specified uuid
|
||||
*/
|
||||
public BossBar getBossBar(UUID id);
|
||||
BossBar getBossBar(UUID id);
|
||||
|
||||
/**
|
||||
* Returns a map of all registered bossbars. This includes both bossbars from config
|
||||
* Returns a map of all registered BossBars. This includes both BossBars from config
|
||||
* and those registered via API.
|
||||
* <p>
|
||||
* Map key is bossbar's name available in {@link me.neznamy.tab.api.bossbar.BossBar#getName()},
|
||||
* map value is the bossbar interface.
|
||||
* @return all registered bossbars
|
||||
* Map key is BossBar's name available in {@link me.neznamy.tab.api.bossbar.BossBar#getName()},
|
||||
* map value is the BossBar interface.
|
||||
* @return all registered BossBars
|
||||
*/
|
||||
public Map<String, BossBar> getRegisteredBossBars();
|
||||
Map<String, BossBar> getRegisteredBossBars();
|
||||
|
||||
/**
|
||||
* Toggles bossbar for this player and sends toggle message if {@code sendToggleMessage} is true.
|
||||
* Toggles BossBar for this player and sends toggle message if {@code sendToggleMessage} is true.
|
||||
*
|
||||
* @param player
|
||||
* Player to toggle bossbar for
|
||||
* Player to toggle BossBar for
|
||||
*
|
||||
* @param sendToggleMessage
|
||||
* {@code true} if toggle message should be sent, {@code false} if not
|
||||
* @see #hasBossBarVisible(TabPlayer)
|
||||
* @see #setBossBarVisible(TabPlayer, boolean, boolean)
|
||||
*/
|
||||
public void toggleBossBar(TabPlayer player, boolean sendToggleMessage);
|
||||
void toggleBossBar(TabPlayer player, boolean sendToggleMessage);
|
||||
|
||||
/**
|
||||
* Returns true if player can see bossbars, false if toggled via command or API.
|
||||
* Returns true if player can see BossBars, false if toggled via command or API.
|
||||
*
|
||||
* @param player
|
||||
* Player to check toggle status of
|
||||
@@ -112,56 +112,56 @@ public interface BossBarManager {
|
||||
* @see #toggleBossBar(TabPlayer, boolean)
|
||||
* @see #setBossBarVisible(TabPlayer, boolean, boolean)
|
||||
*/
|
||||
public boolean hasBossBarVisible(TabPlayer player);
|
||||
boolean hasBossBarVisible(TabPlayer player);
|
||||
|
||||
/**
|
||||
* Sets bossbar visibility of player to set value. If value did not change, nothing happens.
|
||||
* Sets BossBar visibility of player to set value. If value did not change, nothing happens.
|
||||
* If visibility changed, toggle message is sent if {@code sendToggleMessage} is {@code true}.
|
||||
*
|
||||
* @param player
|
||||
* Player to set bossbar visibility of
|
||||
* Player to set BossBar visibility of
|
||||
* @param visible
|
||||
* {@code true} if bossbar should be visible, {@code false} if not
|
||||
* {@code true} if BossBar should be visible, {@code false} if not
|
||||
* @param sendToggleMessage
|
||||
* {@code true} if toggle message should be sent if value changed, {@code false} if not
|
||||
* @see #toggleBossBar(TabPlayer, boolean)
|
||||
* @see #hasBossBarVisible(TabPlayer)
|
||||
*/
|
||||
public void setBossBarVisible(TabPlayer player, boolean visible, boolean sendToggleMessage);
|
||||
void setBossBarVisible(TabPlayer player, boolean visible, boolean sendToggleMessage);
|
||||
|
||||
/**
|
||||
* Temporarily displays registered bossbar to player for specified amount of time in milliseconds.
|
||||
* Temporarily displays registered BossBar to player for specified amount of time in milliseconds.
|
||||
* @param player
|
||||
* Player to show bossbar to
|
||||
* @param bossbar
|
||||
* Name of registered bossbar to show
|
||||
* Player to show BossBar to
|
||||
* @param bossBar
|
||||
* Name of registered BossBar to show
|
||||
* @param duration
|
||||
* In milliseconds for how long should bossbar be displayed
|
||||
* In milliseconds for how long should BossBar be displayed
|
||||
* @throws IllegalArgumentException
|
||||
* if no bossbar with specified name exists
|
||||
* if no BossBar with specified name exists
|
||||
* @see #announceBossBar(String, int)
|
||||
* @see #getAnnouncedBossBars()
|
||||
*/
|
||||
public void sendBossBarTemporarily(TabPlayer player, String bossbar, int duration);
|
||||
void sendBossBarTemporarily(TabPlayer player, String bossBar, int duration);
|
||||
|
||||
/**
|
||||
* Temporarily displays registered bossbar to all players for specified amount of time in milliseconds.
|
||||
* @param bossbar
|
||||
* Name of registered bossbar to show
|
||||
* Temporarily displays registered BossBar to all players for specified amount of time in milliseconds.
|
||||
* @param bossBar
|
||||
* Name of registered BossBar to show
|
||||
* @param duration
|
||||
* In milliseconds for how long should bossbar be displayed
|
||||
* In milliseconds for how long should BossBar be displayed
|
||||
* @throws IllegalArgumentException
|
||||
* if no bossbar with specified name exists
|
||||
* if no BossBar with specified name exists
|
||||
* @see #sendBossBarTemporarily(TabPlayer, String, int)
|
||||
* @see #getAnnouncedBossBars()
|
||||
*/
|
||||
public void announceBossBar(String bossbar, int duration);
|
||||
void announceBossBar(String bossBar, int duration);
|
||||
|
||||
/**
|
||||
* Returns list of bossbars which are currently being announced.
|
||||
* @return list of currently active bossbar announcements
|
||||
* Returns list of BossBars which are currently being announced.
|
||||
* @return list of currently active BossBar announcements
|
||||
* @see #sendBossBarTemporarily(TabPlayer, String, int)
|
||||
* @see #announceBossBar(String, int)
|
||||
*/
|
||||
public List<BossBar> getAnnouncedBossBars();
|
||||
List<BossBar> getAnnouncedBossBars();
|
||||
}
|
||||
@@ -1,31 +1,50 @@
|
||||
package me.neznamy.tab.api.chat;
|
||||
|
||||
import me.neznamy.tab.api.util.Preconditions;
|
||||
|
||||
/**
|
||||
* Class for click event action in chat component
|
||||
*/
|
||||
public class ChatClickable {
|
||||
|
||||
private EnumClickAction action;
|
||||
private String value;
|
||||
/** Click action */
|
||||
private final EnumClickAction action;
|
||||
|
||||
/** Click value */
|
||||
private final String value;
|
||||
|
||||
/**
|
||||
* Constructs new instance with given action and value.
|
||||
* @param action
|
||||
* click event action
|
||||
* @param value
|
||||
* click event value
|
||||
* @throws IllegalArgumentException
|
||||
* if {@code action} is null or {@code value} is null
|
||||
*/
|
||||
public ChatClickable(EnumClickAction action, String value) {
|
||||
Preconditions.checkNotNull(action, "hover action cannot be null");
|
||||
Preconditions.checkNotNull(value, "hover value cannot be null");
|
||||
this.action = action;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns click action defined in constructor
|
||||
* @return click action
|
||||
*/
|
||||
public EnumClickAction getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
public void setAction(EnumClickAction action) {
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns click action defined in constructor
|
||||
* @return click action
|
||||
*/
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum for all possible click actions
|
||||
*/
|
||||
@@ -35,6 +54,6 @@ public class ChatClickable {
|
||||
RUN_COMMAND,
|
||||
CHANGE_PAGE, //since 1.8
|
||||
SUGGEST_COMMAND,
|
||||
COPY_TO_CLIPBOARD; //since 1.15
|
||||
COPY_TO_CLIPBOARD //since 1.15
|
||||
}
|
||||
}
|
||||
@@ -1,31 +1,50 @@
|
||||
package me.neznamy.tab.api.chat;
|
||||
|
||||
import me.neznamy.tab.api.util.Preconditions;
|
||||
|
||||
/**
|
||||
* Class for hover event action in chat component
|
||||
*/
|
||||
public class ChatHoverable {
|
||||
|
||||
private EnumHoverAction action;
|
||||
private IChatBaseComponent value;
|
||||
|
||||
/** Hover action */
|
||||
private final EnumHoverAction action;
|
||||
|
||||
/** Hover value */
|
||||
private final IChatBaseComponent value;
|
||||
|
||||
/**
|
||||
* Constructs new instance with given action and value.
|
||||
* @param action
|
||||
* hover event action
|
||||
* @param value
|
||||
* hover event value
|
||||
* @throws IllegalArgumentException
|
||||
* if {@code action} is null or {@code value} is null
|
||||
*/
|
||||
public ChatHoverable(EnumHoverAction action, IChatBaseComponent value) {
|
||||
Preconditions.checkNotNull(action, "hover action cannot be null");
|
||||
Preconditions.checkNotNull(value, "hover value cannot be null");
|
||||
this.action = action;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns hover action defined in constructor
|
||||
* @return hover action
|
||||
*/
|
||||
public EnumHoverAction getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
public void setAction(EnumHoverAction action) {
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns hover value defined in constructor
|
||||
* @return hover value
|
||||
*/
|
||||
public IChatBaseComponent getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(IChatBaseComponent value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum for all possible hover actions
|
||||
*/
|
||||
@@ -33,6 +52,6 @@ public class ChatHoverable {
|
||||
|
||||
SHOW_TEXT,
|
||||
SHOW_ITEM,
|
||||
SHOW_ENTITY;
|
||||
SHOW_ENTITY
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,7 @@ public class ChatModifier {
|
||||
this.clickEvent = modifier.clickEvent == null ? null : new ChatClickable(modifier.clickEvent.getAction(), modifier.clickEvent.getValue());
|
||||
this.hoverEvent = modifier.hoverEvent == null ? null : new ChatHoverable(modifier.hoverEvent.getAction(), modifier.hoverEvent.getValue());
|
||||
this.font = modifier.font;
|
||||
this.targetVersion = modifier.targetVersion;
|
||||
}
|
||||
|
||||
public TextColor getColor() {
|
||||
@@ -156,7 +157,6 @@ public class ChatModifier {
|
||||
/**
|
||||
* Sets click action to RUN_COMMAND and command to given value
|
||||
* @param command - command to perform, might be without / to send a chat message
|
||||
* @return self
|
||||
*/
|
||||
public void onClickRunCommand(String command) {
|
||||
clickEvent = new ChatClickable(EnumClickAction.RUN_COMMAND, command);
|
||||
@@ -172,11 +172,19 @@ public class ChatModifier {
|
||||
|
||||
/**
|
||||
* Sets click action to CHANGE_PAGE and page id to given value
|
||||
* @param newpage - id of new page
|
||||
* @param newPage - id of new page
|
||||
*/
|
||||
public void onClickChangePage(int newpage) {
|
||||
public void onClickChangePage(int newPage) {
|
||||
if (TabAPI.getInstance().getServerVersion().getMinorVersion() < 8) throw new UnsupportedOperationException("change_page click action is not supported on <1.8");
|
||||
clickEvent = new ChatClickable(EnumClickAction.CHANGE_PAGE, String.valueOf(newpage));
|
||||
clickEvent = new ChatClickable(EnumClickAction.CHANGE_PAGE, String.valueOf(newPage));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets click action to COPY_TO_CLIPBOARD and text to provided value
|
||||
* @param text - text to copy to clipboard on click
|
||||
*/
|
||||
public void onClickCopyToClipBoard(String text) {
|
||||
clickEvent = new ChatClickable(EnumClickAction.COPY_TO_CLIPBOARD, text);
|
||||
}
|
||||
|
||||
public void onClick(EnumClickAction action, String value) {
|
||||
|
||||
@@ -3,81 +3,83 @@ package me.neznamy.tab.api.chat;
|
||||
import me.neznamy.tab.api.chat.rgb.RGBUtils;
|
||||
|
||||
/**
|
||||
* A class representing the n.m.s.EnumChatFormat class to make work with it much easier
|
||||
* An enum containing all possible legacy color codes and magic codes. Also contains handy color-related methods.
|
||||
*/
|
||||
public enum EnumChatFormat {
|
||||
|
||||
BLACK(0, '0', "000000"),
|
||||
DARK_BLUE(1, '1', "0000AA"),
|
||||
DARK_GREEN(2, '2', "00AA00"),
|
||||
DARK_AQUA(3, '3', "00AAAA"),
|
||||
DARK_RED(4, '4', "AA0000"),
|
||||
DARK_PURPLE(5, '5', "AA00AA"),
|
||||
GOLD(6, '6', "FFAA00"),
|
||||
GRAY(7, '7', "AAAAAA"),
|
||||
DARK_GRAY(8, '8', "555555"),
|
||||
BLUE(9, '9', "5555FF"),
|
||||
GREEN(10, 'a', "55FF55"),
|
||||
AQUA(11, 'b', "55FFFF"),
|
||||
RED(12, 'c', "FF5555"),
|
||||
LIGHT_PURPLE(13, 'd', "FF55FF"),
|
||||
YELLOW(14, 'e', "FFFF55"),
|
||||
WHITE(15, 'f', "FFFFFF"),
|
||||
OBFUSCATED(16, 'k'),
|
||||
BOLD(17, 'l'),
|
||||
STRIKETHROUGH(18, 'm'),
|
||||
UNDERLINE(19, 'n'),
|
||||
ITALIC(20, 'o'),
|
||||
RESET(21, 'r');
|
||||
BLACK('0', "000000"),
|
||||
DARK_BLUE('1', "0000AA"),
|
||||
DARK_GREEN('2', "00AA00"),
|
||||
DARK_AQUA('3', "00AAAA"),
|
||||
DARK_RED('4', "AA0000"),
|
||||
DARK_PURPLE('5', "AA00AA"),
|
||||
GOLD('6', "FFAA00"),
|
||||
GRAY('7', "AAAAAA"),
|
||||
DARK_GRAY('8', "555555"),
|
||||
BLUE('9', "5555FF"),
|
||||
GREEN('a', "55FF55"),
|
||||
AQUA('b', "55FFFF"),
|
||||
RED('c', "FF5555"),
|
||||
LIGHT_PURPLE('d', "FF55FF"),
|
||||
YELLOW('e', "FFFF55"),
|
||||
WHITE('f', "FFFFFF"),
|
||||
OBFUSCATED('k'),
|
||||
BOLD('l'),
|
||||
STRIKETHROUGH('m'),
|
||||
UNDERLINE('n'),
|
||||
ITALIC('o'),
|
||||
RESET('r');
|
||||
|
||||
/** Creating a constant to avoid memory allocations on each request */
|
||||
private static final EnumChatFormat[] VALUES = values();
|
||||
|
||||
/** The symbol minecraft uses to colorize text */
|
||||
public static final char COLOR_CHAR = 0x00a7;
|
||||
|
||||
/** The color symbol in form of a string */
|
||||
public static final String COLOR_STRING = String.valueOf(COLOR_CHAR);
|
||||
|
||||
//network id of the color
|
||||
private final int networkId;
|
||||
|
||||
//characer representing the color
|
||||
/** Character representing the color or magic code */
|
||||
private final char character;
|
||||
|
||||
//red value of this color
|
||||
private final int red;
|
||||
/** Red value of this constant, 0 for magic codes */
|
||||
private final short red;
|
||||
|
||||
/** Green value of this constant, 0 for magic codes */
|
||||
private final short green;
|
||||
|
||||
/** Blue value of this constant, 0 for magic codes */
|
||||
private final short blue;
|
||||
|
||||
//green value of this color
|
||||
private final int green;
|
||||
|
||||
//blue value of this color
|
||||
private final int blue;
|
||||
|
||||
//hex code as string
|
||||
/** Color as 6-digit hex code, null for magic codes */
|
||||
private final String hexCode;
|
||||
|
||||
//color char followed by color's character
|
||||
/** Color symbol followed by constant's character */
|
||||
private final String chatFormat;
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters
|
||||
* @param networkId - network id of the color
|
||||
* @param character - character representing the color
|
||||
* @param hexColor - hex code of the color
|
||||
* Constructs new color instance with given character and hex code
|
||||
* @param character
|
||||
* character which the color goes by
|
||||
* @param hexCode
|
||||
* 6-digit hex code of the color
|
||||
*/
|
||||
private EnumChatFormat(int networkId, char character, String hexCode) {
|
||||
this.networkId = networkId;
|
||||
EnumChatFormat(char character, String hexCode) {
|
||||
this.character = character;
|
||||
this.chatFormat = String.valueOf(COLOR_CHAR) + character;
|
||||
this.hexCode = hexCode;
|
||||
int hexColor = Integer.parseInt(hexCode, 16);
|
||||
red = (hexColor >> 16) & 0xFF;
|
||||
green = (hexColor >> 8) & 0xFF;
|
||||
blue = hexColor & 0xFF;
|
||||
red = (short) ((hexColor >> 16) & 0xFF);
|
||||
green = (short) ((hexColor >> 8) & 0xFF);
|
||||
blue = (short) (hexColor & 0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters
|
||||
* @param networkId - network id of the color
|
||||
* @param character - character representing the color
|
||||
* Constructs new magic code instance with given character
|
||||
* @param character
|
||||
* character representing the magic code
|
||||
*/
|
||||
private EnumChatFormat(int networkId, char character) {
|
||||
this.networkId = networkId;
|
||||
EnumChatFormat(char character) {
|
||||
this.character = character;
|
||||
this.chatFormat = String.valueOf(COLOR_CHAR) + character;
|
||||
red = 0;
|
||||
@@ -85,63 +87,58 @@ public enum EnumChatFormat {
|
||||
blue = 0;
|
||||
hexCode = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns network id of this color
|
||||
* @return network if of this color
|
||||
* Returns red value of this color code
|
||||
* @return red value
|
||||
*/
|
||||
public int getNetworkId() {
|
||||
return networkId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns red value of this color
|
||||
* @return red value
|
||||
*/
|
||||
public int getRed() {
|
||||
public short getRed() {
|
||||
return red;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns green value of this color
|
||||
* @return green value
|
||||
* Returns green value of this color code
|
||||
* @return green value
|
||||
*/
|
||||
public int getGreen() {
|
||||
public short getGreen() {
|
||||
return green;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns blue value of this color
|
||||
* @return blue value
|
||||
* Returns blue value of this color code
|
||||
* @return blue value
|
||||
*/
|
||||
public int getBlue() {
|
||||
public short getBlue() {
|
||||
return blue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns enum value based on inserted color or null if character is not valid
|
||||
* @param c - color code character (0-9, a-f, k-o, r)
|
||||
* @return instance from the character
|
||||
* Returns enum value based on provided character or null if character is not valid
|
||||
* @param c
|
||||
* color code character (0-9, a-f, k-o, r)
|
||||
* @return instance from the character or null if character is not valid
|
||||
*/
|
||||
public static EnumChatFormat getByChar(char c) {
|
||||
for (EnumChatFormat format : values()) {
|
||||
for (EnumChatFormat format : VALUES) {
|
||||
if (format.character == c) return format;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns enum value of last colors used in given string
|
||||
* @param string - string to check last colors of
|
||||
* @return last used color code in given string
|
||||
* Returns enum value of last colors used in given string.
|
||||
* If it's null, empty or does not contain color codes, WHITE is returned.
|
||||
* @param string
|
||||
* string to check last colors of
|
||||
* @return last used color code in given string or WHITE if nothing is found
|
||||
*/
|
||||
public static EnumChatFormat lastColorsOf(String string) {
|
||||
if (string == null || string.length() == 0) return EnumChatFormat.WHITE;
|
||||
String legacyText = RGBUtils.getInstance().convertRGBtoLegacy(string); //translating RGB into legacy for nametags
|
||||
String legacyText = RGBUtils.getInstance().convertRGBtoLegacy(string);
|
||||
String last = getLastColors(legacyText);
|
||||
if (last.length() > 0) {
|
||||
char c = last.toCharArray()[1];
|
||||
for (EnumChatFormat e : values()) {
|
||||
for (EnumChatFormat e : VALUES) {
|
||||
if (e.character == c) return e;
|
||||
}
|
||||
}
|
||||
@@ -173,20 +170,29 @@ public enum EnumChatFormat {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns enum value with exact red, green and blue values or null if no match
|
||||
* @param red - exact red value
|
||||
* @param green - exact green value
|
||||
* @param blue - exact blue value
|
||||
* @return enum value or null if no such combination exists
|
||||
* Returns enum value with exact red, green and blue values or null if no match was found
|
||||
* @param red
|
||||
* exact red value
|
||||
* @param green
|
||||
* exact green value
|
||||
* @param blue
|
||||
* exact blue value
|
||||
* @return enum value or null if no such combination exists
|
||||
*/
|
||||
public static EnumChatFormat fromRGBExact(int red, int green, int blue){
|
||||
for (EnumChatFormat format : values()) {
|
||||
for (EnumChatFormat format : VALUES) {
|
||||
if (format.red == red && format.green == green && format.blue == blue) return format;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//code taken from bukkit, so it can work on bungee too
|
||||
|
||||
/**
|
||||
* Color translation method taken from bukkit, which converts '&' symbol into
|
||||
* the actual color character if followed by a valid color character.
|
||||
* @param textToTranslate
|
||||
* text to replace color symbol in
|
||||
* @return colorized string from provided text
|
||||
*/
|
||||
public static String color(String textToTranslate){
|
||||
if (textToTranslate == null) return null;
|
||||
if (!textToTranslate.contains("&")) return textToTranslate;
|
||||
@@ -199,13 +205,25 @@ public enum EnumChatFormat {
|
||||
}
|
||||
return new String(b);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Turns back the color symbol into '&' symbol in provided text.
|
||||
* @param text
|
||||
* text to revert colors in
|
||||
* @return reverted text
|
||||
*/
|
||||
public static String decolor(String text) {
|
||||
if (text == null) return null;
|
||||
if (!text.contains(COLOR_STRING)) return text;
|
||||
return text.replace(COLOR_CHAR, '&');
|
||||
}
|
||||
|
||||
//code taken from bukkit, so it can work on bungee too
|
||||
|
||||
/**
|
||||
* Code taken from bukkit, which returns last color codes used in provided text.
|
||||
* @param input
|
||||
* text to get last colors from
|
||||
* @return last colors used in provided text or empty string if nothing was found
|
||||
*/
|
||||
public static String getLastColors(String input) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
int length = input.length();
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
package me.neznamy.tab.api.chat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
|
||||
import me.neznamy.tab.api.util.Preconditions;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
|
||||
@@ -14,6 +11,7 @@ import me.neznamy.tab.api.TabAPI;
|
||||
import me.neznamy.tab.api.chat.ChatClickable.EnumClickAction;
|
||||
import me.neznamy.tab.api.chat.ChatHoverable.EnumHoverAction;
|
||||
import me.neznamy.tab.api.chat.rgb.RGBUtils;
|
||||
import org.json.simple.parser.ParseException;
|
||||
|
||||
/**
|
||||
* A class representing the n.m.s.IChatBaseComponent class to make work with it much easier
|
||||
@@ -21,21 +19,21 @@ import me.neznamy.tab.api.chat.rgb.RGBUtils;
|
||||
@SuppressWarnings("unchecked")
|
||||
public class IChatBaseComponent {
|
||||
|
||||
/**
|
||||
* Component cache maps to avoid large memory allocations as well as
|
||||
* higher CPU usage when using animations which send the same text on repeat.
|
||||
*/
|
||||
private static final Map<String, IChatBaseComponent> componentCache = new HashMap<>();
|
||||
private static final Map<IChatBaseComponent, String> serializeCacheModern = new HashMap<>();
|
||||
private static final Map<IChatBaseComponent, String> serializeCacheLegacy = new HashMap<>();
|
||||
|
||||
//constants
|
||||
private static final String EMPTY_TRANSLATABLE = "{\"translate\":\"\"}";
|
||||
private static final String EMPTY_TEXT = "{\"text\":\"\"}";
|
||||
private static final List<IChatBaseComponent> EMPTY_LIST = new ArrayList<>(0);
|
||||
|
||||
//component text
|
||||
/** Text of the component */
|
||||
private String text;
|
||||
|
||||
|
||||
/** Chat modifier containing color, magic codes, hover and click event */
|
||||
private ChatModifier modifier = new ChatModifier();
|
||||
|
||||
//extra components
|
||||
/** Extra components used in "extra" field */
|
||||
private List<IChatBaseComponent> extra;
|
||||
|
||||
/**
|
||||
@@ -46,7 +44,8 @@ public class IChatBaseComponent {
|
||||
|
||||
/**
|
||||
* Constructs a new component which is a clone of provided component
|
||||
* @param component - component to clone
|
||||
* @param component
|
||||
* component to clone
|
||||
*/
|
||||
public IChatBaseComponent(IChatBaseComponent component) {
|
||||
this.text = component.text;
|
||||
@@ -58,25 +57,29 @@ public class IChatBaseComponent {
|
||||
|
||||
/**
|
||||
* Constructs new instance with given text
|
||||
* @param text - text to display
|
||||
* @param text
|
||||
* text to display
|
||||
*/
|
||||
public IChatBaseComponent(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of extra components or null if none are defined
|
||||
* @return list of extras
|
||||
* Returns list of extra components. If no extra components are defined, returns empty list.
|
||||
* @return list of extra components
|
||||
*/
|
||||
public List<IChatBaseComponent> getExtra(){
|
||||
if (extra == null) return EMPTY_LIST;
|
||||
if (extra == null) return Collections.emptyList();
|
||||
return extra;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets full list of extra components to given list
|
||||
* @param components - components to use as extra
|
||||
* @return self
|
||||
* Sets full list of extra components to given list. Does not allow empty list.
|
||||
* @param components
|
||||
* components to use as extra
|
||||
* @return self
|
||||
* @throws IllegalArgumentException
|
||||
* if {@code components} is an empty list
|
||||
*/
|
||||
public IChatBaseComponent setExtra(List<IChatBaseComponent> components){
|
||||
if (components.isEmpty()) throw new IllegalArgumentException("Unexpected empty array of components"); //exception taken from minecraft
|
||||
@@ -86,105 +89,126 @@ public class IChatBaseComponent {
|
||||
|
||||
/**
|
||||
* Appends provided component as extra component
|
||||
* @param child - component to append
|
||||
* @return self
|
||||
* @param child
|
||||
* component to append
|
||||
*/
|
||||
public IChatBaseComponent addExtra(IChatBaseComponent child) {
|
||||
public void addExtra(IChatBaseComponent child) {
|
||||
if (extra == null) extra = new ArrayList<>();
|
||||
extra.add(child);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns text of this component
|
||||
* @return text of this component
|
||||
* @return text of this component
|
||||
*/
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns chat modifier of this component
|
||||
* @return chat modifier of this component
|
||||
*/
|
||||
public ChatModifier getModifier() {
|
||||
return modifier;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets modifier to provided value
|
||||
* @param modifier
|
||||
* modifier to set value to
|
||||
* @throws IllegalArgumentException
|
||||
* if {@code modifier} is null
|
||||
*/
|
||||
public void setModifier(ChatModifier modifier) {
|
||||
Preconditions.checkNotNull(modifier, "modifier");
|
||||
this.modifier = modifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets text of this component
|
||||
* @param text - text to show
|
||||
* @return self
|
||||
* Changes text of this component
|
||||
* @param text
|
||||
* text to show
|
||||
*/
|
||||
public IChatBaseComponent setText(String text) {
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes string and returns created component
|
||||
* @param json - serialized string
|
||||
* @return Deserialized component
|
||||
* Deserializes string and returns created component. If provided string is null, returns null.
|
||||
* @param json
|
||||
* serialized string
|
||||
* @return Deserialized component or null if input is null
|
||||
*/
|
||||
public static IChatBaseComponent deserialize(String json) {
|
||||
if (json == null) return null;
|
||||
if (json.startsWith("\"") && json.endsWith("\"") && json.length() > 1) {
|
||||
//simple component with only text used, minecraft serializer outputs the text in quotes instead of full json
|
||||
return new IChatBaseComponent(json.substring(1, json.length()-1));
|
||||
}
|
||||
JSONObject jsonObject;
|
||||
try {
|
||||
if (json == null) return null;
|
||||
if (json.startsWith("\"") && json.endsWith("\"") && json.length() > 1) {
|
||||
//simple component with only text used, minecraft serializer outputs the text in quotes instead of full json
|
||||
return new IChatBaseComponent(json.substring(1, json.length()-1));
|
||||
}
|
||||
JSONObject jsonObject = (JSONObject) new JSONParser().parse(json);
|
||||
IChatBaseComponent component;
|
||||
if (jsonObject.containsKey("type")) {
|
||||
return new ChatComponentEntity((String) jsonObject.get("type"), UUID.fromString((String) jsonObject.get("id")), IChatBaseComponent.deserialize(((JSONObject) jsonObject.get("name")).toString()).toFlatText());
|
||||
}
|
||||
component = new IChatBaseComponent();
|
||||
component.setText((String) jsonObject.get("text"));
|
||||
component.modifier.setBold(getBoolean(jsonObject, "bold"));
|
||||
component.modifier.setItalic(getBoolean(jsonObject, "italic"));
|
||||
component.modifier.setUnderlined(getBoolean(jsonObject, "underlined"));
|
||||
component.modifier.setStrikethrough(getBoolean(jsonObject, "strikethrough"));
|
||||
component.modifier.setObfuscated(getBoolean(jsonObject, "obfuscated"));
|
||||
component.modifier.setColor(TextColor.fromString(((String) jsonObject.get("color"))));
|
||||
if (jsonObject.containsKey("clickEvent")) {
|
||||
JSONObject clickEvent = (JSONObject) jsonObject.get("clickEvent");
|
||||
String action = (String) clickEvent.get("action");
|
||||
String value = clickEvent.get("value").toString();
|
||||
component.modifier.onClick(EnumClickAction.valueOf(action.toUpperCase()), value);
|
||||
}
|
||||
if (jsonObject.containsKey("hoverEvent")) {
|
||||
JSONObject hoverEvent = (JSONObject) jsonObject.get("hoverEvent");
|
||||
String action = (String) hoverEvent.get("action");
|
||||
String value = (String) hoverEvent.get("value");
|
||||
component.modifier.onHover(EnumHoverAction.valueOf(action.toUpperCase()), deserialize(value));
|
||||
}
|
||||
if (jsonObject.containsKey("extra")) {
|
||||
List<Object> list = (List<Object>) jsonObject.get("extra");
|
||||
for (Object extra : list) {
|
||||
String string = extra.toString();
|
||||
//reverting .toString() removing "" for simple text
|
||||
if (!string.startsWith("{")) string = "\"" + string + "\"";
|
||||
component.addExtra(deserialize(string));
|
||||
}
|
||||
}
|
||||
return component;
|
||||
} catch (Exception e) {
|
||||
jsonObject = (JSONObject) new JSONParser().parse(json);
|
||||
} catch (ParseException e) {
|
||||
TabAPI.getInstance().logError("Failed to deserialize json component " + json, e);
|
||||
return null;
|
||||
}
|
||||
IChatBaseComponent component;
|
||||
if (jsonObject.containsKey("type")) {
|
||||
return new ChatComponentEntity((String) jsonObject.get("type"), UUID.fromString((String) jsonObject.get("id")), IChatBaseComponent.deserialize(jsonObject.get("name").toString()).toFlatText());
|
||||
}
|
||||
component = new IChatBaseComponent();
|
||||
component.setText((String) jsonObject.get("text"));
|
||||
component.modifier.setBold(getBoolean(jsonObject, "bold"));
|
||||
component.modifier.setItalic(getBoolean(jsonObject, "italic"));
|
||||
component.modifier.setUnderlined(getBoolean(jsonObject, "underlined"));
|
||||
component.modifier.setStrikethrough(getBoolean(jsonObject, "strikethrough"));
|
||||
component.modifier.setObfuscated(getBoolean(jsonObject, "obfuscated"));
|
||||
component.modifier.setColor(TextColor.fromString(((String) jsonObject.get("color"))));
|
||||
if (jsonObject.containsKey("clickEvent")) {
|
||||
JSONObject clickEvent = (JSONObject) jsonObject.get("clickEvent");
|
||||
String action = (String) clickEvent.get("action");
|
||||
String value = clickEvent.get("value").toString();
|
||||
component.modifier.onClick(EnumClickAction.valueOf(action.toUpperCase()), value);
|
||||
}
|
||||
if (jsonObject.containsKey("hoverEvent")) {
|
||||
JSONObject hoverEvent = (JSONObject) jsonObject.get("hoverEvent");
|
||||
String action = (String) hoverEvent.get("action");
|
||||
String value = (String) hoverEvent.get("value");
|
||||
component.modifier.onHover(EnumHoverAction.valueOf(action.toUpperCase()), deserialize(value));
|
||||
}
|
||||
if (jsonObject.containsKey("extra")) {
|
||||
List<Object> list = (List<Object>) jsonObject.get("extra");
|
||||
for (Object extra : list) {
|
||||
String string = extra.toString();
|
||||
//reverting .toString() removing "" for simple text
|
||||
if (!string.startsWith("{")) string = "\"" + string + "\"";
|
||||
component.addExtra(deserialize(string));
|
||||
}
|
||||
}
|
||||
return component;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns boolean value of requested key
|
||||
* @param jsonObject - object to get value from
|
||||
* @param key - name of key
|
||||
* @return value from json object or null if not present
|
||||
* Returns boolean value of requested key from map
|
||||
* @param jsonObject
|
||||
* map to get value from
|
||||
* @param key
|
||||
* name of key
|
||||
* @return value from json object or null if not present
|
||||
*/
|
||||
private static Boolean getBoolean(JSONObject jsonObject, String key) {
|
||||
String value = String.valueOf(jsonObject.getOrDefault(key, null));
|
||||
return "null".equals(value) ? null : Boolean.parseBoolean(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the component to a string representing the serialized component.
|
||||
* This method is only used internally by json library since it's missing
|
||||
* protocol version field used by the method.
|
||||
* @return serialized component in string form
|
||||
* @see #toString(ProtocolVersion)
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
JSONObject json = new JSONObject();
|
||||
@@ -196,28 +220,33 @@ public class IChatBaseComponent {
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes this component with colors based on client version
|
||||
* @param clientVersion - client version
|
||||
* @return Serialized string
|
||||
* Serializes this component with colors based on client version.
|
||||
* If client version is <1.16, HEX colors will be converted to legacy colors.
|
||||
* @param clientVersion
|
||||
* client version to adapt component for
|
||||
* @return serialized string
|
||||
*/
|
||||
public String toString(ProtocolVersion clientVersion) {
|
||||
return toString(clientVersion, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes this component with colors based on client version
|
||||
* @param clientVersion - client version
|
||||
* @param sendTranslatableIfEmpty - if empty translatable should be sent if text is empty or not
|
||||
* @return Serialized string
|
||||
* Serializes this component with colors based on client version.
|
||||
* If client version is <1.16, HEX colors will be converted to legacy colors.
|
||||
* @param clientVersion
|
||||
* client version to adapt component for
|
||||
* @param sendTranslatableIfEmpty
|
||||
* whether empty translatable should be sent if text is empty or not
|
||||
* @return serialized string
|
||||
*/
|
||||
public String toString(ProtocolVersion clientVersion, boolean sendTranslatableIfEmpty) {
|
||||
if (extra == null) {
|
||||
if (text == null) return null;
|
||||
if (text.length() == 0) {
|
||||
if (sendTranslatableIfEmpty) {
|
||||
return EMPTY_TRANSLATABLE;
|
||||
return "{\"translate\":\"\"}";
|
||||
} else {
|
||||
return EMPTY_TEXT;
|
||||
return "{\"text\":\"\"}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -242,8 +271,9 @@ public class IChatBaseComponent {
|
||||
|
||||
/**
|
||||
* Returns organized component from colored text
|
||||
* @param originalText - text to convert
|
||||
* @return organized component from colored text
|
||||
* @param originalText
|
||||
* text to convert
|
||||
* @return organized component from colored text
|
||||
*/
|
||||
public static IChatBaseComponent fromColoredText(String originalText){
|
||||
String text = RGBUtils.getInstance().applyFormats(EnumChatFormat.color(originalText), false);
|
||||
@@ -328,9 +358,11 @@ public class IChatBaseComponent {
|
||||
|
||||
/**
|
||||
* Returns true if text contains legacy color request at defined RGB index start
|
||||
* @param text - text to check
|
||||
* @param i - current index start
|
||||
* @return true if legacy color is defined, false if not
|
||||
* @param text
|
||||
* text to check
|
||||
* @param i
|
||||
* current index start
|
||||
* @return true if legacy color is defined, false if not
|
||||
*/
|
||||
private static boolean containsLegacyCode(String text, int i) {
|
||||
if (text.length() - i < 9 || text.charAt(i+7) != '|') return false;
|
||||
@@ -338,8 +370,8 @@ public class IChatBaseComponent {
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this component into a simple text with legacy colors (closest match if color is set to RGB)
|
||||
* @return The simple text format
|
||||
* Converts this component into a simple text with legacy colors (the closest match if color is set to RGB)
|
||||
* @return The simple text format
|
||||
*/
|
||||
public String toLegacyText() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
@@ -348,11 +380,13 @@ public class IChatBaseComponent {
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends text to string builder, might also add color and magic codes if different
|
||||
* than previous component in chain
|
||||
* @param builder - builder to append text to
|
||||
* @param previousFormatting - colors and magic codes in previous component
|
||||
* @return New formatting, might be identical to previous one
|
||||
* Appends text to string builder, might also add color and magic codes if they are different
|
||||
* from previous component in chain.
|
||||
* @param builder
|
||||
* builder to append text to
|
||||
* @param previousFormatting
|
||||
* colors and magic codes in previous component
|
||||
* @return wew formatting, might be identical to previous one
|
||||
*/
|
||||
private String append(StringBuilder builder, String previousFormatting) {
|
||||
String formatting = previousFormatting;
|
||||
@@ -372,7 +406,7 @@ public class IChatBaseComponent {
|
||||
|
||||
/**
|
||||
* Returns colors and magic codes of this component
|
||||
* @return used colors and magic codes
|
||||
* @return used colors and magic codes
|
||||
*/
|
||||
private String getFormatting() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
@@ -390,7 +424,7 @@ public class IChatBaseComponent {
|
||||
|
||||
/**
|
||||
* Returns raw text without colors, only works correctly when component is organized
|
||||
* @return raw text in this component
|
||||
* @return raw text in this component and all child components
|
||||
*/
|
||||
public String toRawText() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
@@ -403,11 +437,11 @@ public class IChatBaseComponent {
|
||||
|
||||
/**
|
||||
* Converts the component into flat text with used colors (including rgb) and magic codes
|
||||
* @return converted text
|
||||
* @return converted text
|
||||
*/
|
||||
public String toFlatText() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (modifier.getColor() != null) builder.append("#" + modifier.getColor().getHexCode());
|
||||
if (modifier.getColor() != null) builder.append("#").append(modifier.getColor().getHexCode());
|
||||
builder.append(modifier.getMagicCodes());
|
||||
if (text != null) builder.append(text);
|
||||
for (IChatBaseComponent child : getExtra()) {
|
||||
@@ -420,8 +454,9 @@ public class IChatBaseComponent {
|
||||
* Returns the most optimized component based on text. Returns null if text is null,
|
||||
* organized component if RGB colors are used or simple component with only text field
|
||||
* containing the whole text when no RGB colors are used
|
||||
* @param text - text to create component from
|
||||
* @return The most performance-optimized component based on text
|
||||
* @param text
|
||||
* text to create component from
|
||||
* @return The most performance-optimized component based on text
|
||||
*/
|
||||
public static IChatBaseComponent optimizedComponent(String text){
|
||||
if (text == null) return null;
|
||||
|
||||
@@ -1,89 +1,117 @@
|
||||
package me.neznamy.tab.api.chat;
|
||||
|
||||
import me.neznamy.tab.api.util.Preconditions;
|
||||
|
||||
/**
|
||||
* A class used to represent any combination of RGB colors
|
||||
* A class representing a component color, which can be either RGB or legacy code.
|
||||
*/
|
||||
public class TextColor {
|
||||
|
||||
//rgb values, only initializing when they are actually requested
|
||||
private int red = -1;
|
||||
private int green = -1;
|
||||
private int blue = -1;
|
||||
/**
|
||||
* RGB values as a single number of 3 8-bit numbers (0-255).
|
||||
* It is only initialized if colors are actually used to avoid
|
||||
* unnecessary memory allocations with string operations.
|
||||
*/
|
||||
private int rgb = -1;
|
||||
|
||||
//closest legacy color
|
||||
/** Closest legacy color to this color object. */
|
||||
private EnumChatFormat legacyColor;
|
||||
|
||||
//6-digit combination of hexadecimal numbers
|
||||
/** HEX code of this color as a 6-digit hexadecimal string without "#" prefix. */
|
||||
private String hexCode;
|
||||
|
||||
//true if legacy color was forced via constructor, false if automatically
|
||||
/**
|
||||
* Boolean value whether the legacy color was forced with constructor or should be
|
||||
* automatically assigned as closest color.
|
||||
* This value is used in gradients when converting text for legacy players. */
|
||||
private boolean legacyColorForced;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs new instance as a clone of the provided color.
|
||||
* @param color
|
||||
* color to create a clone of
|
||||
* @throws IllegalArgumentException
|
||||
* if color is {@code null}
|
||||
*/
|
||||
public TextColor(TextColor color) {
|
||||
red = color.red;
|
||||
green = color.green;
|
||||
blue = color.blue;
|
||||
Preconditions.checkNotNull(color, "color cannot be null");
|
||||
rgb = color.rgb;
|
||||
legacyColor = color.legacyColor;
|
||||
hexCode = color.hexCode;
|
||||
legacyColorForced = color.legacyColorForced;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance based on hex code as string
|
||||
* @param hexCode - a 6-digit combination of hex numbers
|
||||
* Constructs new instance from provided 6-digit hex code string
|
||||
* @param hexCode
|
||||
* a 6-digit combination of hex numbers as a string
|
||||
* @throws IllegalArgumentException
|
||||
* if hexCode is {@code null}
|
||||
*/
|
||||
public TextColor(String hexCode) {
|
||||
Preconditions.checkNotNull(hexCode, "hex code cannot be null");
|
||||
this.hexCode = hexCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance from given 6-digit hex code and legacy color
|
||||
* @param hexCode - 6-digit hex code
|
||||
* @param legacyColor color to use for legacy clients
|
||||
* Constructs new instance from provided 6-digit hex code and forced legacy color
|
||||
* @param hexCode
|
||||
* 6-digit combination of hex numbers as a string
|
||||
* @param legacyColor
|
||||
* color to use for legacy clients instead of using the closest legacy color
|
||||
* @throws IllegalArgumentException
|
||||
* if {@code hexCode} is {@code null} or {@code legacyColor} is {@code null}
|
||||
*/
|
||||
public TextColor(String hexCode, EnumChatFormat legacyColor) {
|
||||
Preconditions.checkNotNull(hexCode, "hex code cannot be null");
|
||||
Preconditions.checkNotNull(legacyColor, "legacy color cannot be null");
|
||||
this.hexCode = hexCode;
|
||||
this.legacyColorForced = true;
|
||||
this.legacyColor = legacyColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameter
|
||||
* @param legacyColor - legacy color
|
||||
* Constructs new instance from provided legacy color
|
||||
* @param legacyColor
|
||||
* legacy color to construct the instance from
|
||||
* @throws IllegalArgumentException
|
||||
* if {@code legacyColor} is {@code null}
|
||||
*/
|
||||
public TextColor(EnumChatFormat legacyColor) {
|
||||
this.red = legacyColor.getRed();
|
||||
this.green = legacyColor.getGreen();
|
||||
this.blue = legacyColor.getBlue();
|
||||
Preconditions.checkNotNull(legacyColor, "legacy color cannot be null");
|
||||
this.rgb = (legacyColor.getRed() << 16) + (legacyColor.getGreen() << 8) + legacyColor.getBlue();
|
||||
this.hexCode = legacyColor.getHexCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters
|
||||
* @param red - red value
|
||||
* @param green - green value
|
||||
* @param blue - blue value
|
||||
* Constructs new instance with red, green and blue values
|
||||
* @param red
|
||||
* red value
|
||||
* @param green
|
||||
* green value
|
||||
* @param blue
|
||||
* blue value
|
||||
* @throws IllegalArgumentException
|
||||
* if {@code red}, {@code green} or {@code blue} is out of range ({@code 0-255})
|
||||
*/
|
||||
public TextColor(int red, int green, int blue) {
|
||||
this.red = red;
|
||||
this.green = green;
|
||||
this.blue = blue;
|
||||
Preconditions.checkRange(red, 0, 255, "red color");
|
||||
Preconditions.checkRange(green, 0, 255, "green color");
|
||||
Preconditions.checkRange(blue, 0, 255, "blue color");
|
||||
this.rgb = (red << 16) + (green << 8) + blue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets closest legacy color based on rgb values
|
||||
* Loads the closest legacy color based currently provided values
|
||||
*/
|
||||
private EnumChatFormat getClosestColor(int red, int green, int blue) {
|
||||
private EnumChatFormat loadClosestColor() {
|
||||
double minMaxDist = 9999;
|
||||
double maxDist;
|
||||
EnumChatFormat closestColor = EnumChatFormat.WHITE;
|
||||
for (EnumChatFormat color : EnumChatFormat.values()) {
|
||||
int rDiff = color.getRed() - red;
|
||||
int gDiff = color.getGreen() - green;
|
||||
int bDiff = color.getBlue() - blue;
|
||||
if (rDiff < 0) rDiff = -rDiff;
|
||||
if (gDiff < 0) gDiff = -gDiff;
|
||||
if (bDiff < 0) bDiff = -bDiff;
|
||||
int rDiff = Math.abs(color.getRed() - getRed());
|
||||
int gDiff = Math.abs(color.getGreen() - getGreen());
|
||||
int bDiff = Math.abs(color.getBlue() - getBlue());
|
||||
maxDist = rDiff;
|
||||
if (gDiff > maxDist) maxDist = gDiff;
|
||||
if (bDiff > maxDist) maxDist = bDiff;
|
||||
@@ -96,72 +124,56 @@ public class TextColor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns amount of red
|
||||
* @return amount of red
|
||||
* Returns {@code red} value
|
||||
* @return red value
|
||||
*/
|
||||
public int getRed() {
|
||||
if (red == -1) {
|
||||
int hexColor = Integer.parseInt(hexCode, 16);
|
||||
red = (hexColor >> 16) & 0xFF;
|
||||
green = (hexColor >> 8) & 0xFF;
|
||||
blue = hexColor & 0xFF;
|
||||
}
|
||||
return red;
|
||||
if (rgb == -1) rgb = Integer.parseInt(hexCode, 16);
|
||||
return (rgb >> 16) & 0xFF;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns amount of green
|
||||
* @return amount of green
|
||||
* Returns {@code green} value
|
||||
* @return green value
|
||||
*/
|
||||
public int getGreen() {
|
||||
if (green == -1) {
|
||||
int hexColor = Integer.parseInt(hexCode, 16);
|
||||
red = (hexColor >> 16) & 0xFF;
|
||||
green = (hexColor >> 8) & 0xFF;
|
||||
blue = hexColor & 0xFF;
|
||||
}
|
||||
return green;
|
||||
if (rgb == -1) rgb = Integer.parseInt(hexCode, 16);
|
||||
return (rgb >> 8) & 0xFF;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns amount of blue
|
||||
* @return amount of blue
|
||||
* Returns {@code blue} value
|
||||
* @return blue value
|
||||
*/
|
||||
public int getBlue() {
|
||||
if (blue == -1) {
|
||||
int hexColor = Integer.parseInt(hexCode, 16);
|
||||
red = (hexColor >> 16) & 0xFF;
|
||||
green = (hexColor >> 8) & 0xFF;
|
||||
blue = hexColor & 0xFF;
|
||||
}
|
||||
return blue;
|
||||
if (rgb == -1) rgb = Integer.parseInt(hexCode, 16);
|
||||
return rgb & 0xFF;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns defined legacy color
|
||||
* @return defined legacy color
|
||||
* Returns the closest legacy color of this color object.
|
||||
* If the color was defined in constructor, it's returned.
|
||||
* Otherwise, the closest color is calculated the then returned.
|
||||
* @return closest legacy color
|
||||
*/
|
||||
public EnumChatFormat getLegacyColor() {
|
||||
if (legacyColor == null) {
|
||||
legacyColor = getClosestColor(getRed(), getGreen(), getBlue());
|
||||
}
|
||||
if (legacyColor == null) legacyColor = loadClosestColor();
|
||||
return legacyColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns hex code of this color
|
||||
* @return hex code of this color
|
||||
* Returns the rgb combination as a 6-digit hex code string
|
||||
* @return the rgb combination as a 6-digit hex code string
|
||||
*/
|
||||
public String getHexCode() {
|
||||
if (hexCode == null) {
|
||||
hexCode = String.format("%06X", (red << 16) + (green << 8) + blue);
|
||||
}
|
||||
if (hexCode == null) hexCode = String.format("%06X", rgb);
|
||||
return hexCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the color into a valid color value used in color field in chat component
|
||||
* @return the color converted into string acceptable by client
|
||||
* Converts the color into a valid color value used in color field in chat component.
|
||||
* That is either 6-digit hex code prefixed with '#', or lowercase legacy color.
|
||||
* @return the color serialized for use in chat component
|
||||
*/
|
||||
public String toString() {
|
||||
EnumChatFormat legacyEquivalent = EnumChatFormat.fromRGBExact(getRed(), getGreen(), getBlue());
|
||||
@@ -170,21 +182,24 @@ public class TextColor {
|
||||
return legacyEquivalent.toString().toLowerCase();
|
||||
}
|
||||
return "#" + getHexCode();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if legacy color was forced with a constructor, false if automatically
|
||||
* @return true if forced, false if not
|
||||
* Returns true if legacy color was forced with a constructor, false if not
|
||||
* @return true if forced, false if not
|
||||
*/
|
||||
public boolean isLegacyColorForced() {
|
||||
return legacyColorForced;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the string and turns into text color. String is either #RRGGBB or a lowercased legacy color
|
||||
* @param string - string from color field in chat component
|
||||
* @return An instance from specified string
|
||||
* Reads the string as it appears in chat component and turns it into the color object.
|
||||
* If the entered string is null, returns null.
|
||||
* If it's prefixed with '#', it's considered as a hex code.
|
||||
* Otherwise, it is considered being a lowercase legacy color.
|
||||
* @param string
|
||||
* string from color field in chat component
|
||||
* @return An instance from specified string or null if string is null
|
||||
*/
|
||||
public static TextColor fromString(String string) {
|
||||
if (string == null) return null;
|
||||
|
||||
@@ -4,12 +4,10 @@ import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import me.neznamy.tab.api.chat.EnumChatFormat;
|
||||
import me.neznamy.tab.api.chat.IChatBaseComponent;
|
||||
import me.neznamy.tab.api.chat.TextColor;
|
||||
import me.neznamy.tab.api.chat.rgb.format.BukkitFormat;
|
||||
import me.neznamy.tab.api.chat.rgb.format.CMIFormat;
|
||||
import me.neznamy.tab.api.chat.rgb.format.HtmlFormat;
|
||||
import me.neznamy.tab.api.chat.rgb.format.HtmlFormat2;
|
||||
import me.neznamy.tab.api.chat.rgb.format.RGBFormatter;
|
||||
import me.neznamy.tab.api.chat.rgb.format.UnnamedFormat1;
|
||||
import me.neznamy.tab.api.chat.rgb.gradient.CMIGradient;
|
||||
@@ -22,26 +20,30 @@ import me.neznamy.tab.api.chat.rgb.gradient.KyoriGradient;
|
||||
*/
|
||||
public class RGBUtils {
|
||||
|
||||
//instance of class
|
||||
private final static RGBUtils instance = new RGBUtils();
|
||||
/** Instance of the class */
|
||||
private static final RGBUtils instance = new RGBUtils();
|
||||
|
||||
//rgb formatters
|
||||
/** Registered RGB formatters */
|
||||
private final RGBFormatter[] formats;
|
||||
|
||||
//gradient patterns
|
||||
/** Registered gradient patterns */
|
||||
private final GradientPattern[] gradients;
|
||||
|
||||
//TAB's RGB format
|
||||
/** TAB's RGB pattern, used to convert text to bukkit format for boss bar */
|
||||
private final Pattern tabPattern = Pattern.compile("#[0-9a-fA-F]{6}");
|
||||
|
||||
/** RGB pattern for legacy codes */
|
||||
private final Pattern tabPatternLegacy = Pattern.compile("#[0-9a-fA-F]{6}\\|.");
|
||||
|
||||
/**
|
||||
* Constructs new instance and loads all RGB patterns and gradients
|
||||
*/
|
||||
public RGBUtils() {
|
||||
formats = new RGBFormatter[] {
|
||||
new BukkitFormat(),
|
||||
new CMIFormat(),
|
||||
new UnnamedFormat1(),
|
||||
new HtmlFormat(),
|
||||
new HtmlFormat2()
|
||||
new HtmlFormat()
|
||||
};
|
||||
gradients = new GradientPattern[] {
|
||||
//{#RRGGBB>}text{#RRGGBB<}
|
||||
@@ -60,16 +62,22 @@ public class RGBUtils {
|
||||
|
||||
/**
|
||||
* Returns instance of this class
|
||||
* @return instance
|
||||
* @return instance
|
||||
*/
|
||||
public static RGBUtils getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies all RGB formats and gradients to text and returns it
|
||||
* @param text - original text
|
||||
* @return text where everything is converted to #RRGGBB
|
||||
* Applies all RGB formats and gradients to text and returns it.
|
||||
* This method is called on every property initialization to convert formats
|
||||
* once instead of on every refresh, if possible. Because of that, parameter
|
||||
* {@code ignorePlaceholders} exists to not break raw placeholder identifiers
|
||||
* @param text
|
||||
* original text
|
||||
* @param ignorePlaceholders
|
||||
* whether placeholders should be ignored or not
|
||||
* @return text where everything is converted to #RRGGBB
|
||||
*/
|
||||
public String applyFormats(String text, boolean ignorePlaceholders) {
|
||||
String replaced = text;
|
||||
@@ -81,8 +89,18 @@ public class RGBUtils {
|
||||
}
|
||||
return replaced;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Converts TAB's RGB format (#RRGGBB) into bukkit one (&x&r&r&g&g&b&b)
|
||||
* for modern clients (1.16+), for legacy clients it will use the closest color.
|
||||
* @param text
|
||||
* text to convert
|
||||
* @param rgbClient
|
||||
* whether client accepts RGB or not
|
||||
* @return converted text
|
||||
*/
|
||||
public String convertToBukkitFormat(String text, boolean rgbClient) {
|
||||
if (text == null) return null;
|
||||
if (!text.contains("#")) return text; //no rgb codes
|
||||
if (rgbClient) {
|
||||
//converting random formats to TAB one
|
||||
@@ -90,21 +108,22 @@ public class RGBUtils {
|
||||
for (Pattern p : new Pattern[]{tabPatternLegacy, tabPattern}) {
|
||||
Matcher m = p.matcher(replaced);
|
||||
while (m.find()) {
|
||||
String hexcode = m.group();
|
||||
String fixed = "&x&" + hexcode.charAt(1) + "&" + hexcode.charAt(2) + "&" + hexcode.charAt(3) + "&" + hexcode.charAt(4) + "&" + hexcode.charAt(5) + "&" + hexcode.charAt(6);
|
||||
replaced = replaced.replace(hexcode, EnumChatFormat.color(fixed));
|
||||
String hexCode = m.group();
|
||||
String fixed = "&x&" + hexCode.charAt(1) + "&" + hexCode.charAt(2) + "&" + hexCode.charAt(3) + "&" + hexCode.charAt(4) + "&" + hexCode.charAt(5) + "&" + hexCode.charAt(6);
|
||||
replaced = replaced.replace(hexCode, EnumChatFormat.color(fixed));
|
||||
}
|
||||
}
|
||||
return replaced;
|
||||
} else {
|
||||
return IChatBaseComponent.fromColoredText(text).toLegacyText();
|
||||
return convertRGBtoLegacy(text);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts all hex codes in given string to legacy codes
|
||||
* @param text - text to translate
|
||||
* @return - translated text
|
||||
* @param text
|
||||
* text to convert
|
||||
* @return translated text
|
||||
*/
|
||||
public String convertRGBtoLegacy(String text) {
|
||||
if (text == null) return null;
|
||||
@@ -132,7 +151,14 @@ public class RGBUtils {
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if entered string is a valid 6-digit combination of
|
||||
* hexadecimal numbers, false if not
|
||||
* @param string
|
||||
* string to check
|
||||
* @return {@code true} if valid, {@code false} if not
|
||||
*/
|
||||
public boolean isHexCode(String string) {
|
||||
if (string.length() != 6) return false;
|
||||
for (int i=0; i<6; i++) {
|
||||
@@ -144,9 +170,11 @@ public class RGBUtils {
|
||||
|
||||
/**
|
||||
* Returns true if text contains legacy color request at defined RGB index start
|
||||
* @param text - text to check
|
||||
* @param i - current index start
|
||||
* @return true if legacy color is defined, false if not
|
||||
* @param text
|
||||
* text to check
|
||||
* @param i
|
||||
* current index start
|
||||
* @return {@code true} if legacy color is defined and valid, {@code false} otherwise
|
||||
*/
|
||||
private static boolean containsLegacyCode(String text, int i) {
|
||||
if (text.length() - i < 9 || text.charAt(i+7) != '|') return false;
|
||||
|
||||
@@ -10,7 +10,7 @@ import me.neznamy.tab.api.chat.EnumChatFormat;
|
||||
*/
|
||||
public class BukkitFormat implements RGBFormatter {
|
||||
|
||||
private final Pattern pattern = Pattern.compile("[" + EnumChatFormat.COLOR_CHAR + "&]x[[" + EnumChatFormat.COLOR_CHAR + "&]\\p{XDigit}]{12}");
|
||||
private final Pattern pattern = Pattern.compile("[" + EnumChatFormat.COLOR_CHAR + "&]x[" + EnumChatFormat.COLOR_CHAR + "&\\p{XDigit}]{12}");
|
||||
|
||||
@Override
|
||||
public String reformat(String text) {
|
||||
@@ -18,9 +18,9 @@ public class BukkitFormat implements RGBFormatter {
|
||||
String replaced = text;
|
||||
Matcher m = pattern.matcher(replaced);
|
||||
while (m.find()) {
|
||||
String hexcode = m.group();
|
||||
String fixed = new String(new char[] {'#', hexcode.charAt(3), hexcode.charAt(5), hexcode.charAt(7), hexcode.charAt(9), hexcode.charAt(11), hexcode.charAt(13)});
|
||||
replaced = replaced.replace(hexcode, fixed);
|
||||
String hexCode = m.group();
|
||||
String fixed = new String(new char[] {'#', hexCode.charAt(3), hexCode.charAt(5), hexCode.charAt(7), hexCode.charAt(9), hexCode.charAt(11), hexCode.charAt(13)});
|
||||
replaced = replaced.replace(hexCode, fixed);
|
||||
}
|
||||
return replaced;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import java.util.regex.Pattern;
|
||||
*/
|
||||
public class CMIFormat implements RGBFormatter {
|
||||
|
||||
private final Pattern pattern = Pattern.compile("\\{#[0-9a-fA-F]{6}\\}");
|
||||
private final Pattern pattern = Pattern.compile("\\{#[0-9a-fA-F]{6}}");
|
||||
|
||||
@Override
|
||||
public String reformat(String text) {
|
||||
@@ -16,9 +16,9 @@ public class CMIFormat implements RGBFormatter {
|
||||
String replaced = text;
|
||||
Matcher m = pattern.matcher(replaced);
|
||||
while (m.find()) {
|
||||
String hexcode = m.group();
|
||||
String fixed = hexcode.substring(2, 8);
|
||||
replaced = replaced.replace(hexcode, "#" + fixed);
|
||||
String hexCode = m.group();
|
||||
String fixed = hexCode.substring(2, 8);
|
||||
replaced = replaced.replace(hexCode, "#" + fixed);
|
||||
}
|
||||
return replaced;
|
||||
}
|
||||
|
||||
@@ -16,9 +16,9 @@ public class HtmlFormat implements RGBFormatter {
|
||||
Matcher m = pattern.matcher(text);
|
||||
String replaced = text;
|
||||
while (m.find()) {
|
||||
String hexcode = m.group();
|
||||
String fixed = hexcode.substring(2, 8);
|
||||
replaced = replaced.replace(hexcode, "#" + fixed);
|
||||
String hexCode = m.group();
|
||||
String fixed = hexCode.substring(2, 8);
|
||||
replaced = replaced.replace(hexCode, "#" + fixed);
|
||||
}
|
||||
return replaced;
|
||||
}
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
package me.neznamy.tab.api.chat.rgb.format;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Formatter for <#RRGGBB>
|
||||
*/
|
||||
public class HtmlFormat2 implements RGBFormatter {
|
||||
|
||||
private final Pattern pattern = Pattern.compile("<#[0-9a-fA-F]{6}>");
|
||||
|
||||
@Override
|
||||
public String reformat(String text) {
|
||||
if (!text.contains("<#")) return text;
|
||||
Matcher m = pattern.matcher(text);
|
||||
String replaced = text;
|
||||
while (m.find()) {
|
||||
String hexcode = m.group();
|
||||
String fixed = hexcode.substring(2, 8);
|
||||
replaced = replaced.replace(hexcode, "#" + fixed);
|
||||
}
|
||||
return replaced;
|
||||
}
|
||||
}
|
||||
@@ -10,5 +10,5 @@ public interface RGBFormatter {
|
||||
* @param text - text to format
|
||||
* @return reformatted text
|
||||
*/
|
||||
public String reformat(String text);
|
||||
String reformat(String text);
|
||||
}
|
||||
@@ -6,11 +6,11 @@ import java.util.regex.Pattern;
|
||||
public class CMIGradient extends CommonGradient {
|
||||
|
||||
//pattern for {#RRGGBB<>}
|
||||
private final Pattern shortcutPattern = Pattern.compile("\\{#[0-9a-fA-F]{6}<>\\}");
|
||||
private final Pattern shortcutPattern = Pattern.compile("\\{#[0-9a-fA-F]{6}<>}");
|
||||
|
||||
public CMIGradient() {
|
||||
super(Pattern.compile("\\{#[0-9a-fA-F]{6}>\\}[^\\{]*\\{#[0-9a-fA-F]{6}<\\}"),
|
||||
Pattern.compile("\\{#[0-9a-fA-F]{6}\\|.>\\}[^\\{]*\\{#[0-9a-fA-F]{6}<\\}"),
|
||||
super(Pattern.compile("\\{#[0-9a-fA-F]{6}>}[^{]*\\{#[0-9a-fA-F]{6}<}"),
|
||||
Pattern.compile("\\{#[0-9a-fA-F]{6}\\|.>}[^{]*\\{#[0-9a-fA-F]{6}<}"),
|
||||
"{#", 9, 2, 10, 8);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ public interface GradientPattern {
|
||||
* @param text - text to be reformatted
|
||||
* @return reformatted text
|
||||
*/
|
||||
public String applyPattern(String text, boolean ignorePlaceholders);
|
||||
String applyPattern(String text, boolean ignorePlaceholders);
|
||||
|
||||
/**
|
||||
* Returns gradient text based on start color, text and end color
|
||||
@@ -22,18 +22,18 @@ public interface GradientPattern {
|
||||
* @param end - end color
|
||||
* @return reformatted text
|
||||
*/
|
||||
public default String asGradient(TextColor start, String text, TextColor end) {
|
||||
default String asGradient(TextColor start, String text, TextColor end) {
|
||||
//lazy support for magic codes in gradients
|
||||
String magicCodes = EnumChatFormat.getLastColors(text);
|
||||
String decolorized = text.substring(magicCodes.length());
|
||||
String deColorized = text.substring(magicCodes.length());
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int length = decolorized.length();
|
||||
int length = deColorized.length();
|
||||
if (length == 1) {
|
||||
sb.append("#");
|
||||
sb.append(new TextColor(start.getRed(), start.getGreen(), start.getBlue()).getHexCode());
|
||||
if (start.isLegacyColorForced()) sb.append("|" + start.getLegacyColor().getCharacter());
|
||||
if (start.isLegacyColorForced()) sb.append("|").append(start.getLegacyColor().getCharacter());
|
||||
sb.append(magicCodes);
|
||||
sb.append(decolorized);
|
||||
sb.append(deColorized);
|
||||
return sb.toString();
|
||||
}
|
||||
for (int i=0; i<length; i++) {
|
||||
@@ -42,9 +42,9 @@ public interface GradientPattern {
|
||||
int blue = (int) (start.getBlue() + (float)(end.getBlue() - start.getBlue())/(length-1)*i);
|
||||
sb.append("#");
|
||||
sb.append(new TextColor(red, green, blue).getHexCode());
|
||||
if (start.isLegacyColorForced()) sb.append("|" + start.getLegacyColor().getCharacter());
|
||||
if (start.isLegacyColorForced()) sb.append("|").append(start.getLegacyColor().getCharacter());
|
||||
sb.append(magicCodes);
|
||||
sb.append(decolorized.charAt(i));
|
||||
sb.append(deColorized.charAt(i));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@@ -51,23 +51,19 @@ public abstract class ConfigurationFile {
|
||||
protected ConfigurationFile(InputStream source, File destination) throws IOException {
|
||||
if (destination == null) throw new IllegalArgumentException("Destination cannot be null");
|
||||
this.file = destination;
|
||||
if (file.getParentFile() != null) file.getParentFile().mkdirs();
|
||||
if (!file.exists()) {
|
||||
if (source == null) throw new IllegalStateException("File does not exist and source is null");
|
||||
if (file.getParentFile() != null) Files.createDirectories(file.getParentFile().toPath());
|
||||
if (!file.exists() && source == null) throw new IllegalStateException("File does not exist and source is null");
|
||||
if (file.createNewFile()) {
|
||||
// Files.copy(source, file.toPath());
|
||||
//avoiding MalformedInputException thrown on fabric due to file not having UTF8 encoding by default
|
||||
//also automatically using the encoding so users don't have to worry about it anymore
|
||||
file.createNewFile();
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(source, StandardCharsets.UTF_8));
|
||||
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8))){
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
writer.write(line + "\n");
|
||||
}
|
||||
reader.close();
|
||||
writer.close();
|
||||
}
|
||||
|
||||
}
|
||||
detectHeader();
|
||||
}
|
||||
@@ -155,8 +151,8 @@ public abstract class ConfigurationFile {
|
||||
* @param map
|
||||
* map to get value from
|
||||
* @param key
|
||||
* case insensitive key name
|
||||
* @return map value from case insensitive key
|
||||
* case-insensitive key name
|
||||
* @return map value from case-insensitive key
|
||||
*/
|
||||
private Object getIgnoreCase(Map<Object, Object> map, String key) {
|
||||
for (Entry<Object, Object> entry : map.entrySet()) {
|
||||
@@ -312,7 +308,6 @@ public abstract class ConfigurationFile {
|
||||
public <K, V> Map<K, V> getConfigurationSection(String path) {
|
||||
if (path == null || path.length() == 0) return (Map<K, V>) values;
|
||||
Object value = getObject(path, null);
|
||||
if (value == null) return new LinkedHashMap<>();
|
||||
if (value instanceof Map) {
|
||||
return (Map<K, V>) value;
|
||||
} else {
|
||||
@@ -360,11 +355,11 @@ public abstract class ConfigurationFile {
|
||||
private Map<String, Object> set(Map<String, Object> map, String path, Object value) {
|
||||
if (path.contains(".")) {
|
||||
String keyWord = getRealKey(map, path.split("\\.")[0]);
|
||||
Object submap = map.get(keyWord);
|
||||
if (!(submap instanceof Map)) {
|
||||
submap = new LinkedHashMap<>();
|
||||
Object subMap = map.get(keyWord);
|
||||
if (!(subMap instanceof Map)) {
|
||||
subMap = new LinkedHashMap<>();
|
||||
}
|
||||
map.put(keyWord, set((Map<String, Object>) submap, path.substring(keyWord.length()+1, path.length()), value));
|
||||
map.put(keyWord, set((Map<String, Object>) subMap, path.substring(keyWord.length()+1), value));
|
||||
} else {
|
||||
if (value == null) {
|
||||
map.remove(getRealKey(map, path));
|
||||
@@ -386,20 +381,19 @@ public abstract class ConfigurationFile {
|
||||
* @return The real key name
|
||||
*/
|
||||
private String getRealKey(Map<?, ?> map, String key) {
|
||||
for (Object mapkey : map.keySet()) {
|
||||
if (mapkey.toString().equalsIgnoreCase(key)) return mapkey.toString();
|
||||
for (Object mapKey : map.keySet()) {
|
||||
if (mapKey.toString().equalsIgnoreCase(key)) return mapKey.toString();
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects header of a file (first lines of file starting with #).
|
||||
*
|
||||
* @return list of comment lines on top
|
||||
*
|
||||
* @throws IOException
|
||||
* if I/O operation fails
|
||||
*/
|
||||
private List<String> detectHeader() throws IOException {
|
||||
private void detectHeader() throws IOException {
|
||||
header = new ArrayList<>();
|
||||
for (String line : Files.readAllLines(file.toPath())) {
|
||||
if (line.startsWith("#")) {
|
||||
@@ -408,7 +402,6 @@ public abstract class ConfigurationFile {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return header;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,7 +10,6 @@ import java.io.Writer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.yaml.snakeyaml.DumperOptions;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
@@ -27,9 +26,6 @@ public class YamlConfigurationFile extends ConfigurationFile {
|
||||
/** SnakeYAML instance */
|
||||
private static final Yaml yaml;
|
||||
|
||||
/**
|
||||
* Initializes SnakeYAML instance with BLOCK flowstyle dumper option
|
||||
*/
|
||||
static {
|
||||
DumperOptions options = new DumperOptions();
|
||||
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
|
||||
@@ -53,13 +49,12 @@ public class YamlConfigurationFile extends ConfigurationFile {
|
||||
* @throws IOException
|
||||
* if I/O operation with the file unexpectedly fails
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public YamlConfigurationFile(InputStream source, File destination) throws YAMLException, IOException {
|
||||
super(source, destination);
|
||||
FileInputStream input = null;
|
||||
try {
|
||||
input = new FileInputStream(file);
|
||||
values = (Map<String, Object>) yaml.load(input);
|
||||
values = yaml.load(input);
|
||||
if (values == null) values = new LinkedHashMap<>();
|
||||
input.close();
|
||||
} catch (YAMLException e) {
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package me.neznamy.tab.api.event;
|
||||
|
||||
/**
|
||||
* The event bus. This is used to register event listeners/handlers for
|
||||
* handling events that may be fired by TAB.
|
||||
*/
|
||||
public interface EventBus {
|
||||
|
||||
/**
|
||||
* Scans the given listener for any method that is annotated with
|
||||
* {@link Subscribe} and registers it as a listener to this event bus.
|
||||
*
|
||||
* All methods in this class that are annotated with {@link Subscribe}
|
||||
* must meet the following criteria:
|
||||
* <ul>
|
||||
* <li>It must be <strong>public</strong>.</li>
|
||||
* <li>It must <strong>not</strong> be abstract.</li>
|
||||
* <li>It must have exactly <strong>one</strong> parameter.</li>
|
||||
* <li>Its single parameter must be <strong>an event</strong>.</li>
|
||||
* </ul>
|
||||
* If a method does not meet the above criteria, an exception <strong>will</strong>
|
||||
* be thrown.
|
||||
*
|
||||
* @param listener the listener to register
|
||||
* @throws RuntimeException if a method does not meet the criteria
|
||||
*/
|
||||
void register(Object listener);
|
||||
|
||||
/**
|
||||
* Registers the given handler to this event bus.
|
||||
*
|
||||
* @param type the class type of the event
|
||||
* @param handler the handler to register
|
||||
* @param <E> the type of the event
|
||||
*/
|
||||
<E extends TabEvent> void register(Class<E> type, EventHandler<E> handler);
|
||||
|
||||
/**
|
||||
* Scans the given listener for any method that is annotated with
|
||||
* {@link Subscribe} and unregisters it from this event bus.
|
||||
*
|
||||
* @param listener the listener to unregister
|
||||
*/
|
||||
void unregister(Object listener);
|
||||
|
||||
/**
|
||||
* Unregisters the given handler from this event bus.
|
||||
*
|
||||
* @param handler the handler to unregister
|
||||
* @param <E> the type of the event
|
||||
*/
|
||||
<E extends TabEvent> void unregister(EventHandler<E> handler);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package me.neznamy.tab.api.event;
|
||||
|
||||
/**
|
||||
* A handler for an event. This allows listening for events in a more
|
||||
* functional style.
|
||||
*
|
||||
* @param <E> the type of event this handler handles
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface EventHandler<E> {
|
||||
|
||||
/**
|
||||
* Called when the given event is fired from an event bus.
|
||||
*
|
||||
* @param event the event to handle
|
||||
*/
|
||||
void handle(E event);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package me.neznamy.tab.api.event;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Subscribes to a {@link TabEvent}.
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Subscribe {
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package me.neznamy.tab.api.event;
|
||||
|
||||
/**
|
||||
* An event that may be fired by TAB when something occurs.
|
||||
*
|
||||
* This is a marker interface. All events <strong>must</strong> implement this
|
||||
* interface.
|
||||
*/
|
||||
public interface TabEvent {
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package me.neznamy.tab.api.event.player;
|
||||
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import me.neznamy.tab.api.event.TabEvent;
|
||||
|
||||
/**
|
||||
* Called when the player has been fully loaded by TAB.
|
||||
*/
|
||||
public interface PlayerLoadEvent extends TabEvent {
|
||||
|
||||
/**
|
||||
* Gets the player that was loaded.
|
||||
*
|
||||
* @return the player that was loaded
|
||||
*/
|
||||
TabPlayer getPlayer();
|
||||
|
||||
/**
|
||||
* Returns true if player was loaded because they joined,
|
||||
* false if the player was loaded because tab reload command was executed
|
||||
* @return true if player joined, false if plugin was reloaded
|
||||
*/
|
||||
boolean isJoin();
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package me.neznamy.tab.api.event.plugin;
|
||||
|
||||
import me.neznamy.tab.api.event.TabEvent;
|
||||
import me.neznamy.tab.api.placeholder.Placeholder;
|
||||
|
||||
public interface PlaceholderRegisterEvent extends TabEvent {
|
||||
|
||||
String getIdentifier();
|
||||
|
||||
void setPlaceholder(Placeholder placeholder);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package me.neznamy.tab.api.event.plugin;
|
||||
|
||||
import me.neznamy.tab.api.event.TabEvent;
|
||||
|
||||
/**
|
||||
* Called when TAB is fully loaded.
|
||||
*/
|
||||
public interface TabLoadEvent extends TabEvent {
|
||||
}
|
||||
@@ -2,15 +2,15 @@ package me.neznamy.tab.api.placeholder;
|
||||
|
||||
public interface Placeholder {
|
||||
|
||||
public int getRefresh();
|
||||
int getRefresh();
|
||||
|
||||
public String getIdentifier();
|
||||
String getIdentifier();
|
||||
|
||||
public boolean isTriggerMode();
|
||||
boolean isTriggerMode();
|
||||
|
||||
public void enableTriggerMode();
|
||||
void enableTriggerMode();
|
||||
|
||||
public void enableTriggerMode(Runnable onActivation, Runnable onDisable);
|
||||
void enableTriggerMode(Runnable onActivation, Runnable onDisable);
|
||||
|
||||
public void unload();
|
||||
void unload();
|
||||
}
|
||||
@@ -13,24 +13,24 @@ public interface PlaceholderManager {
|
||||
/**
|
||||
* Registers a server placeholder (placeholder with same output for all players)
|
||||
*/
|
||||
public ServerPlaceholder registerServerPlaceholder(String identifier, int refresh, Supplier<Object> supplier);
|
||||
ServerPlaceholder registerServerPlaceholder(String identifier, int refresh, Supplier<Object> supplier);
|
||||
|
||||
/**
|
||||
* Registers a player placeholder (placeholder with player-specific output)
|
||||
*/
|
||||
public PlayerPlaceholder registerPlayerPlaceholder(String identifier, int refresh, Function<TabPlayer, Object> function);
|
||||
PlayerPlaceholder registerPlayerPlaceholder(String identifier, int refresh, Function<TabPlayer, Object> function);
|
||||
|
||||
/**
|
||||
* Registers a relational placeholder (different output for each player pair)
|
||||
*/
|
||||
public RelationalPlaceholder registerRelationalPlaceholder(String identifier, int refresh, BiFunction<TabPlayer, TabPlayer, Object> function);
|
||||
RelationalPlaceholder registerRelationalPlaceholder(String identifier, int refresh, BiFunction<TabPlayer, TabPlayer, Object> function);
|
||||
|
||||
/**
|
||||
* Detects placeholders in text using %% pattern and returns list of all detected identifiers
|
||||
* @param text - text to detect placeholders in
|
||||
* @return list of detected identifiers
|
||||
*/
|
||||
public List<String> detectPlaceholders(String text);
|
||||
List<String> detectPlaceholders(String text);
|
||||
|
||||
/**
|
||||
* Adds placeholder to list of used placeholders and assigns this feature as using it,
|
||||
@@ -38,7 +38,9 @@ public interface PlaceholderManager {
|
||||
* @param identifier - placeholder identifier
|
||||
* @param feature - feature using the placeholder
|
||||
*/
|
||||
public void addUsedPlaceholder(String identifier, TabFeature feature);
|
||||
void addUsedPlaceholder(String identifier, TabFeature feature);
|
||||
|
||||
public String findReplacement(String placeholder, String output);
|
||||
String findReplacement(String placeholder, String output);
|
||||
|
||||
List<String> getUsedPlaceholders();
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import me.neznamy.tab.api.TabPlayer;
|
||||
|
||||
public interface PlayerPlaceholder extends Placeholder {
|
||||
|
||||
public void updateValue(TabPlayer player, Object value);
|
||||
void updateValue(TabPlayer player, Object value);
|
||||
|
||||
public Object request(TabPlayer p);
|
||||
Object request(TabPlayer p);
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import me.neznamy.tab.api.TabPlayer;
|
||||
|
||||
public interface RelationalPlaceholder extends Placeholder {
|
||||
|
||||
public void updateValue(TabPlayer viewer, TabPlayer target, Object value);
|
||||
void updateValue(TabPlayer viewer, TabPlayer target, Object value);
|
||||
|
||||
public Object request(TabPlayer viewer, TabPlayer target);
|
||||
Object request(TabPlayer viewer, TabPlayer target);
|
||||
}
|
||||
@@ -2,7 +2,7 @@ package me.neznamy.tab.api.placeholder;
|
||||
|
||||
public interface ServerPlaceholder extends Placeholder {
|
||||
|
||||
public void updateValue(Object value);
|
||||
void updateValue(Object value);
|
||||
|
||||
public Object request();
|
||||
Object request();
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import me.neznamy.tab.api.chat.rgb.RGBUtils;
|
||||
import me.neznamy.tab.api.util.BiFunctionWithException;
|
||||
|
||||
/**
|
||||
* An interface represending a platform-specific packet builder
|
||||
* An interface representing a platform-specific packet builder
|
||||
*/
|
||||
public abstract class PacketBuilder {
|
||||
|
||||
@@ -180,7 +180,7 @@ public abstract class PacketBuilder {
|
||||
|
||||
/**
|
||||
* If {@code clientVersion} is >= 1.13, creates a component from given text and returns
|
||||
* it as a serialized component, which bungeecord uses.
|
||||
* it as a serialized component, which BungeeCord uses.
|
||||
* <p>
|
||||
* If {@code clientVersion} is < 1.12, the text is cut to {@code length} characters if
|
||||
* needed and returned.
|
||||
@@ -202,13 +202,13 @@ public abstract class PacketBuilder {
|
||||
|
||||
/**
|
||||
* Converts platform-specific instance of player info packet into
|
||||
* {@link me.neznamy.tab.api.protocol.PacketPlayOutPlayerInfo} object.
|
||||
* {@link PacketPlayOutPlayerInfo} object.
|
||||
*
|
||||
* @param packet
|
||||
* platform-specific info packet
|
||||
* @param clientVersion
|
||||
* Version of client receiving the packet
|
||||
* @return The packet converted into {@link me.neznamy.tab.api.protocol.PacketPlayOutPlayerInfo}
|
||||
* @return The packet converted into {@link PacketPlayOutPlayerInfo}
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
@@ -216,29 +216,25 @@ public abstract class PacketBuilder {
|
||||
|
||||
/**
|
||||
* Converts platform-specific instance of objective packet into
|
||||
* {@link me.neznamy.tab.api.protocol.PacketPlayOutScoreboardObjective} object.
|
||||
* {@link PacketPlayOutScoreboardObjective} object.
|
||||
*
|
||||
* @param packet
|
||||
* platform-specific objective packet
|
||||
* @param clientVersion
|
||||
* Version of client receiving the packet
|
||||
* @return The packet converted into {@link me.neznamy.tab.api.protocol.PacketPlayOutScoreboardObjective}
|
||||
* @return The packet converted into {@link PacketPlayOutScoreboardObjective}
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public abstract PacketPlayOutScoreboardObjective readObjective(Object packet, ProtocolVersion clientVersion) throws ReflectiveOperationException;
|
||||
public abstract PacketPlayOutScoreboardObjective readObjective(Object packet) throws ReflectiveOperationException;
|
||||
|
||||
/**
|
||||
* Converts platform-specific instance of display objective packet into
|
||||
* {@link me.neznamy.tab.api.protocol.PacketPlayOutScoreboardDisplayObjective} object.
|
||||
* {@link PacketPlayOutScoreboardDisplayObjective} object.
|
||||
*
|
||||
* @param packet
|
||||
* platform-specific display objective packet
|
||||
* @param clientVersion
|
||||
* Version of client receiving the packet
|
||||
* @return The packet converted into {@link me.neznamy.tab.api.protocol.PacketPlayOutScoreboardDisplayObjective}
|
||||
* @return The packet converted into {@link PacketPlayOutScoreboardDisplayObjective}
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public abstract PacketPlayOutScoreboardDisplayObjective readDisplayObjective(Object packet, ProtocolVersion clientVersion) throws ReflectiveOperationException;
|
||||
public abstract PacketPlayOutScoreboardDisplayObjective readDisplayObjective(Object packet) throws ReflectiveOperationException;
|
||||
}
|
||||
@@ -10,22 +10,22 @@ import me.neznamy.tab.api.bossbar.BarStyle;
|
||||
*/
|
||||
public class PacketPlayOutBoss implements TabPacket {
|
||||
|
||||
/** UUID of the bossbar */
|
||||
private UUID id;
|
||||
/** UUID of the BossBar */
|
||||
private final UUID id;
|
||||
|
||||
/** Action of this packet */
|
||||
private Action operation;
|
||||
private final Action operation;
|
||||
|
||||
/** Bossbar title */
|
||||
/** BossBar title */
|
||||
private String name;
|
||||
|
||||
/** Bossbar progress (0-1)*/
|
||||
/** BossBar progress (0-1)*/
|
||||
private float pct;
|
||||
|
||||
/** Bossbar color */
|
||||
/** BossBar color */
|
||||
private BarColor color;
|
||||
|
||||
/** Bossbar style */
|
||||
/** BossBar style */
|
||||
private BarStyle overlay;
|
||||
|
||||
/** Darken screen flag */
|
||||
@@ -42,15 +42,15 @@ public class PacketPlayOutBoss implements TabPacket {
|
||||
* {@link me.neznamy.tab.api.protocol.PacketPlayOutBoss.Action}.ADD action
|
||||
*
|
||||
* @param id
|
||||
* bossbar uuid
|
||||
* BossBar uuid
|
||||
* @param name
|
||||
* bossbar title
|
||||
* BossBar title
|
||||
* @param pct
|
||||
* bossbar progress
|
||||
* BossBar progress
|
||||
* @param color
|
||||
* bossbar color
|
||||
* BossBar color
|
||||
* @param overlay
|
||||
* bossbar style
|
||||
* BossBar style
|
||||
*/
|
||||
public PacketPlayOutBoss(UUID id, String name, float pct, BarColor color, BarStyle overlay) {
|
||||
this.operation = Action.ADD;
|
||||
@@ -66,7 +66,7 @@ public class PacketPlayOutBoss implements TabPacket {
|
||||
* {@link me.neznamy.tab.api.protocol.PacketPlayOutBoss.Action}.REMOVE action
|
||||
*
|
||||
* @param id
|
||||
* bossbar uuid
|
||||
* BossBar uuid
|
||||
*/
|
||||
public PacketPlayOutBoss(UUID id) {
|
||||
this.operation = Action.REMOVE;
|
||||
@@ -78,9 +78,9 @@ public class PacketPlayOutBoss implements TabPacket {
|
||||
* {@link me.neznamy.tab.api.protocol.PacketPlayOutBoss.Action}.UPDATE_PCT action
|
||||
*
|
||||
* @param id
|
||||
* bossbar uuid
|
||||
* BossBar uuid
|
||||
* @param pct
|
||||
* bossbar progress
|
||||
* BossBar progress
|
||||
*/
|
||||
public PacketPlayOutBoss(UUID id, float pct) {
|
||||
this.operation = Action.UPDATE_PCT;
|
||||
@@ -93,9 +93,9 @@ public class PacketPlayOutBoss implements TabPacket {
|
||||
* {@link me.neznamy.tab.api.protocol.PacketPlayOutBoss.Action}.UPDATE_NAME action
|
||||
*
|
||||
* @param id
|
||||
* bossbar uuid
|
||||
* BossBar uuid
|
||||
* @param name
|
||||
* bossbar title
|
||||
* BossBar title
|
||||
*/
|
||||
public PacketPlayOutBoss(UUID id, String name) {
|
||||
this.operation = Action.UPDATE_NAME;
|
||||
@@ -108,11 +108,11 @@ public class PacketPlayOutBoss implements TabPacket {
|
||||
* {@link me.neznamy.tab.api.protocol.PacketPlayOutBoss.Action}.UPDATE_STYLE action
|
||||
*
|
||||
* @param id
|
||||
* bossbar uuid
|
||||
* @param name
|
||||
* bossbar color
|
||||
* BossBar uuid
|
||||
* @param color
|
||||
* BossBar color
|
||||
* @param overlay
|
||||
* bossbar style
|
||||
* BossBar style
|
||||
*/
|
||||
public PacketPlayOutBoss(UUID id, BarColor color, BarStyle overlay) {
|
||||
this.operation = Action.UPDATE_STYLE;
|
||||
@@ -171,7 +171,7 @@ public class PacketPlayOutBoss implements TabPacket {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #style}
|
||||
* Returns {@link #overlay}
|
||||
* @return style
|
||||
*/
|
||||
public BarStyle getOverlay() {
|
||||
@@ -275,6 +275,6 @@ public class PacketPlayOutBoss implements TabPacket {
|
||||
UPDATE_PCT,
|
||||
UPDATE_NAME,
|
||||
UPDATE_STYLE,
|
||||
UPDATE_PROPERTIES;
|
||||
UPDATE_PROPERTIES
|
||||
}
|
||||
}
|
||||
@@ -55,6 +55,6 @@ public class PacketPlayOutChat implements TabPacket {
|
||||
|
||||
CHAT,
|
||||
SYSTEM,
|
||||
GAME_INFO;
|
||||
GAME_INFO
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ import me.neznamy.tab.api.chat.IChatBaseComponent;
|
||||
public class PacketPlayOutPlayerInfo implements TabPacket {
|
||||
|
||||
/** Packet action */
|
||||
private EnumPlayerInfoAction action;
|
||||
private final EnumPlayerInfoAction action;
|
||||
|
||||
/** List of affected entries */
|
||||
private final List<PlayerInfoData> entries;
|
||||
@@ -72,12 +72,12 @@ public class PacketPlayOutPlayerInfo implements TabPacket {
|
||||
/** Latency */
|
||||
private int latency;
|
||||
|
||||
/** Gamemode */
|
||||
private EnumGamemode gameMode = EnumGamemode.SURVIVAL; //protocollib causes NPE even when action does not use gamemode
|
||||
/** GameMode */
|
||||
private EnumGamemode gameMode = EnumGamemode.SURVIVAL; //ProtocolLib causes NPE even when action does not use GameMode
|
||||
|
||||
/**
|
||||
* Display name displayed in tablist. Using {@code null} results in no display name
|
||||
* and scoreboard team prefix/suffix being visible in tablist instead.
|
||||
* Display name displayed in TabList. Using {@code null} results in no display name
|
||||
* and scoreboard team prefix/suffix being visible in TabList instead.
|
||||
*/
|
||||
private IChatBaseComponent displayName;
|
||||
|
||||
@@ -103,7 +103,7 @@ public class PacketPlayOutPlayerInfo implements TabPacket {
|
||||
* @param latency
|
||||
* Player's ping
|
||||
* @param gameMode
|
||||
* Player's gamemode
|
||||
* Player's GameMode
|
||||
* @param displayName
|
||||
* Player's display name
|
||||
*/
|
||||
@@ -123,7 +123,7 @@ public class PacketPlayOutPlayerInfo implements TabPacket {
|
||||
* @param uniqueId
|
||||
* Player's uuid
|
||||
* @param gameMode
|
||||
* Player's gamemode
|
||||
* Player's GameMode
|
||||
*/
|
||||
public PlayerInfoData(UUID uniqueId, EnumGamemode gameMode) {
|
||||
this.uniqueId = uniqueId;
|
||||
@@ -254,7 +254,7 @@ public class PacketPlayOutPlayerInfo implements TabPacket {
|
||||
/**
|
||||
* Sets {@link #gameMode} to specified value
|
||||
* @param gameMode
|
||||
* Gamemode to use
|
||||
* GameMode to use
|
||||
*/
|
||||
public void setGameMode(EnumGamemode gameMode) {
|
||||
this.gameMode = gameMode;
|
||||
@@ -288,11 +288,11 @@ public class PacketPlayOutPlayerInfo implements TabPacket {
|
||||
UPDATE_GAME_MODE,
|
||||
UPDATE_LATENCY,
|
||||
UPDATE_DISPLAY_NAME,
|
||||
REMOVE_PLAYER;
|
||||
REMOVE_PLAYER
|
||||
}
|
||||
|
||||
/**
|
||||
* An enum representing gamemode
|
||||
* An enum representing GameMode
|
||||
*/
|
||||
public enum EnumGamemode {
|
||||
|
||||
@@ -300,6 +300,6 @@ public class PacketPlayOutPlayerInfo implements TabPacket {
|
||||
SURVIVAL,
|
||||
CREATIVE,
|
||||
ADVENTURE,
|
||||
SPECTATOR;
|
||||
SPECTATOR
|
||||
}
|
||||
}
|
||||
+6
-6
@@ -7,10 +7,10 @@ import me.neznamy.tab.api.chat.IChatBaseComponent;
|
||||
*/
|
||||
public class PacketPlayOutPlayerListHeaderFooter implements TabPacket {
|
||||
|
||||
/** Tablist header */
|
||||
/** TabList header */
|
||||
private final IChatBaseComponent header;
|
||||
|
||||
/** Tablist footer */
|
||||
/** TabList footer */
|
||||
private final IChatBaseComponent footer;
|
||||
|
||||
/**
|
||||
@@ -18,9 +18,9 @@ public class PacketPlayOutPlayerListHeaderFooter implements TabPacket {
|
||||
* using {@link IChatBaseComponent#optimizedComponent(String)} method.
|
||||
*
|
||||
* @param header
|
||||
* Tablist header
|
||||
* TabList header
|
||||
* @param footer
|
||||
* Tablist footer
|
||||
* TabList footer
|
||||
*/
|
||||
public PacketPlayOutPlayerListHeaderFooter(String header, String footer) {
|
||||
this.header = IChatBaseComponent.optimizedComponent(header);
|
||||
@@ -31,9 +31,9 @@ public class PacketPlayOutPlayerListHeaderFooter implements TabPacket {
|
||||
* Constructs new instance with given parameters.
|
||||
*
|
||||
* @param header
|
||||
* Tablist header
|
||||
* TabList header
|
||||
* @param footer
|
||||
* Tablist footer
|
||||
* TabList footer
|
||||
*/
|
||||
public PacketPlayOutPlayerListHeaderFooter(IChatBaseComponent header, IChatBaseComponent footer) {
|
||||
this.header = header;
|
||||
|
||||
+3
-3
@@ -7,9 +7,9 @@ public class PacketPlayOutScoreboardDisplayObjective implements TabPacket {
|
||||
|
||||
/**
|
||||
* Display slot.
|
||||
* 0 = playerlist,
|
||||
* 1 = sidebar,
|
||||
* 2 = belowname.
|
||||
* 0 = PlayerList,
|
||||
* 1 = SideBar,
|
||||
* 2 = BelowName.
|
||||
*/
|
||||
private final int slot;
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ public class PacketPlayOutScoreboardObjective implements TabPacket {
|
||||
/** Display name */
|
||||
private final String displayName;
|
||||
|
||||
/** Display type, only takes effect in playertlist */
|
||||
/** Display type, only takes effect in PlayerList */
|
||||
private final EnumScoreboardHealthDisplay renderType;
|
||||
|
||||
/**
|
||||
@@ -100,10 +100,10 @@ public class PacketPlayOutScoreboardObjective implements TabPacket {
|
||||
|
||||
/**
|
||||
* An enum representing available display types.
|
||||
* They only take effect in playerlist position.
|
||||
* They only take effect in PlayerList position.
|
||||
*/
|
||||
public enum EnumScoreboardHealthDisplay {
|
||||
|
||||
INTEGER, HEARTS;
|
||||
INTEGER, HEARTS
|
||||
}
|
||||
}
|
||||
@@ -84,6 +84,6 @@ public class PacketPlayOutScoreboardScore implements TabPacket {
|
||||
public enum Action {
|
||||
|
||||
CHANGE,
|
||||
REMOVE;
|
||||
REMOVE
|
||||
}
|
||||
}
|
||||
@@ -12,12 +12,12 @@ public class PacketPlayOutScoreboardTeam implements TabPacket {
|
||||
|
||||
/**
|
||||
* Up to 16 characters long team name.
|
||||
* It is used to sort players alphabetically in tablist by team names.
|
||||
* Teamless players appear on top, sorted by usernames.
|
||||
* It is used to sort players alphabetically in TabList by team names.
|
||||
* Team-less players appear on top, sorted by usernames.
|
||||
* Players with teams are below them, players of the same team are
|
||||
* sorted alphabetically by usernames.
|
||||
*/
|
||||
private String name;
|
||||
private final String name;
|
||||
|
||||
/** Team prefix, limited to 16 characters, on <1.13 */
|
||||
private String playerPrefix;
|
||||
@@ -26,10 +26,10 @@ public class PacketPlayOutScoreboardTeam implements TabPacket {
|
||||
private String playerSuffix;
|
||||
|
||||
/**
|
||||
* Nametag visibility rule since 1.8. Possible options are:
|
||||
* NameTag visibility rule since 1.8. Possible options are:
|
||||
* {@code always}, {@code hideForOtherTeams}, {@code hideForOwnTeam}, {@code never}
|
||||
*/
|
||||
private String nametagVisibility;
|
||||
private String nameTagVisibility;
|
||||
|
||||
/**
|
||||
* Collision rule added in 1.9. Possible options are:
|
||||
@@ -44,7 +44,7 @@ public class PacketPlayOutScoreboardTeam implements TabPacket {
|
||||
private EnumChatFormat color;
|
||||
|
||||
/**
|
||||
* Affected entities. For players it is their name, for other entities their UUID
|
||||
* Affected entities. For players, it is their name, for other entities their UUID
|
||||
* Player name length is limited to 16 characters for <1.8, 40 characters since 1.8.
|
||||
* Entity UUID option was added in 1.8.
|
||||
*/
|
||||
@@ -58,7 +58,7 @@ public class PacketPlayOutScoreboardTeam implements TabPacket {
|
||||
* 3 = add entries,
|
||||
* 4 = remove entries
|
||||
*/
|
||||
private int method;
|
||||
private final int method;
|
||||
|
||||
/**
|
||||
* Bit mask.
|
||||
@@ -96,7 +96,7 @@ public class PacketPlayOutScoreboardTeam implements TabPacket {
|
||||
* @param suffix
|
||||
* Suffix of players in team
|
||||
* @param visibility
|
||||
* Nametag visibility rule
|
||||
* NameTag visibility rule
|
||||
* @param collision
|
||||
* Collision rule
|
||||
* @param players
|
||||
@@ -110,7 +110,7 @@ public class PacketPlayOutScoreboardTeam implements TabPacket {
|
||||
this(0, team);
|
||||
this.playerPrefix = prefix;
|
||||
this.playerSuffix = suffix;
|
||||
this.nametagVisibility = visibility;
|
||||
this.nameTagVisibility = visibility;
|
||||
this.collisionRule = collision;
|
||||
this.players = players;
|
||||
this.options = options;
|
||||
@@ -138,7 +138,7 @@ public class PacketPlayOutScoreboardTeam implements TabPacket {
|
||||
* @param suffix
|
||||
* Suffix of players in team
|
||||
* @param visibility
|
||||
* Nametag visibility rule
|
||||
* NameTag visibility rule
|
||||
* @param collision
|
||||
* Collision rule
|
||||
* @param options
|
||||
@@ -150,7 +150,7 @@ public class PacketPlayOutScoreboardTeam implements TabPacket {
|
||||
this(2, team);
|
||||
this.playerPrefix = prefix;
|
||||
this.playerSuffix = suffix;
|
||||
this.nametagVisibility = visibility;
|
||||
this.nameTagVisibility = visibility;
|
||||
this.collisionRule = collision;
|
||||
this.options = options;
|
||||
}
|
||||
@@ -175,9 +175,9 @@ public class PacketPlayOutScoreboardTeam implements TabPacket {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("PacketPlayOutScoreboardTeam{name=%s,playerPrefix=%s,playerSuffix=%s,nametagVisibility=%s,"
|
||||
return String.format("PacketPlayOutScoreboardTeam{name=%s,playerPrefix=%s,playerSuffix=%s,nameTagVisibility=%s,"
|
||||
+ "collisionRule=%s,color=%s,players=%s,method=%s,options=%s}",
|
||||
name, playerPrefix, playerSuffix, nametagVisibility, collisionRule, color, players, method, options);
|
||||
name, playerPrefix, playerSuffix, nameTagVisibility, collisionRule, color, players, method, options);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -205,11 +205,11 @@ public class PacketPlayOutScoreboardTeam implements TabPacket {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #nametagVisibility}
|
||||
* @return nametagVisibility
|
||||
* Returns {@link #nameTagVisibility}
|
||||
* @return nameTagVisibility
|
||||
*/
|
||||
public String getNametagVisibility() {
|
||||
return nametagVisibility;
|
||||
public String getNameTagVisibility() {
|
||||
return nameTagVisibility;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,5 +12,5 @@ public interface TabPacket {
|
||||
* Returns user-friendly string representation of the packet
|
||||
* @return user-friendly string representation of the packet
|
||||
*/
|
||||
public String toString();
|
||||
String toString();
|
||||
}
|
||||
@@ -9,11 +9,11 @@ public interface Line {
|
||||
|
||||
/**
|
||||
* Returns configured raw text of this line. Placeholders
|
||||
* remain unparsed.
|
||||
* remain in raw format.
|
||||
*
|
||||
* @return raw text of this line
|
||||
*/
|
||||
public String getText();
|
||||
String getText();
|
||||
|
||||
/**
|
||||
* Changes text to new value. Supports placeholders, which are
|
||||
@@ -25,5 +25,5 @@ public interface Line {
|
||||
* @param text
|
||||
* Raw text to display in the line
|
||||
*/
|
||||
public void setText(String text);
|
||||
void setText(String text);
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package me.neznamy.tab.api.scoreboard;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* An interface allowing to work with scoreboard, such as adding plyaers,
|
||||
* An interface allowing to work with scoreboard, such as adding players,
|
||||
* removing players and changing lines. New instance can be created using
|
||||
* {@link ScoreboardManager#createScoreboard(String, String, List)},
|
||||
* for scoreboards from config {@link ScoreboardManager#getRegisteredScoreboards()}.
|
||||
@@ -17,16 +17,16 @@ public interface Scoreboard {
|
||||
*
|
||||
* @return custom name of this scoreboard
|
||||
*/
|
||||
public String getName();
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Returns raw title of this scoreboard. Placeholders stay in their
|
||||
* raw, unparsed format.
|
||||
* raw format.
|
||||
*
|
||||
* @return scoreboard title
|
||||
* @see #setTitle(String)
|
||||
*/
|
||||
public String getTitle();
|
||||
String getTitle();
|
||||
|
||||
/**
|
||||
* Sets title to specified value. Placeholders are refreshed automatically
|
||||
@@ -43,7 +43,7 @@ public interface Scoreboard {
|
||||
* New title to use with placeholder support
|
||||
* @see #getTitle()
|
||||
*/
|
||||
public void setTitle(String title);
|
||||
void setTitle(String title);
|
||||
|
||||
/**
|
||||
* Returns list of lines in this scoreboard in the order they appear
|
||||
@@ -54,7 +54,7 @@ public interface Scoreboard {
|
||||
* @see #addLine(String)
|
||||
* @see #removeLine(int)
|
||||
*/
|
||||
public List<Line> getLines();
|
||||
List<Line> getLines();
|
||||
|
||||
/**
|
||||
* Adds line with specified text on the bottom of scoreboard. Supports
|
||||
@@ -65,7 +65,7 @@ public interface Scoreboard {
|
||||
* @see #getLines()
|
||||
* @see #removeLine(int)
|
||||
*/
|
||||
public void addLine(String text);
|
||||
void addLine(String text);
|
||||
|
||||
/**
|
||||
* Removes line with specified index. Index starts at {@code 0} and ends at
|
||||
@@ -78,12 +78,10 @@ public interface Scoreboard {
|
||||
* @see #getLines()
|
||||
* @see #addLine(String)
|
||||
*/
|
||||
public void removeLine(int index);
|
||||
void removeLine(int index);
|
||||
|
||||
/**
|
||||
* Unregisters this scoreboard from all players who can see it.
|
||||
* Calling this method is equal to iterating over {@link #getPlayers()}
|
||||
* and calling {@link #removePlayer(TabPlayer)} on each player.
|
||||
*/
|
||||
public void unregister();
|
||||
void unregister();
|
||||
}
|
||||
@@ -23,7 +23,7 @@ public interface ScoreboardManager {
|
||||
* Scoreboard {@code title} is limited to 32 characters on <1.13. If needed,
|
||||
* it will be cut to 32 character for those players (after replacing
|
||||
* placeholders). RGB is supported using any of the supported formats.
|
||||
* Placholders are supported.
|
||||
* Placeholders are supported.
|
||||
* <p>
|
||||
* {@code lines} will display in the same order as contained in the list.
|
||||
* Client can only see up to 15 lines at a time, however you can define
|
||||
@@ -39,7 +39,7 @@ public interface ScoreboardManager {
|
||||
* @throws NullPointerException
|
||||
* if {@code name} or {@code lines} is {@code null}
|
||||
*/
|
||||
public Scoreboard createScoreboard(String name, String title, List<String> lines);
|
||||
Scoreboard createScoreboard(String name, String title, List<String> lines);
|
||||
|
||||
/**
|
||||
* Returns map of registered scoreboards via config and API.
|
||||
@@ -49,7 +49,7 @@ public interface ScoreboardManager {
|
||||
*
|
||||
* @return map of registered scoreboards
|
||||
*/
|
||||
public Map<String, Scoreboard> getRegisteredScoreboards();
|
||||
Map<String, Scoreboard> getRegisteredScoreboards();
|
||||
|
||||
/**
|
||||
* Displays scoreboard to defined player. This will disable all display
|
||||
@@ -66,7 +66,7 @@ public interface ScoreboardManager {
|
||||
* @see #hasCustomScoreboard(TabPlayer)
|
||||
* @see #resetScoreboard(TabPlayer)
|
||||
*/
|
||||
public void showScoreboard(TabPlayer player, Scoreboard scoreboard);
|
||||
void showScoreboard(TabPlayer player, Scoreboard scoreboard);
|
||||
|
||||
/**
|
||||
* Returns {@code true} if player has custom scoreboard set using
|
||||
@@ -79,7 +79,7 @@ public interface ScoreboardManager {
|
||||
* @see #showScoreboard(TabPlayer, Scoreboard)
|
||||
* @see #resetScoreboard(TabPlayer)
|
||||
*/
|
||||
public boolean hasCustomScoreboard(TabPlayer player);
|
||||
boolean hasCustomScoreboard(TabPlayer player);
|
||||
|
||||
/**
|
||||
* Hides custom scoreboard sent using {@link #showScoreboard(TabPlayer, Scoreboard)}
|
||||
@@ -91,7 +91,7 @@ public interface ScoreboardManager {
|
||||
* @see #showScoreboard(TabPlayer, Scoreboard)
|
||||
* @see #hasCustomScoreboard(TabPlayer)
|
||||
*/
|
||||
public void resetScoreboard(TabPlayer player);
|
||||
void resetScoreboard(TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns {@code true} if player has scoreboard enabled, {@code false}
|
||||
@@ -105,7 +105,7 @@ public interface ScoreboardManager {
|
||||
* @see #setScoreboardVisible(TabPlayer, boolean, boolean)
|
||||
* @see #toggleScoreboard(TabPlayer, boolean)
|
||||
*/
|
||||
public boolean hasScoreboardVisible(TabPlayer player);
|
||||
boolean hasScoreboardVisible(TabPlayer player);
|
||||
|
||||
/**
|
||||
* Sets scoreboard visibility of player to defined value. If visibility status
|
||||
@@ -122,7 +122,7 @@ public interface ScoreboardManager {
|
||||
* @see #toggleScoreboard(TabPlayer, boolean)
|
||||
* @see #hasScoreboardVisible(TabPlayer)
|
||||
*/
|
||||
public void setScoreboardVisible(TabPlayer player, boolean visible, boolean sendToggleMessage);
|
||||
void setScoreboardVisible(TabPlayer player, boolean visible, boolean sendToggleMessage);
|
||||
|
||||
/**
|
||||
* Toggles scoreboard for specified player. If player had scoreboard visible,
|
||||
@@ -136,7 +136,7 @@ public interface ScoreboardManager {
|
||||
* @see #hasScoreboardVisible(TabPlayer)
|
||||
* @see #setScoreboardVisible(TabPlayer, boolean, boolean)
|
||||
*/
|
||||
public void toggleScoreboard(TabPlayer player, boolean sendToggleMessage);
|
||||
void toggleScoreboard(TabPlayer player, boolean sendToggleMessage);
|
||||
|
||||
/**
|
||||
* Temporarily displays scoreboard to all players for specified amount of
|
||||
@@ -151,5 +151,15 @@ public interface ScoreboardManager {
|
||||
* if no scoreboard was found with such name or {@code duration}
|
||||
* is < 0.
|
||||
*/
|
||||
public void announceScoreboard(String scoreboard, int duration);
|
||||
void announceScoreboard(String scoreboard, int duration);
|
||||
|
||||
/**
|
||||
* Returns player's currently displayed scoreboard. This can be either with
|
||||
* configuration, overridden with commands or the API. Will return {@code null}
|
||||
* if player does not see any scoreboard due to not meeting any display condition.
|
||||
* @param player
|
||||
* player to get active scoreboard of
|
||||
* @return player's active scoreboard or {@code null} if player has no scoreboard
|
||||
*/
|
||||
Scoreboard getActiveScoreboard(TabPlayer player);
|
||||
}
|
||||
@@ -13,14 +13,23 @@ public interface ThreadManager {
|
||||
* @param type - usage type to add cpu usage to
|
||||
* @param task - the task
|
||||
*/
|
||||
public Future<Void> runMeasuredTask(String errorDescription, TabFeature feature, String type, Runnable task);
|
||||
Future<Void> runMeasuredTask(String errorDescription, TabFeature feature, String type, Runnable task);
|
||||
|
||||
/**
|
||||
* Starts a task in new thread and measures how long it took to process
|
||||
* @param errorDescription - description to use if this task throws an error
|
||||
* @param feature - feature to add cpu usage to
|
||||
* @param type - usage type to add cpu usage to
|
||||
* @param task - the task
|
||||
*/
|
||||
Future<Void> runMeasuredTask(String errorDescription, String feature, String type, Runnable task);
|
||||
|
||||
/**
|
||||
* Runs task in a new thread
|
||||
* @param errorDescription - description to use if this task throws an error
|
||||
* @param task - the task
|
||||
*/
|
||||
public Future<Void> runTask(String errorDescription, Runnable task);
|
||||
Future<Void> runTask(String errorDescription, Runnable task);
|
||||
|
||||
/**
|
||||
* Starts a new task with defined repeat interval that measures cpu usage
|
||||
@@ -30,7 +39,7 @@ public interface ThreadManager {
|
||||
* @param type - usage type to add cpu usage to
|
||||
* @param task - the task
|
||||
*/
|
||||
public RepeatingTask startRepeatingMeasuredTask(int intervalMilliseconds, String errorDescription, TabFeature feature, String type, Runnable task);
|
||||
RepeatingTask startRepeatingMeasuredTask(int intervalMilliseconds, String errorDescription, TabFeature feature, String type, Runnable task);
|
||||
|
||||
/**
|
||||
* Runs task with a delay and measures how long it took to process
|
||||
@@ -39,18 +48,9 @@ public interface ThreadManager {
|
||||
* @param feature - feature to add cpu usage to
|
||||
* @param type - usage type to add cpu usage to
|
||||
* @param task - the task
|
||||
* @return future allowing to cancel the task
|
||||
*/
|
||||
public Future<Void> runTaskLater(int delayMilliseconds, String errorDescription, TabFeature feature, String type, Runnable task);
|
||||
|
||||
/**
|
||||
* Runs task with a delay and measures how long it took to process
|
||||
* @param delayMilliseconds - how long to run the task after
|
||||
* @param errorDescription - description to use if this task throws an error
|
||||
* @param feature - feature to add cpu usage to
|
||||
* @param type - usage type to add cpu usage to
|
||||
* @param task - the task
|
||||
*/
|
||||
public Future<Void> runTaskLater(int delayMilliseconds, String errorDescription, String feature, String type, Runnable task);
|
||||
|
||||
public Future<Void> runTaskLater(int delayMilliseconds, String errorDescription, Runnable task);
|
||||
Future<?> runTaskLater(int delayMilliseconds, String errorDescription, TabFeature feature, String type, Runnable task);
|
||||
|
||||
Future<?> runTaskLater(int delayMilliseconds, String errorDescription, Runnable task);
|
||||
}
|
||||
@@ -5,109 +5,109 @@ import me.neznamy.tab.api.TabPlayer;
|
||||
public interface TeamManager {
|
||||
|
||||
/**
|
||||
* Makes player's nametag globally invisible
|
||||
* @see showNametag
|
||||
* @see hasHiddenNametag
|
||||
* Makes player's NameTag globally invisible
|
||||
* @see #showNametag(TabPlayer)
|
||||
* @see #hasHiddenNametag(TabPlayer)
|
||||
*/
|
||||
public void hideNametag(TabPlayer player);
|
||||
void hideNametag(TabPlayer player);
|
||||
|
||||
/**
|
||||
* Hides player's nametag for specified player until it's shown again
|
||||
* @param viewer - player to hide nametag for
|
||||
* Hides player's NameTag for specified player until it's shown again
|
||||
* @param viewer - player to hide NameTag for
|
||||
*/
|
||||
public void hideNametag(TabPlayer player, TabPlayer viewer);
|
||||
void hideNametag(TabPlayer player, TabPlayer viewer);
|
||||
|
||||
/**
|
||||
* Makes player's nametag visible again
|
||||
* @see hideNametag
|
||||
* @see hasHiddenNametag
|
||||
* Makes player's NameTag visible again
|
||||
* @see #hideNametag(TabPlayer)
|
||||
* @see #hasHiddenNametag(TabPlayer)
|
||||
*/
|
||||
public void showNametag(TabPlayer player);
|
||||
void showNametag(TabPlayer player);
|
||||
|
||||
/**
|
||||
* Shows player's nametag for specified viewer if it was hidden before
|
||||
* @param viewer - player to show nametag back for
|
||||
* Shows player's NameTag for specified viewer if it was hidden before
|
||||
* @param viewer - player to show NameTag back for
|
||||
*/
|
||||
public void showNametag(TabPlayer player, TabPlayer viewer);
|
||||
void showNametag(TabPlayer player, TabPlayer viewer);
|
||||
|
||||
/**
|
||||
* Return whether player has hidden nametag or not
|
||||
* @return Whether player has hidden nametag or not
|
||||
* @see hideNametag
|
||||
* @see showNametag
|
||||
* Return whether player has hidden NameTag or not
|
||||
* @return Whether player has hidden NameTag or not
|
||||
* @see #hideNametag(TabPlayer)
|
||||
* @see #showNametag(TabPlayer)
|
||||
*/
|
||||
public boolean hasHiddenNametag(TabPlayer player);
|
||||
boolean hasHiddenNametag(TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns true if nametag is hidden for specified viewer, false if not
|
||||
* Returns true if NameTag is hidden for specified viewer, false if not
|
||||
* @param viewer - player to check visibility status for
|
||||
* @return true if hidden, false if not
|
||||
*/
|
||||
public boolean hasHiddenNametag(TabPlayer player, TabPlayer viewer);
|
||||
boolean hasHiddenNametag(TabPlayer player, TabPlayer viewer);
|
||||
|
||||
/**
|
||||
* Unregisters player's team and no longer handles it, as well as disables anti-override for teams.
|
||||
* This can be resumed using resumeTeamHandling(). If team handling was paused already, nothing happens.
|
||||
*/
|
||||
public void pauseTeamHandling(TabPlayer player);
|
||||
void pauseTeamHandling(TabPlayer player);
|
||||
|
||||
/**
|
||||
* Resumes team handling if it was before paused using pauseTeamHandling(), if not, nothing happens
|
||||
*/
|
||||
public void resumeTeamHandling(TabPlayer player);
|
||||
void resumeTeamHandling(TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns true if team handling is paused for this player using pauseTeamHandling(), false if not or
|
||||
* Returns true if team handling is paused for this player using pauseTeamHandling(), false if not, or
|
||||
* it was resumed already using resumeTeamHandling
|
||||
* @return true if paused, false if not
|
||||
*/
|
||||
public boolean hasTeamHandlingPaused(TabPlayer player);
|
||||
boolean hasTeamHandlingPaused(TabPlayer player);
|
||||
|
||||
/**
|
||||
* Forces new team name for the player until this method is called again with null argument and
|
||||
* performs all actions to change player's team name
|
||||
* @param teamName - forced team name
|
||||
*/
|
||||
public void forceTeamName(TabPlayer player, String teamName);
|
||||
void forceTeamName(TabPlayer player, String teamName);
|
||||
|
||||
/**
|
||||
* Returns forced team name of player or null if not forced
|
||||
* @return forced team name of player or null if not forced
|
||||
*/
|
||||
public String getForcedTeamName(TabPlayer player);
|
||||
String getForcedTeamName(TabPlayer player);
|
||||
|
||||
|
||||
/**
|
||||
* Forces collision rule for the player. Setting it to null will remove forced value
|
||||
* @param collision - forced collision rule
|
||||
*/
|
||||
public void setCollisionRule(TabPlayer player, Boolean collision);
|
||||
void setCollisionRule(TabPlayer player, Boolean collision);
|
||||
|
||||
/**
|
||||
* Returns forced collision rule or null if collision is not forced using setCollisionRule
|
||||
* @return forced value or null if not forced
|
||||
*/
|
||||
public Boolean getCollisionRule(TabPlayer player);
|
||||
Boolean getCollisionRule(TabPlayer player);
|
||||
|
||||
/**
|
||||
* Sends update team properties packet of player's team to everyone
|
||||
* Sends update team's properties packet of player's team to everyone
|
||||
* @param player - player to update team data of
|
||||
*/
|
||||
public void updateTeamData(TabPlayer player);
|
||||
void updateTeamData(TabPlayer player);
|
||||
|
||||
public void setPrefix(TabPlayer player, String prefix);
|
||||
void setPrefix(TabPlayer player, String prefix);
|
||||
|
||||
public void setSuffix(TabPlayer player, String suffix);
|
||||
void setSuffix(TabPlayer player, String suffix);
|
||||
|
||||
public void resetPrefix(TabPlayer player);
|
||||
void resetPrefix(TabPlayer player);
|
||||
|
||||
public void resetSuffix(TabPlayer player);
|
||||
void resetSuffix(TabPlayer player);
|
||||
|
||||
public String getCustomPrefix(TabPlayer player);
|
||||
String getCustomPrefix(TabPlayer player);
|
||||
|
||||
public String getCustomSuffix(TabPlayer player);
|
||||
String getCustomSuffix(TabPlayer player);
|
||||
|
||||
public String getOriginalPrefix(TabPlayer player);
|
||||
String getOriginalPrefix(TabPlayer player);
|
||||
|
||||
public String getOriginalSuffix(TabPlayer player);
|
||||
String getOriginalSuffix(TabPlayer player);
|
||||
}
|
||||
@@ -6,27 +6,27 @@ import me.neznamy.tab.api.TabPlayer;
|
||||
|
||||
public interface UnlimitedNametagManager extends TeamManager {
|
||||
|
||||
public void disableArmorStands(TabPlayer player);
|
||||
void disableArmorStands(TabPlayer player);
|
||||
|
||||
public void enableArmorStands(TabPlayer player);
|
||||
void enableArmorStands(TabPlayer player);
|
||||
|
||||
public boolean hasDisabledArmorStands(TabPlayer player);
|
||||
boolean hasDisabledArmorStands(TabPlayer player);
|
||||
|
||||
public void setName(TabPlayer player, String customname);
|
||||
void setName(TabPlayer player, String customName);
|
||||
|
||||
public void setLine(TabPlayer player, String line, String value);
|
||||
void setLine(TabPlayer player, String line, String value);
|
||||
|
||||
public void resetName(TabPlayer player);
|
||||
void resetName(TabPlayer player);
|
||||
|
||||
public void resetLine(TabPlayer player, String line);
|
||||
void resetLine(TabPlayer player, String line);
|
||||
|
||||
public String getCustomName(TabPlayer player);
|
||||
String getCustomName(TabPlayer player);
|
||||
|
||||
public String getCustomLineValue(TabPlayer player, String line);
|
||||
String getCustomLineValue(TabPlayer player, String line);
|
||||
|
||||
public String getOriginalName(TabPlayer player);
|
||||
String getOriginalName(TabPlayer player);
|
||||
|
||||
public String getOriginalLineValue(TabPlayer player, String line);
|
||||
String getOriginalLineValue(TabPlayer player, String line);
|
||||
|
||||
public List<String> getDefinedLines();
|
||||
List<String> getDefinedLines();
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package me.neznamy.tab.api.util;
|
||||
|
||||
public class Preconditions {
|
||||
|
||||
public static void checkNotNull(Object obj, String exceptionMessage){
|
||||
if (obj == null) throw new IllegalArgumentException(exceptionMessage);
|
||||
}
|
||||
|
||||
public static void checkRange(Number number, Number min, Number max, String variable){
|
||||
if (number.doubleValue() < min.doubleValue() || number.doubleValue() > max.doubleValue())
|
||||
throw new IllegalArgumentException("Number index out of range (" + min + " - " + max + ") for " + variable);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
plugins {
|
||||
id("tab.base-conventions")
|
||||
id("tab.standard-conventions")
|
||||
id("com.github.johnrengelman.shadow")
|
||||
}
|
||||
|
||||
@@ -8,5 +8,6 @@ tasks {
|
||||
archiveFileName.set("TAB-${project.name}-${project.version}.jar")
|
||||
relocate("org.bstats", "me.neznamy.tab.libs.org.bstats")
|
||||
relocate("org.json.simple", "me.neznamy.tab.libs.org.json.simple")
|
||||
relocate("net.kyori.event", "me.neznamy.tab.libs.net.kyori.event")
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
plugins {
|
||||
id("tab.base-conventions")
|
||||
`maven-publish`
|
||||
}
|
||||
|
||||
java {
|
||||
withSourcesJar()
|
||||
withJavadocJar()
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications.create<MavenPublication>("mavenJava") {
|
||||
groupId = rootProject.group as String
|
||||
artifactId = project.name
|
||||
version = rootProject.version as String
|
||||
from(components["java"])
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import gradle.kotlin.dsl.accessors._4cbb0020bd75d48acc42cabded5fdbb7.publishing
|
||||
import org.gradle.api.artifacts.repositories.PasswordCredentials
|
||||
import org.gradle.api.publish.maven.MavenPublication
|
||||
import org.gradle.kotlin.dsl.get
|
||||
import org.gradle.kotlin.dsl.repositories
|
||||
|
||||
plugins {
|
||||
id("tab.base-conventions")
|
||||
`maven-publish`
|
||||
}
|
||||
|
||||
java {
|
||||
withSourcesJar()
|
||||
withJavadocJar()
|
||||
}
|
||||
|
||||
publishing {
|
||||
repositories {
|
||||
maven {
|
||||
name = "krypton"
|
||||
url = uri("https://repo.kryptonmc.org/releases")
|
||||
credentials(PasswordCredentials::class)
|
||||
}
|
||||
}
|
||||
publications.create<MavenPublication>("mavenJava") {
|
||||
groupId = rootProject.group as String
|
||||
artifactId = "tab-${project.name}"
|
||||
version = rootProject.version as String
|
||||
from(components["java"])
|
||||
}
|
||||
}
|
||||
@@ -15,9 +15,15 @@ val platforms = setOf(
|
||||
projects.velocity
|
||||
).map { it.dependencyProject }
|
||||
|
||||
val special = setOf(
|
||||
projects.api,
|
||||
projects.shared
|
||||
).map { it.dependencyProject }
|
||||
|
||||
subprojects {
|
||||
when (this) {
|
||||
in platforms -> plugins.apply("tab.platform-conventions")
|
||||
in special -> plugins.apply("tab.standard-conventions")
|
||||
else -> plugins.apply("tab.base-conventions")
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,6 @@ import me.neznamy.tab.api.protocol.PacketPlayOutPlayerInfo.PlayerInfoData;
|
||||
import me.neznamy.tab.api.protocol.PacketPlayOutPlayerListHeaderFooter;
|
||||
import me.neznamy.tab.api.protocol.PacketPlayOutScoreboardDisplayObjective;
|
||||
import me.neznamy.tab.api.protocol.PacketPlayOutScoreboardObjective;
|
||||
import me.neznamy.tab.api.protocol.PacketPlayOutScoreboardObjective.EnumScoreboardHealthDisplay;
|
||||
import me.neznamy.tab.api.protocol.PacketPlayOutScoreboardScore;
|
||||
import me.neznamy.tab.api.protocol.PacketPlayOutScoreboardTeam;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.NMSStorage;
|
||||
@@ -95,7 +94,7 @@ public class BukkitPacketBuilder extends PacketBuilder {
|
||||
@Override
|
||||
public Object build(PacketPlayOutBoss packet, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
if (nms.getMinorVersion() >= 9 || clientVersion.getMinorVersion() >= 9) {
|
||||
//1.9+ server or client, handled by bukkit api or viaversion
|
||||
//1.9+ server or client, handled by bukkit api or ViaVersion
|
||||
return packet;
|
||||
}
|
||||
//<1.9 client and server
|
||||
@@ -209,9 +208,9 @@ public class BukkitPacketBuilder extends PacketBuilder {
|
||||
nms.ScoreboardTeam_setAllowFriendlyFire.invoke(team, (packet.getOptions() & 0x1) > 0);
|
||||
nms.ScoreboardTeam_setCanSeeFriendlyInvisibles.invoke(team, (packet.getOptions() & 0x2) > 0);
|
||||
if (nms.getMinorVersion() >= 13) {
|
||||
team = createTeamModern(packet, clientVersion, team, prefix, suffix);
|
||||
createTeamModern(packet, clientVersion, team, prefix, suffix);
|
||||
} else {
|
||||
team = createTeamLegacy(packet, team, prefix, suffix);
|
||||
createTeamLegacy(packet, team, prefix, suffix);
|
||||
}
|
||||
if (nms.getMinorVersion() >= 17) {
|
||||
switch (packet.getMethod()) {
|
||||
@@ -234,13 +233,13 @@ public class BukkitPacketBuilder extends PacketBuilder {
|
||||
|
||||
/**
|
||||
* Builds entity destroy packet with given parameter
|
||||
* @param id - entity id to destroy
|
||||
* @return destroy packet
|
||||
* @throws ReflectiveOperationException
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public Object build(PacketPlayOutEntityDestroy packet) throws ReflectiveOperationException {
|
||||
try {
|
||||
return nms.newPacketPlayOutEntityDestroy.newInstance(packet.getEntities());
|
||||
return nms.newPacketPlayOutEntityDestroy.newInstance(new Object[]{packet.getEntities()});
|
||||
} catch (IllegalArgumentException e) {
|
||||
//1.17.0
|
||||
return nms.newPacketPlayOutEntityDestroy.newInstance(packet.getEntities()[0]);
|
||||
@@ -253,13 +252,10 @@ public class BukkitPacketBuilder extends PacketBuilder {
|
||||
|
||||
/**
|
||||
* Builds entity spawn packet with given parameters
|
||||
* @param entityId - entity id
|
||||
* @param uuid - entity uuid
|
||||
* @param entityType - entity type
|
||||
* @param loc - location to spawn at
|
||||
* @param dataWatcher - datawatcher
|
||||
*
|
||||
* @return entity spawn packet
|
||||
* @throws ReflectiveOperationException
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public Object build(PacketPlayOutSpawnEntityLiving packet) throws ReflectiveOperationException {
|
||||
Object nmsPacket;
|
||||
@@ -290,10 +286,9 @@ public class BukkitPacketBuilder extends PacketBuilder {
|
||||
|
||||
/**
|
||||
* Builds entity teleport packet with given parameters
|
||||
* @param entityId - entity id
|
||||
* @param location - location to teleport to
|
||||
* @return entity teleport packet
|
||||
* @throws ReflectiveOperationException
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public Object build(PacketPlayOutEntityTeleport packet) throws ReflectiveOperationException {
|
||||
Object nmsPacket;
|
||||
@@ -317,22 +312,20 @@ public class BukkitPacketBuilder extends PacketBuilder {
|
||||
return nmsPacket;
|
||||
}
|
||||
|
||||
private Object createTeamModern(PacketPlayOutScoreboardTeam packet, ProtocolVersion clientVersion, Object team, String prefix, String suffix) throws ReflectiveOperationException {
|
||||
private void createTeamModern(PacketPlayOutScoreboardTeam packet, ProtocolVersion clientVersion, Object team, String prefix, String suffix) throws ReflectiveOperationException {
|
||||
if (prefix != null) nms.ScoreboardTeam_setPrefix.invoke(team, toNMSComponent(IChatBaseComponent.optimizedComponent(prefix), clientVersion));
|
||||
if (suffix != null) nms.ScoreboardTeam_setSuffix.invoke(team, toNMSComponent(IChatBaseComponent.optimizedComponent(suffix), clientVersion));
|
||||
EnumChatFormat format = packet.getColor() != null ? packet.getColor() : EnumChatFormat.lastColorsOf(prefix);
|
||||
nms.ScoreboardTeam_setColor.invoke(team, nms.EnumChatFormat_values[format.ordinal()]);
|
||||
nms.ScoreboardTeam_setNameTagVisibility.invoke(team, String.valueOf(packet.getNametagVisibility()).equals("always") ? nms.EnumNameTagVisibility_values[0] : nms.EnumNameTagVisibility_values[1]);
|
||||
nms.ScoreboardTeam_setNameTagVisibility.invoke(team, String.valueOf(packet.getNameTagVisibility()).equals("always") ? nms.EnumNameTagVisibility_values[0] : nms.EnumNameTagVisibility_values[1]);
|
||||
nms.ScoreboardTeam_setCollisionRule.invoke(team, String.valueOf(packet.getCollisionRule()).equals("always") ? nms.EnumTeamPush_values[0] : nms.EnumTeamPush_values[1]);
|
||||
return team;
|
||||
}
|
||||
|
||||
private Object createTeamLegacy(PacketPlayOutScoreboardTeam packet, Object team, String prefix, String suffix) throws ReflectiveOperationException {
|
||||
private void createTeamLegacy(PacketPlayOutScoreboardTeam packet, Object team, String prefix, String suffix) throws ReflectiveOperationException {
|
||||
if (prefix != null) nms.ScoreboardTeam_setPrefix.invoke(team, prefix);
|
||||
if (suffix != null) nms.ScoreboardTeam_setSuffix.invoke(team, suffix);
|
||||
if (nms.getMinorVersion() >= 8) nms.ScoreboardTeam_setNameTagVisibility.invoke(team, String.valueOf(packet.getNametagVisibility()).equals("always") ? nms.EnumNameTagVisibility_values[0] : nms.EnumNameTagVisibility_values[1]);
|
||||
if (nms.getMinorVersion() >= 8) nms.ScoreboardTeam_setNameTagVisibility.invoke(team, String.valueOf(packet.getNameTagVisibility()).equals("always") ? nms.EnumNameTagVisibility_values[0] : nms.EnumNameTagVisibility_values[1]);
|
||||
if (nms.getMinorVersion() >= 9) nms.ScoreboardTeam_setCollisionRule.invoke(team, String.valueOf(packet.getCollisionRule()).equals("always") ? nms.EnumTeamPush_values[0] : nms.EnumTeamPush_values[1]);
|
||||
return team;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -341,42 +334,27 @@ public class BukkitPacketBuilder extends PacketBuilder {
|
||||
EnumPlayerInfoAction action = EnumPlayerInfoAction.valueOf(nms.PacketPlayOutPlayerInfo_ACTION.get(nmsPacket).toString());
|
||||
List<PlayerInfoData> listData = new ArrayList<>();
|
||||
for (Object nmsData : (List<?>) nms.PacketPlayOutPlayerInfo_PLAYERS.get(nmsPacket)) {
|
||||
Object nmsGamemode = nms.PlayerInfoData_getGamemode.invoke(nmsData);
|
||||
EnumGamemode gamemode = (nmsGamemode == null) ? null : EnumGamemode.valueOf(nmsGamemode.toString());
|
||||
Object nmsGameMode = nms.PlayerInfoData_getGamemode.invoke(nmsData);
|
||||
EnumGamemode gameMode = (nmsGameMode == null) ? null : EnumGamemode.valueOf(nmsGameMode.toString());
|
||||
GameProfile profile = (GameProfile) nms.PlayerInfoData_getProfile.invoke(nmsData);
|
||||
Object nmsComponent = nms.PlayerInfoData_getDisplayName.invoke(nmsData);
|
||||
IChatBaseComponent listName = nmsComponent == null ? null : fromNMSComponent(nmsComponent);
|
||||
PropertyMap map = new PropertyMap();
|
||||
map.putAll(profile.getProperties());
|
||||
listData.add(new PlayerInfoData(profile.getName(), profile.getId(), map, (int) nms.PlayerInfoData_getLatency.invoke(nmsData), gamemode, listName));
|
||||
listData.add(new PlayerInfoData(profile.getName(), profile.getId(), map, (int) nms.PlayerInfoData_getLatency.invoke(nmsData), gameMode, listName));
|
||||
}
|
||||
return new PacketPlayOutPlayerInfo(action, listData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketPlayOutScoreboardObjective readObjective(Object nmsPacket, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
String objective = (String) nms.PacketPlayOutScoreboardObjective_OBJECTIVENAME.get(nmsPacket);
|
||||
String displayName;
|
||||
Object component = nms.PacketPlayOutScoreboardObjective_DISPLAYNAME.get(nmsPacket);
|
||||
if (nms.getMinorVersion() >= 13) {
|
||||
IChatBaseComponent c = component == null ? null : fromNMSComponent(component);
|
||||
displayName = c == null ? null : c.toLegacyText();
|
||||
} else {
|
||||
displayName = (String) component;
|
||||
}
|
||||
EnumScoreboardHealthDisplay renderType = null;
|
||||
if (nms.getMinorVersion() >= 8) {
|
||||
Object nmsRender = nms.PacketPlayOutScoreboardObjective_RENDERTYPE.get(nmsPacket);
|
||||
if (nmsRender != null) {
|
||||
renderType = EnumScoreboardHealthDisplay.valueOf(nmsRender.toString());
|
||||
}
|
||||
}
|
||||
int method = nms.PacketPlayOutScoreboardObjective_METHOD.getInt(nmsPacket);
|
||||
return new PacketPlayOutScoreboardObjective(method, objective, displayName, renderType);
|
||||
public PacketPlayOutScoreboardObjective readObjective(Object nmsPacket) throws ReflectiveOperationException {
|
||||
return new PacketPlayOutScoreboardObjective(nms.PacketPlayOutScoreboardObjective_METHOD.getInt(nmsPacket),
|
||||
(String) nms.PacketPlayOutScoreboardObjective_OBJECTIVENAME.get(nmsPacket), null, null
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketPlayOutScoreboardDisplayObjective readDisplayObjective(Object nmsPacket, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
public PacketPlayOutScoreboardDisplayObjective readDisplayObjective(Object nmsPacket) throws ReflectiveOperationException {
|
||||
return new PacketPlayOutScoreboardDisplayObjective(
|
||||
nms.PacketPlayOutScoreboardDisplayObjective_POSITION.getInt(nmsPacket),
|
||||
(String) nms.PacketPlayOutScoreboardDisplayObjective_OBJECTIVENAME.get(nmsPacket)
|
||||
@@ -384,11 +362,12 @@ public class BukkitPacketBuilder extends PacketBuilder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds entity bossbar packet
|
||||
* Builds entity BossBar packet
|
||||
* @param packet - packet to build
|
||||
* @param clientVersion - client version
|
||||
* @return entity bossbar packet
|
||||
* @throws ReflectiveOperationException
|
||||
* @return entity BossBar packet
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
private Object buildBossPacketEntity(PacketPlayOutBoss packet, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
if (packet.getOperation() == Action.UPDATE_STYLE) return null; //nothing to do here
|
||||
@@ -415,7 +394,7 @@ public class BukkitPacketBuilder extends PacketBuilder {
|
||||
}
|
||||
|
||||
/**
|
||||
* A method yoinked from minecraft code used to convert double to int
|
||||
* A method taken from minecraft code used to convert double to int
|
||||
* @param paramDouble double value
|
||||
* @return int value
|
||||
*/
|
||||
@@ -425,10 +404,11 @@ public class BukkitPacketBuilder extends PacketBuilder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts minecraft IChatBaseComponent into TAB's component class. Currently does not support show_item hover event on 1.16+.
|
||||
* Converts minecraft IChatBaseComponent into TAB's component class. Currently, does not support show_item hover event on 1.16+.
|
||||
* @param component - component to convert
|
||||
* @return converted component
|
||||
* @throws ReflectiveOperationException
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
private IChatBaseComponent fromNMSComponent(Object component) throws ReflectiveOperationException {
|
||||
if (!nms.ChatComponentText.isInstance(component)) return null; //paper
|
||||
@@ -484,11 +464,12 @@ public class BukkitPacketBuilder extends PacketBuilder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts TAB's IChatBaseComponent into minecraft's component. Currently does not support hover event.
|
||||
* Converts TAB's IChatBaseComponent into minecraft's component. Currently, does not support hover event.
|
||||
* @param component - component to convert
|
||||
* @param clientVersion - client version used to decide RGB conversion
|
||||
* @return converted component
|
||||
* @throws ReflectiveOperationException
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public Object toNMSComponent(IChatBaseComponent component, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
Object obj;
|
||||
|
||||
@@ -13,6 +13,7 @@ import me.neznamy.tab.shared.TabConstants;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.features.NickCompatibility;
|
||||
import me.neznamy.tab.shared.features.PipelineInjector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class BukkitPipelineInjector extends PipelineInjector {
|
||||
|
||||
@@ -33,7 +34,7 @@ public class BukkitPipelineInjector extends PipelineInjector {
|
||||
public class BukkitChannelDuplexHandler extends ChannelDuplexHandler {
|
||||
|
||||
//injected player
|
||||
private TabPlayer player;
|
||||
private final TabPlayer player;
|
||||
|
||||
/**
|
||||
* Constructs new instance with given player
|
||||
@@ -44,7 +45,7 @@ public class BukkitPipelineInjector extends PipelineInjector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext context, Object packet) {
|
||||
public void channelRead(@NotNull ChannelHandlerContext context, @NotNull Object packet) {
|
||||
try {
|
||||
if (TAB.getInstance().getFeatureManager().onPacketReceive(player, packet)) return;
|
||||
super.channelRead(context, packet);
|
||||
@@ -65,8 +66,8 @@ public class BukkitPipelineInjector extends PipelineInjector {
|
||||
super.write(context, packet, channelPromise);
|
||||
return;
|
||||
}
|
||||
if (nms.PacketPlayOutScoreboardDisplayObjective.isInstance(packet) && TAB.getInstance().getFeatureManager().onDisplayObjective(player, packet)) {
|
||||
return;
|
||||
if (nms.PacketPlayOutScoreboardDisplayObjective.isInstance(packet)){
|
||||
TAB.getInstance().getFeatureManager().onDisplayObjective(player, packet);
|
||||
}
|
||||
if (nms.PacketPlayOutScoreboardObjective.isInstance(packet)) {
|
||||
TAB.getInstance().getFeatureManager().onObjective(player, packet);
|
||||
@@ -85,7 +86,8 @@ public class BukkitPipelineInjector extends PipelineInjector {
|
||||
/**
|
||||
* Removes all real players from team if packet does not come from TAB and reports this to override log
|
||||
* @param packetPlayOutScoreboardTeam - team packet
|
||||
* @throws ReflectiveOperationException
|
||||
* @throws ReflectiveOperationException
|
||||
* nmsGameMode
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private void modifyPlayers(Object packetPlayOutScoreboardTeam) throws ReflectiveOperationException {
|
||||
@@ -109,7 +111,7 @@ public class BukkitPipelineInjector extends PipelineInjector {
|
||||
}
|
||||
}
|
||||
nms.setField(packetPlayOutScoreboardTeam, nms.PacketPlayOutScoreboardTeam_PLAYERS, newList);
|
||||
TAB.getInstance().getCPUManager().addTime("Nametags", TabConstants.CpuUsageCategory.ANTI_OVERRIDE, System.nanoTime()-time);
|
||||
TAB.getInstance().getCPUManager().addTime("NameTags", TabConstants.CpuUsageCategory.ANTI_OVERRIDE, System.nanoTime()-time);
|
||||
}
|
||||
|
||||
private TabPlayer getPlayer(String name) {
|
||||
@@ -119,9 +121,8 @@ public class BukkitPipelineInjector extends PipelineInjector {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private String getName(TabPlayer p) {
|
||||
return ((NickCompatibility) TAB.getInstance().getFeatureManager().getFeature("nick")).getNickname(p);
|
||||
return ((NickCompatibility) TAB.getInstance().getFeatureManager().getFeature(TabConstants.Feature.NICK_COMPATIBILITY)).getNickname(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
+23
-11
@@ -1,6 +1,8 @@
|
||||
package me.neznamy.tab.platforms.bukkit;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.math.RoundingMode;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.NumberFormat;
|
||||
@@ -45,6 +47,7 @@ public class BukkitPlaceholderRegistry implements PlaceholderRegistry {
|
||||
private boolean paperTps;
|
||||
private boolean paperMspt;
|
||||
private boolean purpur;
|
||||
private Method playerIsAfk;
|
||||
|
||||
private Listener healthListener = null;
|
||||
|
||||
@@ -82,7 +85,7 @@ public class BukkitPlaceholderRegistry implements PlaceholderRegistry {
|
||||
//not paper
|
||||
}
|
||||
try {
|
||||
Player.class.getMethod("isAfk");
|
||||
playerIsAfk = Player.class.getMethod("isAfk");
|
||||
purpur = true;
|
||||
} catch (NoSuchMethodException e) {
|
||||
//not purpur
|
||||
@@ -92,11 +95,10 @@ public class BukkitPlaceholderRegistry implements PlaceholderRegistry {
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void registerPlaceholders(PlaceholderManager manager) {
|
||||
NumberFormat roundDown = NumberFormat.getInstance();
|
||||
NumberFormat roundDown = NumberFormat.getNumberInstance(Locale.ENGLISH);
|
||||
roundDown.setRoundingMode(RoundingMode.DOWN);
|
||||
roundDown.setMaximumFractionDigits(2);
|
||||
manager.registerPlayerPlaceholder("%displayname%", 500, p -> ((Player) p.getPlayer()).getDisplayName());
|
||||
manager.registerPlayerPlaceholder("%vanished%", 1000, TabPlayer::isVanished);
|
||||
if (paperTps) {
|
||||
manager.registerServerPlaceholder("%tps%", 1000, () -> formatTPS(Bukkit.getTPS()[0]));
|
||||
} else if (recentTps != null) {
|
||||
@@ -115,7 +117,19 @@ public class BukkitPlaceholderRegistry implements PlaceholderRegistry {
|
||||
}
|
||||
manager.registerPlayerPlaceholder("%afk%", 500, p -> {
|
||||
if (essentials != null && ((Essentials)essentials).getUser(p.getUniqueId()).isAfk()) return true;
|
||||
return purpur && ((Player)p.getPlayer()).isAfk();
|
||||
if (!purpur || playerIsAfk == null) return false;
|
||||
try {
|
||||
return playerIsAfk.invoke(p.getPlayer());
|
||||
} catch (final IllegalAccessException | InvocationTargetException exception) {
|
||||
TAB.getInstance().getErrorManager().printError("Failed to invoke isAfk!", exception);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
manager.registerPlayerPlaceholder("%essentialsnick%", 1000, p -> {
|
||||
String nickname = null;
|
||||
if (essentials != null)
|
||||
nickname = ((Essentials)essentials).getUser(p.getUniqueId()).getNickname();
|
||||
return nickname == null || nickname.length() == 0 ? p.getName() : nickname;
|
||||
});
|
||||
if (chat != null) {
|
||||
manager.registerPlayerPlaceholder("%vault-prefix%", 500, p -> ((Chat) chat).getPlayerPrefix((Player) p.getPlayer()));
|
||||
@@ -133,13 +147,13 @@ public class BukkitPlaceholderRegistry implements PlaceholderRegistry {
|
||||
}
|
||||
|
||||
private void registerOnlinePlaceholders(PlaceholderManager manager) {
|
||||
manager.registerPlayerPlaceholder("%online%", -1, p -> {
|
||||
manager.registerPlayerPlaceholder("%online%", 1000, p -> {
|
||||
int count = 0;
|
||||
for (TabPlayer all : TAB.getInstance().getOnlinePlayers()){
|
||||
if (((Player) p.getPlayer()).canSee((Player) all.getPlayer())) count++;
|
||||
}
|
||||
return count;
|
||||
}).enableTriggerMode();
|
||||
});
|
||||
manager.registerPlayerPlaceholder("%staffonline%", 2000, p -> {
|
||||
int count = 0;
|
||||
for (TabPlayer all : TAB.getInstance().getOnlinePlayers()){
|
||||
@@ -185,13 +199,11 @@ public class BukkitPlaceholderRegistry implements PlaceholderRegistry {
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
|
||||
public void onRespawn(PlayerRespawnEvent e) {
|
||||
health.updateValue(TAB.getInstance().getPlayer(e.getPlayer().getUniqueId()), e.getPlayer().getMaxHealth());
|
||||
health.updateValue(TAB.getInstance().getPlayer(e.getPlayer().getUniqueId()), (int) e.getPlayer().getMaxHealth());
|
||||
}
|
||||
};
|
||||
Bukkit.getPluginManager().registerEvents(healthListener, plugin);
|
||||
}, () -> {
|
||||
HandlerList.unregisterAll(healthListener);
|
||||
});
|
||||
}, () -> HandlerList.unregisterAll(healthListener));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import java.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import me.neznamy.tab.shared.TabConstants;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
@@ -18,7 +19,7 @@ import me.neznamy.tab.api.chat.EnumChatFormat;
|
||||
import me.neznamy.tab.api.protocol.PacketBuilder;
|
||||
import me.neznamy.tab.platforms.bukkit.event.TabLoadEvent;
|
||||
import me.neznamy.tab.platforms.bukkit.event.TabPlayerLoadEvent;
|
||||
import me.neznamy.tab.platforms.bukkit.features.PerWorldPlayerlist;
|
||||
import me.neznamy.tab.platforms.bukkit.features.PerWorldPlayerList;
|
||||
import me.neznamy.tab.platforms.bukkit.features.PetFix;
|
||||
import me.neznamy.tab.platforms.bukkit.features.TabExpansion;
|
||||
import me.neznamy.tab.platforms.bukkit.features.WitherBossBar;
|
||||
@@ -36,9 +37,10 @@ import me.neznamy.tab.shared.permission.UltraPermissions;
|
||||
import me.neznamy.tab.shared.placeholders.PlayerPlaceholderImpl;
|
||||
import me.neznamy.tab.shared.placeholders.UniversalPlaceholderRegistry;
|
||||
import net.milkbowl.vault.permission.Permission;
|
||||
import org.bukkit.plugin.RegisteredServiceProvider;
|
||||
|
||||
/**
|
||||
* Bukkit implementation of Platform
|
||||
* Bukkit's implementation of Platform interface
|
||||
*/
|
||||
public class BukkitPlatform implements Platform {
|
||||
|
||||
@@ -49,9 +51,7 @@ public class BukkitPlatform implements Platform {
|
||||
|
||||
//booleans to check plugin presence
|
||||
private boolean placeholderAPI;
|
||||
private boolean viaversion;
|
||||
private boolean idisguise;
|
||||
private boolean libsdisguises;
|
||||
private boolean libsDisguises;
|
||||
private Plugin essentials;
|
||||
|
||||
/**
|
||||
@@ -69,7 +69,9 @@ public class BukkitPlatform implements Platform {
|
||||
} else if (Bukkit.getPluginManager().isPluginEnabled("UltraPermissions")) {
|
||||
return new UltraPermissions(getPluginVersion("UltraPermissions"));
|
||||
} else if (Bukkit.getPluginManager().isPluginEnabled("Vault")) {
|
||||
return new Vault(Bukkit.getServicesManager().getRegistration(Permission.class).getProvider(), getPluginVersion("Vault"));
|
||||
RegisteredServiceProvider<Permission> provider = Bukkit.getServicesManager().getRegistration(Permission.class);
|
||||
if (provider == null) return new None();
|
||||
return new Vault(provider.getProvider(), getPluginVersion("Vault"));
|
||||
} else {
|
||||
return new None();
|
||||
}
|
||||
@@ -80,7 +82,6 @@ public class BukkitPlatform implements Platform {
|
||||
if (Bukkit.getPluginManager().isPluginEnabled("ViaVersion")) {
|
||||
try {
|
||||
Class.forName("com.viaversion.viaversion.api.Via");
|
||||
viaversion = true;
|
||||
} catch (ClassNotFoundException e) {
|
||||
TAB.getInstance().sendConsoleMessage("&c[TAB] An outdated version of ViaVersion (" + getPluginVersion("ViaVersion") + ") was detected.", true);
|
||||
TAB.getInstance().sendConsoleMessage("&c[TAB] TAB only supports ViaVersion 4.0.0 and above. Disabling ViaVersion hook.", true);
|
||||
@@ -91,24 +92,26 @@ public class BukkitPlatform implements Platform {
|
||||
TAB.getInstance().sendConsoleMessage("&c[TAB] Detected plugin \"Tablisknu\", which causes TAB to not work properly. Consider removing the plugin.", true);
|
||||
}
|
||||
placeholderAPI = Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI");
|
||||
idisguise = Bukkit.getPluginManager().isPluginEnabled("iDisguise");
|
||||
libsdisguises = Bukkit.getPluginManager().isPluginEnabled("LibsDisguises");
|
||||
libsDisguises = Bukkit.getPluginManager().isPluginEnabled("LibsDisguises");
|
||||
essentials = Bukkit.getPluginManager().getPlugin("Essentials");
|
||||
TAB tab = TAB.getInstance();
|
||||
if (tab.getConfiguration().isPipelineInjection()) tab.getFeatureManager().registerFeature("injection", new BukkitPipelineInjector());
|
||||
if (tab.getConfiguration().isPipelineInjection())
|
||||
tab.getFeatureManager().registerFeature(TabConstants.Feature.PIPELINE_INJECTION, new BukkitPipelineInjector());
|
||||
new BukkitPlaceholderRegistry(plugin).registerPlaceholders(tab.getPlaceholderManager());
|
||||
new UniversalPlaceholderRegistry().registerPlaceholders(tab.getPlaceholderManager());
|
||||
loadNametagFeature(tab);
|
||||
loadNameTagFeature(tab);
|
||||
tab.loadUniversalFeatures();
|
||||
if (tab.getConfiguration().getConfig().getBoolean("bossbar.enabled", false)) {
|
||||
if (tab.getServerVersion().getMinorVersion() < 9) {
|
||||
tab.getFeatureManager().registerFeature("bossbar", new WitherBossBar(plugin));
|
||||
tab.getFeatureManager().registerFeature(TabConstants.Feature.BOSS_BAR, new WitherBossBar(plugin));
|
||||
} else {
|
||||
tab.getFeatureManager().registerFeature("bossbar", new BossBarManagerImpl());
|
||||
tab.getFeatureManager().registerFeature(TabConstants.Feature.BOSS_BAR, new BossBarManagerImpl());
|
||||
}
|
||||
}
|
||||
if (tab.getServerVersion().getMinorVersion() >= 9 && tab.getConfiguration().getConfig().getBoolean("fix-pet-names.enabled", false)) tab.getFeatureManager().registerFeature("petfix", new PetFix());
|
||||
if (tab.getConfiguration().getConfig().getBoolean("per-world-playerlist.enabled", false)) tab.getFeatureManager().registerFeature("pwp", new PerWorldPlayerlist(plugin));
|
||||
if (tab.getServerVersion().getMinorVersion() >= 9 && tab.getConfiguration().getConfig().getBoolean("fix-pet-names.enabled", false))
|
||||
tab.getFeatureManager().registerFeature(TabConstants.Feature.PET_FIX, new PetFix());
|
||||
if (tab.getConfiguration().getConfig().getBoolean("per-world-playerlist.enabled", false))
|
||||
tab.getFeatureManager().registerFeature(TabConstants.Feature.PER_WORLD_PLAYER_LIST, new PerWorldPlayerList(plugin));
|
||||
if (placeholderAPI) {
|
||||
new TabExpansion(plugin);
|
||||
}
|
||||
@@ -118,19 +121,20 @@ public class BukkitPlatform implements Platform {
|
||||
}
|
||||
|
||||
private String getPluginVersion(String plugin) {
|
||||
return Bukkit.getPluginManager().getPlugin(plugin).getDescription().getVersion();
|
||||
Plugin pl = Bukkit.getPluginManager().getPlugin(plugin);
|
||||
return pl == null ? "" : pl.getDescription().getVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads nametag feature from config
|
||||
* Loads NameTag feature from config
|
||||
* @param tab - tab instance
|
||||
*/
|
||||
private void loadNametagFeature(TAB tab) {
|
||||
private void loadNameTagFeature(TAB tab) {
|
||||
if (tab.getConfiguration().getConfig().getBoolean("scoreboard-teams.enabled", true)) {
|
||||
if (tab.getConfiguration().getConfig().getBoolean("scoreboard-teams.unlimited-nametag-mode.enabled", false) && tab.getServerVersion().getMinorVersion() >= 8) {
|
||||
tab.getFeatureManager().registerFeature("nametagx", new NameTagX(plugin));
|
||||
tab.getFeatureManager().registerFeature(TabConstants.Feature.UNLIMITED_NAME_TAGS, new NameTagX(plugin));
|
||||
} else {
|
||||
tab.getFeatureManager().registerFeature("nametag16", new NameTag());
|
||||
tab.getFeatureManager().registerFeature(TabConstants.Feature.NAME_TAGS, new NameTag());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -182,11 +186,12 @@ public class BukkitPlatform implements Platform {
|
||||
long time = System.nanoTime();
|
||||
String syncedPlaceholder = identifier.substring(6, identifier.length()-1);
|
||||
String value = placeholderAPI ? PlaceholderAPI.setPlaceholders((Player) p.getPlayer(), "%" + syncedPlaceholder + "%") : identifier;
|
||||
getLastValues().put(p.getName(), value);
|
||||
if (!getForceUpdate().contains(p.getName())) getForceUpdate().add(p.getName());
|
||||
getLastValues().put(p, value);
|
||||
getForceUpdate().add(p);
|
||||
TAB.getInstance().getCPUManager().addPlaceholderTime(getIdentifier(), System.nanoTime()-time);
|
||||
});
|
||||
return getLastValues().get(p.getName());
|
||||
String value = getLastValues().get(p);
|
||||
return value == null ? identifier : value;
|
||||
}
|
||||
});
|
||||
return;
|
||||
@@ -227,20 +232,12 @@ public class BukkitPlatform implements Platform {
|
||||
return Bukkit.getMaxPlayers();
|
||||
}
|
||||
|
||||
public boolean isViaversionEnabled() {
|
||||
return viaversion;
|
||||
}
|
||||
|
||||
public boolean isLibsdisguisesEnabled() {
|
||||
return libsdisguises;
|
||||
public boolean isLibsDisguisesEnabled() {
|
||||
return libsDisguises;
|
||||
}
|
||||
|
||||
public void setLibsdisguisesEnabled(boolean enabled) {
|
||||
libsdisguises = enabled;
|
||||
}
|
||||
|
||||
public boolean isIdisguiseEnabled() {
|
||||
return idisguise;
|
||||
public void setLibsDisguisesEnabled(boolean enabled) {
|
||||
libsDisguises = enabled;
|
||||
}
|
||||
|
||||
public Essentials getEssentials() {
|
||||
|
||||
@@ -42,8 +42,8 @@ public class BukkitTabPlayer extends ITabPlayer {
|
||||
private Object playerConnection;
|
||||
|
||||
//player's visible boss bars
|
||||
private final Map<UUID, BossBar> bossbars = new HashMap<>();
|
||||
private final Map<UUID, com.viaversion.viaversion.api.legacy.bossbar.BossBar> viaBossbars = new HashMap<>();
|
||||
private final Map<UUID, BossBar> bossBars = new HashMap<>();
|
||||
private final Map<UUID, com.viaversion.viaversion.api.legacy.bossbar.BossBar> viaBossBars = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameter
|
||||
@@ -102,36 +102,38 @@ public class BukkitTabPlayer extends ITabPlayer {
|
||||
}
|
||||
|
||||
private void handle(PacketPlayOutBoss packet) {
|
||||
BossBar bar;
|
||||
switch (packet.getOperation()) {
|
||||
case ADD:
|
||||
if (bossbars.containsKey(packet.getId())) return;
|
||||
bar = Bukkit.createBossBar(RGBUtils.getInstance().convertToBukkitFormat(packet.getName(), getVersion().getMinorVersion() >= 16 && TAB.getInstance().getServerVersion().getMinorVersion() >= 16),
|
||||
BarColor.valueOf(packet.getColor().name()),
|
||||
BossBar bar = bossBars.get(packet.getId());
|
||||
if (packet.getOperation() == PacketPlayOutBoss.Action.ADD) {
|
||||
if (bossBars.containsKey(packet.getId())) return;
|
||||
bar = Bukkit.createBossBar(RGBUtils.getInstance().convertToBukkitFormat(packet.getName(), getVersion().getMinorVersion() >= 16 && TAB.getInstance().getServerVersion().getMinorVersion() >= 16),
|
||||
BarColor.valueOf(packet.getColor().name()),
|
||||
BarStyle.valueOf(packet.getOverlay().getBukkitName()));
|
||||
if (packet.isCreateWorldFog()) bar.addFlag(BarFlag.CREATE_FOG);
|
||||
if (packet.isDarkenScreen()) bar.addFlag(BarFlag.DARKEN_SKY);
|
||||
if (packet.isPlayMusic()) bar.addFlag(BarFlag.PLAY_BOSS_MUSIC);
|
||||
bar.setProgress(packet.getPct());
|
||||
bossbars.put(packet.getId(), bar);
|
||||
bossBars.put(packet.getId(), bar);
|
||||
bar.addPlayer(getPlayer());
|
||||
break;
|
||||
return;
|
||||
}
|
||||
if (bar == null) return; //no idea how
|
||||
switch (packet.getOperation()) {
|
||||
case REMOVE:
|
||||
bossbars.get(packet.getId()).removePlayer(getPlayer());
|
||||
bossbars.remove(packet.getId());
|
||||
bar.removePlayer(getPlayer());
|
||||
bossBars.remove(packet.getId());
|
||||
break;
|
||||
case UPDATE_PCT:
|
||||
bossbars.get(packet.getId()).setProgress(packet.getPct());
|
||||
bar.setProgress(packet.getPct());
|
||||
break;
|
||||
case UPDATE_NAME:
|
||||
bossbars.get(packet.getId()).setTitle(RGBUtils.getInstance().convertToBukkitFormat(packet.getName(), getVersion().getMinorVersion() >= 16 && TAB.getInstance().getServerVersion().getMinorVersion() >= 16));
|
||||
bar.setTitle(RGBUtils.getInstance().convertToBukkitFormat(packet.getName(), getVersion().getMinorVersion() >= 16 && TAB.getInstance().getServerVersion().getMinorVersion() >= 16));
|
||||
break;
|
||||
case UPDATE_STYLE:
|
||||
bossbars.get(packet.getId()).setColor(BarColor.valueOf(packet.getColor().name()));
|
||||
bossbars.get(packet.getId()).setStyle(BarStyle.valueOf(packet.getOverlay().getBukkitName()));
|
||||
bar.setColor(BarColor.valueOf(packet.getColor().name()));
|
||||
bar.setStyle(BarStyle.valueOf(packet.getOverlay().getBukkitName()));
|
||||
break;
|
||||
case UPDATE_PROPERTIES:
|
||||
bar = bossbars.get(packet.getId());
|
||||
bar = bossBars.get(packet.getId());
|
||||
processFlag(bar, packet.isCreateWorldFog(), BarFlag.CREATE_FOG);
|
||||
processFlag(bar, packet.isDarkenScreen(), BarFlag.DARKEN_SKY);
|
||||
processFlag(bar, packet.isPlayMusic(), BarFlag.PLAY_BOSS_MUSIC);
|
||||
@@ -145,7 +147,7 @@ public class BukkitTabPlayer extends ITabPlayer {
|
||||
com.viaversion.viaversion.api.legacy.bossbar.BossBar bar;
|
||||
switch (packet.getOperation()) {
|
||||
case ADD:
|
||||
if (viaBossbars.containsKey(packet.getId())) return;
|
||||
if (viaBossBars.containsKey(packet.getId())) return;
|
||||
bar = Via.getAPI().legacyAPI().createLegacyBossBar(RGBUtils.getInstance().convertToBukkitFormat(packet.getName(), getVersion().getMinorVersion() >= 16),
|
||||
packet.getPct(),
|
||||
BossColor.valueOf(packet.getColor().name()),
|
||||
@@ -153,25 +155,25 @@ public class BukkitTabPlayer extends ITabPlayer {
|
||||
//fog missing from via API
|
||||
if (packet.isDarkenScreen()) bar.addFlag(BossFlag.DARKEN_SKY);
|
||||
if (packet.isPlayMusic()) bar.addFlag(BossFlag.PLAY_BOSS_MUSIC);
|
||||
viaBossbars.put(packet.getId(), bar);
|
||||
viaBossBars.put(packet.getId(), bar);
|
||||
bar.addPlayer(getPlayer().getUniqueId());
|
||||
break;
|
||||
case REMOVE:
|
||||
viaBossbars.get(packet.getId()).removePlayer(getPlayer().getUniqueId());
|
||||
viaBossbars.remove(packet.getId());
|
||||
viaBossBars.get(packet.getId()).removePlayer(getPlayer().getUniqueId());
|
||||
viaBossBars.remove(packet.getId());
|
||||
break;
|
||||
case UPDATE_PCT:
|
||||
viaBossbars.get(packet.getId()).setHealth(packet.getPct());
|
||||
viaBossBars.get(packet.getId()).setHealth(packet.getPct());
|
||||
break;
|
||||
case UPDATE_NAME:
|
||||
viaBossbars.get(packet.getId()).setTitle(RGBUtils.getInstance().convertToBukkitFormat(packet.getName(), getVersion().getMinorVersion() >= 16));
|
||||
viaBossBars.get(packet.getId()).setTitle(RGBUtils.getInstance().convertToBukkitFormat(packet.getName(), getVersion().getMinorVersion() >= 16));
|
||||
break;
|
||||
case UPDATE_STYLE:
|
||||
viaBossbars.get(packet.getId()).setColor(BossColor.valueOf(packet.getColor().name()));
|
||||
viaBossbars.get(packet.getId()).setStyle(BossStyle.valueOf(packet.getOverlay().getBukkitName()));
|
||||
viaBossBars.get(packet.getId()).setColor(BossColor.valueOf(packet.getColor().name()));
|
||||
viaBossBars.get(packet.getId()).setStyle(BossStyle.valueOf(packet.getOverlay().getBukkitName()));
|
||||
break;
|
||||
case UPDATE_PROPERTIES:
|
||||
bar = viaBossbars.get(packet.getId());
|
||||
bar = viaBossBars.get(packet.getId());
|
||||
//fog missing from via API
|
||||
processFlagVia(bar, packet.isDarkenScreen(), BossFlag.DARKEN_SKY);
|
||||
processFlagVia(bar, packet.isPlayMusic(), BossFlag.PLAY_BOSS_MUSIC);
|
||||
@@ -213,12 +215,12 @@ public class BukkitTabPlayer extends ITabPlayer {
|
||||
@Override
|
||||
public boolean isDisguised() {
|
||||
try {
|
||||
if (!((BukkitPlatform)TAB.getInstance().getPlatform()).isLibsdisguisesEnabled()) return false;
|
||||
if (!((BukkitPlatform)TAB.getInstance().getPlatform()).isLibsDisguisesEnabled()) return false;
|
||||
return DisguiseAPI.isDisguised(getPlayer());
|
||||
} catch (NoClassDefFoundError | ExceptionInInitializerError e) {
|
||||
} catch (LinkageError e) {
|
||||
//java.lang.NoClassDefFoundError: Could not initialize class me.libraryaddict.disguise.DisguiseAPI
|
||||
TAB.getInstance().getErrorManager().printError("Failed to check disguise status using LibsDisguises", e);
|
||||
((BukkitPlatform)TAB.getInstance().getPlatform()).setLibsdisguisesEnabled(false);
|
||||
((BukkitPlatform)TAB.getInstance().getPlatform()).setLibsDisguisesEnabled(false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -256,4 +258,4 @@ public class BukkitTabPlayer extends ITabPlayer {
|
||||
public int getGamemode() {
|
||||
return getPlayer().getGameMode().getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,11 +7,9 @@ import java.util.List;
|
||||
import org.bstats.bukkit.Metrics;
|
||||
import org.bstats.charts.SimplePie;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
import org.bukkit.command.*;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
@@ -22,14 +20,15 @@ import me.neznamy.tab.api.chat.EnumChatFormat;
|
||||
import me.neznamy.tab.platforms.bukkit.nms.NMSStorage;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.TabConstants;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Main class for Bukkit platform
|
||||
*/
|
||||
public class Main extends JavaPlugin {
|
||||
|
||||
private boolean viaversion;
|
||||
private boolean protocolsupport;
|
||||
private boolean viaVersion;
|
||||
private boolean protocolSupport;
|
||||
|
||||
@Override
|
||||
public void onEnable(){
|
||||
@@ -38,22 +37,24 @@ public class Main extends JavaPlugin {
|
||||
Bukkit.getPluginManager().disablePlugin(this);
|
||||
return;
|
||||
}
|
||||
viaversion = Bukkit.getPluginManager().isPluginEnabled("ViaVersion");
|
||||
protocolsupport = Bukkit.getPluginManager().isPluginEnabled("ProtocolSupport");
|
||||
viaVersion = Bukkit.getPluginManager().isPluginEnabled("ViaVersion");
|
||||
protocolSupport = Bukkit.getPluginManager().isPluginEnabled("ProtocolSupport");
|
||||
TAB.setInstance(new TAB(new BukkitPlatform(this), ProtocolVersion.fromFriendlyName(Bukkit.getBukkitVersion().split("-")[0])));
|
||||
if (TAB.getInstance().getServerVersion() == ProtocolVersion.UNKNOWN) {
|
||||
Bukkit.getConsoleSender().sendMessage(EnumChatFormat.color("&c[TAB] Unknown server version: " + Bukkit.getBukkitVersion() + "! Plugin may not work correctly."));
|
||||
}
|
||||
Bukkit.getPluginManager().registerEvents(new BukkitEventListener(this), this);
|
||||
TABCommand command = new TABCommand();
|
||||
Bukkit.getPluginCommand("tab").setExecutor(command);
|
||||
Bukkit.getPluginCommand("tab").setTabCompleter(command);
|
||||
TAB.getInstance().load();
|
||||
Metrics metrics = new Metrics(this, 5304);
|
||||
metrics.addCustomChart(new SimplePie("unlimited_nametag_mode_enabled", () -> TAB.getInstance().getFeatureManager().isFeatureEnabled("nametagx") ? "Yes" : "No"));
|
||||
metrics.addCustomChart(new SimplePie("unlimited_nametag_mode_enabled", () -> TAB.getInstance().getFeatureManager().isFeatureEnabled(TabConstants.Feature.UNLIMITED_NAME_TAGS) ? "Yes" : "No"));
|
||||
metrics.addCustomChart(new SimplePie("placeholderapi", () -> Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI") ? "Yes" : "No"));
|
||||
metrics.addCustomChart(new SimplePie("permission_system", () -> TAB.getInstance().getGroupManager().getPlugin().getName()));
|
||||
metrics.addCustomChart(new SimplePie("server_version", () -> "1." + TAB.getInstance().getServerVersion().getMinorVersion() + ".x"));
|
||||
PluginCommand cmd = Bukkit.getPluginCommand("tab");
|
||||
if (cmd == null) return;
|
||||
TABCommand command = new TABCommand();
|
||||
cmd.setExecutor(command);
|
||||
cmd.setTabCompleter(command);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -101,12 +102,12 @@ public class Main extends JavaPlugin {
|
||||
* @return protocol version of this player
|
||||
*/
|
||||
public int getProtocolVersion(Player player) {
|
||||
if (protocolsupport){
|
||||
if (protocolSupport){
|
||||
int version = getProtocolVersionPS(player);
|
||||
//some PS versions return -1 on unsupported server versions instead of throwing exception
|
||||
if (version != -1 && version < TAB.getInstance().getServerVersion().getNetworkId()) return version;
|
||||
}
|
||||
if (viaversion) {
|
||||
if (viaVersion) {
|
||||
return getProtocolVersionVia(player, 0);
|
||||
}
|
||||
return TAB.getInstance().getServerVersion().getNetworkId();
|
||||
@@ -149,16 +150,17 @@ public class Main extends JavaPlugin {
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
return -1;
|
||||
} catch (Exception | NoClassDefFoundError e) {
|
||||
TAB.getInstance().getErrorManager().printError(String.format("Failed to get protocol version of %s using ViaVersion v%s", player.getName(), Bukkit.getPluginManager().getPlugin("ViaVersion").getDescription().getVersion()), e);
|
||||
} catch (Exception | LinkageError e) {
|
||||
Plugin via = Bukkit.getPluginManager().getPlugin("ViaVersion");
|
||||
TAB.getInstance().getErrorManager().printError(String.format("Failed to get protocol version of %s using ViaVersion v%s", player.getName(), via == null ? "" : via.getDescription().getVersion()), e);
|
||||
return TAB.getInstance().getServerVersion().getNetworkId();
|
||||
}
|
||||
}
|
||||
|
||||
public class TABCommand implements CommandExecutor, TabCompleter {
|
||||
public static class TABCommand implements CommandExecutor, TabCompleter {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) {
|
||||
if (TAB.getInstance().isDisabled()) {
|
||||
for (String message : TAB.getInstance().getDisabledCommand().execute(args, sender.hasPermission(TabConstants.Permission.COMMAND_RELOAD), sender.hasPermission(TabConstants.Permission.COMMAND_ALL))) {
|
||||
sender.sendMessage(EnumChatFormat.color(message));
|
||||
@@ -175,7 +177,7 @@ public class Main extends JavaPlugin {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, String[] args) {
|
||||
TabPlayer p = null;
|
||||
if (sender instanceof Player) {
|
||||
p = TAB.getInstance().getPlayer(((Player)sender).getUniqueId());
|
||||
|
||||
@@ -2,21 +2,25 @@ package me.neznamy.tab.platforms.bukkit.event;
|
||||
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Bukkit event that is called each time TAB fully loads. This includes server startup, reload,
|
||||
* /tab reload and /plugman reload tab
|
||||
*
|
||||
* @deprecated for removal, use {@link me.neznamy.tab.api.event.plugin.TabLoadEvent}
|
||||
*/
|
||||
@Deprecated
|
||||
public class TabLoadEvent extends Event {
|
||||
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers(){
|
||||
public @NotNull HandlerList getHandlers(){
|
||||
return getHandlerList();
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,10 +4,14 @@ import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Bukkit event that is called when player is successfully loaded after joining. This also includes plugin reloading.
|
||||
*
|
||||
* @deprecated for removal, use {@link me.neznamy.tab.api.event.player.PlayerLoadEvent}
|
||||
*/
|
||||
@Deprecated
|
||||
public class TabPlayerLoadEvent extends Event {
|
||||
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
@@ -19,7 +23,7 @@ public class TabPlayerLoadEvent extends Event {
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers(){
|
||||
public @NotNull HandlerList getHandlers(){
|
||||
return getHandlerList();
|
||||
}
|
||||
|
||||
@@ -30,4 +34,4 @@ public class TabPlayerLoadEvent extends Event {
|
||||
public TabPlayer getPlayer() {
|
||||
return player;
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -19,10 +19,10 @@ import me.neznamy.tab.shared.TabConstants;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
|
||||
/**
|
||||
* Per-world-playerlist feature handler
|
||||
* Per-world-PlayerList feature handler
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class PerWorldPlayerlist extends TabFeature implements Listener {
|
||||
public class PerWorldPlayerList extends TabFeature implements Listener {
|
||||
|
||||
//plugin instance
|
||||
private final JavaPlugin plugin;
|
||||
@@ -36,10 +36,10 @@ public class PerWorldPlayerlist extends TabFeature implements Listener {
|
||||
* Constructs new instance with given parameters and loads config options
|
||||
* @param plugin - plugin instance
|
||||
*/
|
||||
public PerWorldPlayerlist(JavaPlugin plugin) {
|
||||
super("Per world playerlist", null);
|
||||
public PerWorldPlayerList(JavaPlugin plugin) {
|
||||
super("Per world PlayerList", null);
|
||||
this.plugin = plugin;
|
||||
TAB.getInstance().debug(String.format("Loaded PerWorldPlayerlist feature with parameters allowBypass=%s, ignoredWorlds=%s, sharedWorlds=%s", allowBypass, ignoredWorlds, sharedWorlds));
|
||||
TAB.getInstance().debug(String.format("Loaded PerWorldPlayerList feature with parameters allowBypass=%s, ignoredWorlds=%s, sharedWorlds=%s", allowBypass, ignoredWorlds, sharedWorlds));
|
||||
Bukkit.getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package me.neznamy.tab.platforms.bukkit.features;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
import me.neznamy.tab.api.TabFeature;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
@@ -12,8 +10,8 @@ import me.neznamy.tab.platforms.bukkit.nms.datawatcher.DataWatcherItem;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
|
||||
/**
|
||||
* A feature to disable minecraft 1.9+ feature making tamed animals with custom names copy nametag properties of their owner
|
||||
* This is achieved by listening to entity spawn (<1.15) / entity metadata packets and removing owner field from the datawatcher list
|
||||
* A feature to disable minecraft 1.9+ feature making tamed animals with custom names copy NameTag properties of their owner
|
||||
* This is achieved by listening to entity spawn (<1.15) / entity metadata packets and removing owner field from the DataWatcher list
|
||||
* Since 1.16 this results in client sending entity use packet twice, so we must cancel the 2nd one to prevent double toggle
|
||||
*/
|
||||
public class PetFix extends TabFeature {
|
||||
@@ -21,11 +19,11 @@ public class PetFix extends TabFeature {
|
||||
//nms storage
|
||||
private final NMSStorage nms = NMSStorage.getInstance();
|
||||
|
||||
//datawatcher position of pet owner field
|
||||
//DataWatcher position of pet owner field
|
||||
private final int petOwnerPosition = getPetOwnerPosition();
|
||||
|
||||
//logger of last interacts to prevent feature not working on 1.16
|
||||
private final Map<String, Long> lastInteractFix = new HashMap<>();
|
||||
private final WeakHashMap<TabPlayer, Long> lastInteractFix = new WeakHashMap<>();
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameter
|
||||
@@ -60,18 +58,19 @@ public class PetFix extends TabFeature {
|
||||
|
||||
/**
|
||||
* Cancels a packet if previous one arrived with no delay to prevent double toggle on 1.16
|
||||
* @throws ReflectiveOperationException
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
@Override
|
||||
public boolean onPacketReceive(TabPlayer sender, Object packet) throws ReflectiveOperationException {
|
||||
if (nms.PacketPlayInUseEntity.isInstance(packet)) {
|
||||
if (lastInteractFix.containsKey(sender.getName()) && (System.currentTimeMillis() - lastInteractFix.get(sender.getName()) < 5)) {
|
||||
if (lastInteractFix.containsKey(sender) && (System.currentTimeMillis() - lastInteractFix.get(sender) < 5)) {
|
||||
//last interact packet was sent right now, cancelling to prevent double-toggle due to this feature enabled
|
||||
return true;
|
||||
}
|
||||
if (isInteract(nms.PacketPlayInUseEntity_ACTION.get(packet))) {
|
||||
//this is the first packet, saving player so the next packet can be cancelled
|
||||
lastInteractFix.put(sender.getName(), System.currentTimeMillis());
|
||||
lastInteractFix.put(sender, System.currentTimeMillis());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@@ -86,8 +85,9 @@ public class PetFix extends TabFeature {
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes pet owner field from datawatcher
|
||||
* @throws ReflectiveOperationException
|
||||
* Removes pet owner field from DataWatcher
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
@@ -96,14 +96,19 @@ public class PetFix extends TabFeature {
|
||||
Object removedEntry = null;
|
||||
List<Object> items = (List<Object>) nms.PacketPlayOutEntityMetadata_LIST.get(packet);
|
||||
if (items == null) return;
|
||||
for (Object item : items) {
|
||||
if (item == null) continue;
|
||||
if (nms.DataWatcherObject_SLOT.getInt(nms.DataWatcherItem_TYPE.get(item)) == petOwnerPosition) {
|
||||
Object value = nms.DataWatcherItem_VALUE.get(item);
|
||||
if (value instanceof java.util.Optional || value instanceof com.google.common.base.Optional) {
|
||||
removedEntry = item;
|
||||
try {
|
||||
for (Object item : items) {
|
||||
if (item == null) continue;
|
||||
if (nms.DataWatcherObject_SLOT.getInt(nms.DataWatcherItem_TYPE.get(item)) == petOwnerPosition) {
|
||||
Object value = nms.DataWatcherItem_VALUE.get(item);
|
||||
if (value instanceof java.util.Optional || value instanceof com.google.common.base.Optional) {
|
||||
removedEntry = item;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ConcurrentModificationException e) {
|
||||
//no idea how can this list change in another thread since it's created for the packet but whatever, try again
|
||||
onPacketSend(receiver, packet);
|
||||
}
|
||||
if (removedEntry != null) items.remove(removedEntry);
|
||||
} else if (nms.PacketPlayOutSpawnEntityLiving.isInstance(packet) && nms.PacketPlayOutSpawnEntityLiving_DATAWATCHER != null) {
|
||||
@@ -116,12 +121,4 @@ public class PetFix extends TabFeature {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removing player data to not have a memory leak
|
||||
*/
|
||||
@Override
|
||||
public void onQuit(TabPlayer disconnectedPlayer) {
|
||||
lastInteractFix.remove(disconnectedPlayer.getName());
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package me.neznamy.tab.platforms.bukkit.features;
|
||||
|
||||
import me.neznamy.tab.shared.TabConstants;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
@@ -12,7 +13,7 @@ import me.neznamy.tab.api.bossbar.BossBarManager;
|
||||
import me.neznamy.tab.api.scoreboard.Scoreboard;
|
||||
import me.neznamy.tab.api.scoreboard.ScoreboardManager;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.features.scoreboard.ScoreboardManagerImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* TAB's expansion for PlaceholderAPI
|
||||
@@ -42,22 +43,22 @@ public class TabExpansion extends PlaceholderExpansion {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthor(){
|
||||
public @NotNull String getAuthor(){
|
||||
return plugin.getDescription().getAuthors().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdentifier(){
|
||||
public @NotNull String getIdentifier(){
|
||||
return "tab";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion(){
|
||||
public @NotNull String getVersion(){
|
||||
return plugin.getDescription().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onPlaceholderRequest(Player player, String identifier){
|
||||
public String onPlaceholderRequest(Player player, @NotNull String identifier){
|
||||
if (player == null) return "";
|
||||
TabPlayer p = TAB.getInstance().getPlayer(player.getUniqueId());
|
||||
if ("scoreboard_visible".equals(identifier)) {
|
||||
@@ -82,21 +83,21 @@ public class TabExpansion extends PlaceholderExpansion {
|
||||
}
|
||||
|
||||
private boolean hasBossBarVisible(TabPlayer p) {
|
||||
BossBarManager boss = (BossBarManager) TAB.getInstance().getFeatureManager().getFeature("bossbar");
|
||||
BossBarManager boss = (BossBarManager) TAB.getInstance().getFeatureManager().getFeature(TabConstants.Feature.BOSS_BAR);
|
||||
if (boss == null) return false;
|
||||
return boss.hasBossBarVisible(p);
|
||||
}
|
||||
|
||||
private boolean hasScoreboardVisible(TabPlayer p) {
|
||||
ScoreboardManager scoreboard = (ScoreboardManager) TAB.getInstance().getFeatureManager().getFeature("scoreboard");
|
||||
ScoreboardManager scoreboard = (ScoreboardManager) TAB.getInstance().getFeatureManager().getFeature(TabConstants.Feature.SCOREBOARD);
|
||||
if (scoreboard == null) return false;
|
||||
return scoreboard.hasScoreboardVisible(p);
|
||||
}
|
||||
|
||||
private String getActiveScoreboard(TabPlayer p) {
|
||||
ScoreboardManagerImpl sb = (ScoreboardManagerImpl) TabAPI.getInstance().getScoreboardManager();
|
||||
ScoreboardManager sb = TabAPI.getInstance().getScoreboardManager();
|
||||
if (sb == null) return "";
|
||||
Scoreboard active = sb.getActiveScoreboards().get(p);
|
||||
Scoreboard active = sb.getActiveScoreboard(p);
|
||||
if (active == null) return "";
|
||||
return active.getName();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package me.neznamy.tab.platforms.bukkit.features;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
@@ -32,10 +32,10 @@ public class WitherBossBar extends BossBarManagerImpl implements Listener {
|
||||
*/
|
||||
public WitherBossBar(JavaPlugin plugin) {
|
||||
Bukkit.getPluginManager().registerEvents(this, plugin);
|
||||
//when MC is on fullscreen, bossbar disappears after 1 second of not being seen
|
||||
//when MC is on fullscreen, BossBar disappears after 1 second of not being seen
|
||||
//when in a small window, it's about 100ms
|
||||
TAB.getInstance().getPlaceholderManager().registerPlayerPlaceholder("%location%", 100, p -> ((Player)p.getPlayer()).getLocation());
|
||||
addUsedPlaceholders(Arrays.asList("%location%"));
|
||||
addUsedPlaceholders(Collections.singletonList("%location%"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+8
-9
@@ -27,12 +27,12 @@ import me.neznamy.tab.shared.TAB;
|
||||
*/
|
||||
public class BukkitArmorStand implements ArmorStand {
|
||||
|
||||
private static boolean alwaysVisible = TAB.getInstance().getConfiguration().isArmorStandsAlwaysVisible();
|
||||
private final boolean alwaysVisible = TAB.getInstance().getConfiguration().isArmorStandsAlwaysVisible();
|
||||
//entity id counter to pick unique entity IDs
|
||||
private static int idCounter = 2000000000;
|
||||
|
||||
//nametag feature
|
||||
private final NameTagX manager = (NameTagX) TAB.getInstance().getFeatureManager().getFeature("nametagx");
|
||||
//NameTag feature
|
||||
private final NameTagX manager = (NameTagX) TAB.getInstance().getFeatureManager().getFeature(TabConstants.Feature.UNLIMITED_NAME_TAGS);
|
||||
|
||||
//owner of the armor stand
|
||||
private final TabPlayer owner;
|
||||
@@ -59,7 +59,7 @@ public class BukkitArmorStand implements ArmorStand {
|
||||
private final Property property;
|
||||
|
||||
//if offset is static or dynamic based on other armor stands
|
||||
private boolean staticOffset;
|
||||
private final boolean staticOffset;
|
||||
|
||||
//entity destroy packet
|
||||
private final PacketPlayOutEntityDestroy destroyPacket = new PacketPlayOutEntityDestroy(entityId);
|
||||
@@ -119,7 +119,7 @@ public class BukkitArmorStand implements ArmorStand {
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
for (TabPlayer all : TAB.getInstance().getOnlinePlayers()) all.sendCustomPacket(destroyPacket, TabConstants.PacketCategory.UNLIMITED_NAMETAGS_DESPAWN);
|
||||
for (TabPlayer all : owner.getArmorStandManager().getNearbyPlayers()) all.sendCustomPacket(destroyPacket, TabConstants.PacketCategory.UNLIMITED_NAMETAGS_DESPAWN);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -149,7 +149,7 @@ public class BukkitArmorStand implements ArmorStand {
|
||||
this.sneaking = sneaking;
|
||||
for (TabPlayer viewer : owner.getArmorStandManager().getNearbyPlayers()) {
|
||||
if (viewer.getVersion().getMinorVersion() == 14 && !alwaysVisible) {
|
||||
//1.14.x client sided bug, despawning completely
|
||||
//1.14.x client sided bug, de-spawning completely
|
||||
if (sneaking) {
|
||||
viewer.sendCustomPacket(destroyPacket, TabConstants.PacketCategory.UNLIMITED_NAMETAGS_SNEAK);
|
||||
} else {
|
||||
@@ -196,7 +196,7 @@ public class BukkitArmorStand implements ArmorStand {
|
||||
|
||||
/**
|
||||
* Returns general visibility rule for everyone with limited info
|
||||
* @return true if should be visible, false if not
|
||||
* @return true if armor stand should be visible, false if not
|
||||
*/
|
||||
public boolean getVisibility() {
|
||||
if (owner.isDisguised() || manager.getVehicleManager().isOnBoat(owner)) return false;
|
||||
@@ -261,7 +261,7 @@ public class BukkitArmorStand implements ArmorStand {
|
||||
* Creates data watcher with specified display name for viewer
|
||||
* @param displayName - armor stand name
|
||||
* @param viewer - player to apply checks against
|
||||
* @return datawatcher for viewer
|
||||
* @return DataWatcher for viewer
|
||||
*/
|
||||
public DataWatcher createDataWatcher(String displayName, TabPlayer viewer) {
|
||||
DataWatcher datawatcher = new DataWatcher();
|
||||
@@ -299,7 +299,6 @@ public class BukkitArmorStand implements ArmorStand {
|
||||
/**
|
||||
* Returns list of packets to send to make armor stand spawn with metadata
|
||||
* @param viewer - viewer to apply relational placeholders for
|
||||
* @param addToRegistered - if player should be added to registered or not
|
||||
* @return List of packets that spawn the armor stand
|
||||
*/
|
||||
public TabPacket[] getSpawnPackets(TabPlayer viewer) {
|
||||
|
||||
+6
-7
@@ -16,25 +16,25 @@ import me.neznamy.tab.shared.TAB;
|
||||
*/
|
||||
public class EventListener implements Listener {
|
||||
|
||||
//the nametag feature handler
|
||||
//the NameTag feature handler
|
||||
private final NameTagX feature;
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters
|
||||
* @param feature - nametagx feature handler
|
||||
* @param feature - NameTag feature handler
|
||||
*/
|
||||
public EventListener(NameTagX feature) {
|
||||
this.feature = feature;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sneak event listener to despawn & spawn armor stands to skip animation
|
||||
* Sneak event listener to de-spawn & spawn armor stands to skip animation
|
||||
* @param e - sneak event
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void onSneak(PlayerToggleSneakEvent e) {
|
||||
TabPlayer p = TAB.getInstance().getPlayer(e.getPlayer().getUniqueId());
|
||||
if (p == null || !p.isLoaded() || feature.isPlayerDisabled(p)) return;
|
||||
if (p == null || feature.isPlayerDisabled(p)) return;
|
||||
TAB.getInstance().getCPUManager().runMeasuredTask("processing PlayerToggleSneakEvent", feature, TabConstants.CpuUsageCategory.PLAYER_SNEAK, () -> {
|
||||
if (p.getArmorStandManager() != null) p.getArmorStandManager().sneak(e.isSneaking());
|
||||
});
|
||||
@@ -56,12 +56,11 @@ public class EventListener implements Listener {
|
||||
@EventHandler
|
||||
public void onWorldChange(PlayerChangedWorldEvent e) {
|
||||
TabPlayer p = TAB.getInstance().getPlayer(e.getPlayer().getUniqueId());
|
||||
if (p == null) return;
|
||||
if (p == null || !p.isLoaded()) return;
|
||||
long time = System.nanoTime();
|
||||
String to = e.getPlayer().getWorld().getName();
|
||||
if (feature.isDisabled(to)) {
|
||||
if (!feature.getPlayersInDisabledUnlimitedWorlds().contains(p))
|
||||
feature.getPlayersInDisabledUnlimitedWorlds().add(p);
|
||||
feature.getPlayersInDisabledUnlimitedWorlds().add(p);
|
||||
} else {
|
||||
feature.getPlayersInDisabledUnlimitedWorlds().remove(p);
|
||||
}
|
||||
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
package me.neznamy.tab.platforms.bukkit.features.unlimitedtags;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import me.neznamy.tab.api.TabFeature;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
|
||||
public class LocationRefresher extends TabFeature {
|
||||
|
||||
private final NameTagX feature;
|
||||
|
||||
public LocationRefresher(NameTagX feature) {
|
||||
super(feature.getFeatureName(), "Processing passengers / preview");
|
||||
this.feature = feature;
|
||||
TAB.getInstance().getPlaceholderManager().registerPlayerPlaceholder("%location0%", 50, p -> {
|
||||
|
||||
if (!feature.getVehicleManager().getPlayersInVehicle().containsKey(p) && !p.isPreviewingNametag()) return null;
|
||||
Location l = ((Player)p.getPlayer()).getLocation();
|
||||
return l.getX()+l.getY()+l.getZ(); //less cpu usage than literal Location#toString() and then .equals() when comparing last value
|
||||
});
|
||||
addUsedPlaceholders(Arrays.asList("%location0%")); //making sure it's not the same one as in WiherBossBar
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh(TabPlayer p, boolean force) {
|
||||
if (feature.getVehicleManager().getPlayersInVehicle().containsKey(p)) {
|
||||
feature.getVehicleManager().processPassengers((Entity) p.getPlayer());
|
||||
}
|
||||
if (p.isPreviewingNametag()) {
|
||||
p.getArmorStandManager().teleport(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
+32
-37
@@ -1,10 +1,6 @@
|
||||
package me.neznamy.tab.platforms.bukkit.features.unlimitedtags;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@@ -24,7 +20,7 @@ import me.neznamy.tab.shared.TabConstants;
|
||||
import me.neznamy.tab.shared.features.nametags.NameTag;
|
||||
|
||||
/**
|
||||
* The core class for unlimited nametag mode
|
||||
* The core class for unlimited NameTag mode
|
||||
*/
|
||||
public class NameTagX extends NameTag implements UnlimitedNametagManager {
|
||||
|
||||
@@ -42,26 +38,24 @@ public class NameTagX extends NameTag implements UnlimitedNametagManager {
|
||||
//bukkit event listener
|
||||
private final EventListener eventListener = new EventListener(this);
|
||||
|
||||
private final List<TabPlayer> playersInDisabledUnlimitedWorlds = new ArrayList<>();
|
||||
private final Set<TabPlayer> playersInDisabledUnlimitedWorlds = Collections.newSetFromMap(new WeakHashMap<>());
|
||||
private final String[] disabledUnlimitedWorldsArray = disabledUnlimitedWorlds.toArray(new String[0]);
|
||||
private final boolean unlimitedWorldWhitelistMode = disabledUnlimitedWorlds.contains("WHITELIST");
|
||||
|
||||
private final List<TabPlayer> playersDisabledWithAPI = new ArrayList<>();
|
||||
private final Set<TabPlayer> playersDisabledWithAPI = Collections.newSetFromMap(new WeakHashMap<>());
|
||||
|
||||
private final VehicleRefresher vehicleManager = new VehicleRefresher(this);
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters and loads config options
|
||||
* @param plugin - plugin instance
|
||||
* @param nms - nms storage
|
||||
*/
|
||||
public NameTagX(JavaPlugin plugin) {
|
||||
Collections.reverse(dynamicLines);
|
||||
Bukkit.getPluginManager().registerEvents(eventListener, plugin);
|
||||
TAB.getInstance().getFeatureManager().registerFeature("nametagx-packet", new PacketListener(this));
|
||||
TAB.getInstance().getFeatureManager().registerFeature("nametagx-vehicle", vehicleManager);
|
||||
TAB.getInstance().getFeatureManager().registerFeature("nametagx-location", new LocationRefresher(this));
|
||||
TAB.getInstance().debug(String.format("Loaded Unlimited nametag feature with parameters markerFor18x=%s, disableOnBoats=%s, spaceBetweenLines=%s, disabledUnlimitedWorlds=%s",
|
||||
TAB.getInstance().getFeatureManager().registerFeature(TabConstants.Feature.UNLIMITED_NAME_TAGS_PACKET_LISTENER, new PacketListener(this));
|
||||
TAB.getInstance().getFeatureManager().registerFeature(TabConstants.Feature.UNLIMITED_NAME_TAGS_VEHICLE_REFRESHER, vehicleManager);
|
||||
TAB.getInstance().debug(String.format("Loaded Unlimited NameTag feature with parameters markerFor18x=%s, disableOnBoats=%s, spaceBetweenLines=%s, disabledUnlimitedWorlds=%s",
|
||||
markerFor18x, disableOnBoats, spaceBetweenLines, disabledUnlimitedWorlds));
|
||||
}
|
||||
|
||||
@@ -85,10 +79,10 @@ public class NameTagX extends NameTag implements UnlimitedNametagManager {
|
||||
}
|
||||
|
||||
private void startVisibilityRefreshTask() {
|
||||
TAB.getInstance().getCPUManager().startRepeatingMeasuredTask(500, "refreshing nametag visibility", this, TabConstants.CpuUsageCategory.REFRESHING_NAMETAG_VISIBILITY, () -> {
|
||||
TAB.getInstance().getCPUManager().startRepeatingMeasuredTask(500, "refreshing NameTag visibility", this, TabConstants.CpuUsageCategory.REFRESHING_NAME_TAG_VISIBILITY, () -> {
|
||||
|
||||
for (TabPlayer p : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (!p.isLoaded() || isPlayerDisabled(p)) continue;
|
||||
if (isPlayerDisabled(p)) continue;
|
||||
p.getArmorStandManager().updateVisibility(false);
|
||||
}
|
||||
});
|
||||
@@ -106,7 +100,7 @@ public class NameTagX extends NameTag implements UnlimitedNametagManager {
|
||||
|
||||
@Override
|
||||
public void onJoin(TabPlayer connectedPlayer) {
|
||||
if (isDisabled(connectedPlayer.getWorld()) && !playersInDisabledUnlimitedWorlds.contains(connectedPlayer))
|
||||
if (isDisabled(connectedPlayer.getWorld()))
|
||||
playersInDisabledUnlimitedWorlds.add(connectedPlayer);
|
||||
super.onJoin(connectedPlayer);
|
||||
getEntityIdMap().put(((Player) connectedPlayer.getPlayer()).getEntityId(), connectedPlayer);
|
||||
@@ -136,9 +130,7 @@ public class NameTagX extends NameTag implements UnlimitedNametagManager {
|
||||
for (TabPlayer all : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (all.getArmorStandManager() != null) all.getArmorStandManager().unregisterPlayer(disconnectedPlayer);
|
||||
}
|
||||
getEntityIdMap().remove(((Player) disconnectedPlayer.getPlayer()).getEntityId());
|
||||
playersInDisabledUnlimitedWorlds.remove(disconnectedPlayer);
|
||||
playersDisabledWithAPI.remove(disconnectedPlayer);
|
||||
entityIdMap.remove(((Player) disconnectedPlayer.getPlayer()).getEntityId());
|
||||
if (disconnectedPlayer.getArmorStandManager() != null) { //player was not loaded yet
|
||||
disconnectedPlayer.getArmorStandManager().destroy();
|
||||
TAB.getInstance().getCPUManager().runTaskLater(500, "processing onQuit", this, TabConstants.CpuUsageCategory.PLAYER_QUIT, () -> disconnectedPlayer.getArmorStandManager().destroy());
|
||||
@@ -152,7 +144,7 @@ public class NameTagX extends NameTag implements UnlimitedNametagManager {
|
||||
* @param sendMutually - if packets should be sent both ways
|
||||
*/
|
||||
public void spawnArmorStands(TabPlayer owner, TabPlayer viewer, boolean sendMutually) {
|
||||
if (owner == viewer) return; //not displaying own armorstands
|
||||
if (owner == viewer) return; //not displaying own armor stands
|
||||
if (((Player) viewer.getPlayer()).getWorld() != ((Player) owner.getPlayer()).getWorld()) return; //different world
|
||||
if (isPlayerDisabled(owner)) return;
|
||||
if (getDistance(viewer, owner) <= 48) {
|
||||
@@ -232,26 +224,29 @@ public class NameTagX extends NameTag implements UnlimitedNametagManager {
|
||||
* @param p - player to update
|
||||
*/
|
||||
@Override
|
||||
public void updateProperties(TabPlayer p) {
|
||||
super.updateProperties(p);
|
||||
p.loadPropertyFromConfig(this, TabConstants.Property.CUSTOMTAGNAME, p.getName());
|
||||
p.setProperty(this, TabConstants.Property.NAMETAG, p.getProperty(TabConstants.Property.TAGPREFIX).getCurrentRawValue() + p.getProperty(TabConstants.Property.CUSTOMTAGNAME).getCurrentRawValue() + p.getProperty(TabConstants.Property.TAGSUFFIX).getCurrentRawValue());
|
||||
public boolean updateProperties(TabPlayer p) {
|
||||
boolean changed = super.updateProperties(p);
|
||||
if (p.loadPropertyFromConfig(this, TabConstants.Property.CUSTOMTAGNAME, p.getName())) changed = true;
|
||||
if (p.setProperty(this, TabConstants.Property.NAMETAG, p.getProperty(TabConstants.Property.TAGPREFIX).getCurrentRawValue() +
|
||||
p.getProperty(TabConstants.Property.CUSTOMTAGNAME).getCurrentRawValue() + p.getProperty(TabConstants.Property.TAGSUFFIX).getCurrentRawValue())) changed = true;
|
||||
for (String property : dynamicLines) {
|
||||
if (!property.equals(TabConstants.Property.NAMETAG)) p.loadPropertyFromConfig(this, property);
|
||||
if (!property.equals(TabConstants.Property.NAMETAG) && p.loadPropertyFromConfig(this, property)) changed = true;
|
||||
}
|
||||
for (String property : staticLines.keySet()) {
|
||||
if (!property.equals(TabConstants.Property.NAMETAG)) p.loadPropertyFromConfig(this, property);
|
||||
if (!property.equals(TabConstants.Property.NAMETAG) && p.loadPropertyFromConfig(this, property)) changed = true;
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFeatureName() {
|
||||
return "Unlimited Nametags";
|
||||
return "Unlimited NameTags";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getTeamVisibility(TabPlayer p, TabPlayer viewer) {
|
||||
if (p.hasInvisibilityPotion()) return false; //1.8.x client sided bug
|
||||
if (vehicleManager == null) return false; //class is still being initialized and this was called from super constructor
|
||||
return vehicleManager.isOnBoat(p) || isPlayerDisabled(p);
|
||||
}
|
||||
|
||||
@@ -273,7 +268,7 @@ public class NameTagX extends NameTag implements UnlimitedNametagManager {
|
||||
return markerFor18x;
|
||||
}
|
||||
|
||||
public List<TabPlayer> getPlayersInDisabledUnlimitedWorlds() {
|
||||
public Set<TabPlayer> getPlayersInDisabledUnlimitedWorlds() {
|
||||
return playersInDisabledUnlimitedWorlds;
|
||||
}
|
||||
|
||||
@@ -329,35 +324,35 @@ public class NameTagX extends NameTag implements UnlimitedNametagManager {
|
||||
@Override
|
||||
public void setPrefix(TabPlayer player, String prefix) {
|
||||
player.getProperty(TabConstants.Property.TAGPREFIX).setTemporaryValue(prefix);
|
||||
rebuildNametagLine(player);
|
||||
rebuildNameTagLine(player);
|
||||
player.forceRefresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSuffix(TabPlayer player, String suffix) {
|
||||
player.getProperty(TabConstants.Property.TAGSUFFIX).setTemporaryValue(suffix);
|
||||
rebuildNametagLine(player);
|
||||
rebuildNameTagLine(player);
|
||||
player.forceRefresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetPrefix(TabPlayer player) {
|
||||
player.getProperty(TabConstants.Property.TAGPREFIX).setTemporaryValue(null);
|
||||
rebuildNametagLine(player);
|
||||
rebuildNameTagLine(player);
|
||||
player.forceRefresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetSuffix(TabPlayer player) {
|
||||
player.getProperty(TabConstants.Property.TAGSUFFIX).setTemporaryValue(null);
|
||||
rebuildNametagLine(player);
|
||||
rebuildNameTagLine(player);
|
||||
player.forceRefresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(TabPlayer player, String customname) {
|
||||
player.getProperty(TabConstants.Property.CUSTOMTAGNAME).setTemporaryValue(customname);
|
||||
rebuildNametagLine(player);
|
||||
public void setName(TabPlayer player, String customName) {
|
||||
player.getProperty(TabConstants.Property.CUSTOMTAGNAME).setTemporaryValue(customName);
|
||||
rebuildNameTagLine(player);
|
||||
player.forceRefresh();
|
||||
}
|
||||
|
||||
@@ -370,7 +365,7 @@ public class NameTagX extends NameTag implements UnlimitedNametagManager {
|
||||
@Override
|
||||
public void resetName(TabPlayer player) {
|
||||
player.getProperty(TabConstants.Property.CUSTOMTAGNAME).setTemporaryValue(null);
|
||||
rebuildNametagLine(player);
|
||||
rebuildNameTagLine(player);
|
||||
player.forceRefresh();
|
||||
}
|
||||
|
||||
@@ -400,7 +395,7 @@ public class NameTagX extends NameTag implements UnlimitedNametagManager {
|
||||
return player.getProperty(line).getOriginalRawValue();
|
||||
}
|
||||
|
||||
private void rebuildNametagLine(TabPlayer player) {
|
||||
private void rebuildNameTagLine(TabPlayer player) {
|
||||
player.setProperty(this, TabConstants.Property.NAMETAG, player.getProperty(TabConstants.Property.TAGPREFIX).getCurrentRawValue() +
|
||||
player.getProperty(TabConstants.Property.CUSTOMTAGNAME).getCurrentRawValue() + player.getProperty(TabConstants.Property.TAGSUFFIX).getCurrentRawValue());
|
||||
}
|
||||
|
||||
+4
-4
@@ -13,7 +13,7 @@ import me.neznamy.tab.shared.TAB;
|
||||
|
||||
/**
|
||||
* The packet listening part for securing proper functionality of armor stands
|
||||
* Bukkit events are too unreliable and delayed/ahead which causes desync
|
||||
* Bukkit events are too unreliable and delayed/ahead which causes de-sync
|
||||
*/
|
||||
public class PacketListener extends TabFeature {
|
||||
|
||||
@@ -119,8 +119,8 @@ public class PacketListener extends TabFeature {
|
||||
}
|
||||
|
||||
private void onEntityDestroy(TabPlayer receiver, int entity) {
|
||||
TabPlayer despawnedPlayer = nameTagX.getEntityIdMap().get(entity);
|
||||
if (despawnedPlayer != null && despawnedPlayer.isLoaded() && !nameTagX.isPlayerDisabled(despawnedPlayer))
|
||||
TAB.getInstance().getCPUManager().runMeasuredTask("processing EntityDestroy", nameTagX, TabConstants.CpuUsageCategory.PACKET_ENTITY_DESTROY, () -> despawnedPlayer.getArmorStandManager().destroy(receiver));
|
||||
TabPlayer deSpawnedPlayer = nameTagX.getEntityIdMap().get(entity);
|
||||
if (deSpawnedPlayer != null && deSpawnedPlayer.isLoaded() && !nameTagX.isPlayerDisabled(deSpawnedPlayer))
|
||||
TAB.getInstance().getCPUManager().runMeasuredTask("processing EntityDestroy", nameTagX, TabConstants.CpuUsageCategory.PACKET_ENTITY_DESTROY, () -> deSpawnedPlayer.getArmorStandManager().destroy(receiver));
|
||||
}
|
||||
}
|
||||
+37
-19
@@ -1,11 +1,9 @@
|
||||
package me.neznamy.tab.platforms.bukkit.features.unlimitedtags;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import me.neznamy.tab.shared.TabConstants;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -16,24 +14,50 @@ import me.neznamy.tab.shared.TAB;
|
||||
|
||||
public class VehicleRefresher extends TabFeature {
|
||||
|
||||
//list of players currently in a vehicle
|
||||
private final Map<TabPlayer, Entity> playersInVehicle = new ConcurrentHashMap<>();
|
||||
//map of players currently in a vehicle
|
||||
private final WeakHashMap<TabPlayer, Entity> playersInVehicle = new WeakHashMap<>();
|
||||
|
||||
//map of vehicles carrying players
|
||||
private final Map<Integer, List<Entity>> vehicles = new ConcurrentHashMap<>();
|
||||
|
||||
//list of players currently on boats
|
||||
private final List<TabPlayer> playersOnBoats = new ArrayList<>();
|
||||
//set of players currently on boats
|
||||
private final Set<TabPlayer> playersOnBoats = Collections.newSetFromMap(new WeakHashMap<>());
|
||||
|
||||
private final NameTagX feature;
|
||||
|
||||
public VehicleRefresher(NameTagX feature) {
|
||||
super(feature.getFeatureName(), "Refreshing vehicles");
|
||||
this.feature = feature;
|
||||
addUsedPlaceholders(Arrays.asList("%vehicle%"));
|
||||
TAB.getInstance().getPlaceholderManager().registerPlayerPlaceholder("%vehicle%", 100, p -> ((Player)p.getPlayer()).getVehicle());
|
||||
TAB.getInstance().getCPUManager().startRepeatingMeasuredTask(50, "processing player movement",
|
||||
this, TabConstants.CpuUsageCategory.PROCESSING_PLAYER_MOVEMENT, () -> {
|
||||
for (TabPlayer inVehicle : playersInVehicle.keySet()) {
|
||||
inVehicle.getArmorStandManager().teleport();
|
||||
// feature.getVehicleManager().processPassengers((Entity) inVehicle.getPlayer());
|
||||
}
|
||||
for (TabPlayer p : TAB.getInstance().getOnlinePlayers()) {
|
||||
if (p.isPreviewingNametag()) {
|
||||
p.getArmorStandManager().teleport(p);
|
||||
}
|
||||
}
|
||||
});
|
||||
addUsedPlaceholders(Collections.singletonList("%vehicle%"));
|
||||
TAB.getInstance().getPlaceholderManager().registerPlayerPlaceholder("%vehicle%", 100, p -> ((Player)p.getPlayer()).getVehicle() == null ? "" : ((Player)p.getPlayer()).getVehicle());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
for (TabPlayer p : TAB.getInstance().getOnlinePlayers()) {
|
||||
Entity vehicle = ((Player)p.getPlayer()).getVehicle();
|
||||
if (vehicle != null) {
|
||||
vehicles.put(vehicle.getEntityId(), getPassengers(vehicle));
|
||||
playersInVehicle.put(p, vehicle);
|
||||
if (feature.isDisableOnBoats() && vehicle.getType() == EntityType.BOAT) {
|
||||
playersOnBoats.add(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh(TabPlayer p, boolean force) {
|
||||
if (feature.isPlayerDisabled(p)) return;
|
||||
@@ -67,8 +91,6 @@ public class VehicleRefresher extends TabFeature {
|
||||
@Override
|
||||
public void onQuit(TabPlayer disconnectedPlayer) {
|
||||
if (playersInVehicle.containsKey(disconnectedPlayer)) vehicles.remove(playersInVehicle.get(disconnectedPlayer).getEntityId());
|
||||
playersInVehicle.remove(disconnectedPlayer);
|
||||
playersOnBoats.remove(disconnectedPlayer);
|
||||
}
|
||||
|
||||
public Map<Integer, List<Entity>> getVehicles() {
|
||||
@@ -86,7 +108,7 @@ public class VehicleRefresher extends TabFeature {
|
||||
return vehicle.getPassengers();
|
||||
} else {
|
||||
if (vehicle.getPassenger() != null) {
|
||||
return Arrays.asList(vehicle.getPassenger());
|
||||
return Collections.singletonList(vehicle.getPassenger());
|
||||
} else {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
@@ -98,8 +120,8 @@ public class VehicleRefresher extends TabFeature {
|
||||
* @param p - player to load passengers of
|
||||
*/
|
||||
public void loadPassengers(TabPlayer p) {
|
||||
if (((Entity) p.getPlayer()).getVehicle() == null) return;
|
||||
Entity vehicle = ((Entity) p.getPlayer()).getVehicle();
|
||||
if (vehicle == null) return;
|
||||
vehicles.put(vehicle.getEntityId(), getPassengers(vehicle));
|
||||
}
|
||||
|
||||
@@ -115,8 +137,4 @@ public class VehicleRefresher extends TabFeature {
|
||||
processPassengers(passenger);
|
||||
}
|
||||
}
|
||||
|
||||
public Map<TabPlayer, Entity> getPlayersInVehicle() {
|
||||
return playersInVehicle;
|
||||
}
|
||||
}
|
||||
@@ -38,14 +38,13 @@ public final class NMSStorage {
|
||||
|
||||
//another field due to fabric which uses 1.16 package on 1.17 server
|
||||
private final ProtocolVersion serverVersion = ProtocolVersion.fromFriendlyName(Bukkit.getBukkitVersion().split("-")[0]);
|
||||
|
||||
|
||||
//base
|
||||
private final Class<?> Packet = getNMSClass("net.minecraft.network.protocol.Packet", "Packet");
|
||||
public final Class<?> EnumChatFormat = getNMSClass("net.minecraft.EnumChatFormat", "EnumChatFormat");
|
||||
public final Class<?> EntityPlayer = getNMSClass("net.minecraft.server.level.EntityPlayer", "EntityPlayer");
|
||||
private final Class<?> Entity = getNMSClass("net.minecraft.world.entity.Entity", "Entity");
|
||||
private final Class<?> EntityLiving = getNMSClass("net.minecraft.world.entity.EntityLiving", "EntityLiving");
|
||||
private final Class<?> NetworkManager = getNMSClass("net.minecraft.network.NetworkManager", "NetworkManager");
|
||||
private final Class<?> PlayerConnection = getNMSClass("net.minecraft.server.network.PlayerConnection", "PlayerConnection");
|
||||
public Constructor<?> newEntityArmorStand;
|
||||
public final Field PING = getField(EntityPlayer, "ping", "latency", "field_71138_i", "field_13967", "e");
|
||||
@@ -224,9 +223,12 @@ public final class NMSStorage {
|
||||
|
||||
/**
|
||||
* Creates new instance, initializes required NMS classes and fields
|
||||
* @throws ReflectiveOperationException
|
||||
* @throws ReflectiveOperationException
|
||||
* If any class, field or method fails to load
|
||||
*/
|
||||
public NMSStorage() throws ReflectiveOperationException {
|
||||
ProtocolVersion.UNKNOWN.setMinorVersion(minorVersion); //fixing compatibility with forks that set version field value to "Unknown"
|
||||
Class<?> NetworkManager = getNMSClass("net.minecraft.network.NetworkManager", "NetworkManager");
|
||||
if (minorVersion >= 7) {
|
||||
NETWORK_MANAGER = getFields(PlayerConnection, NetworkManager).get(0);
|
||||
}
|
||||
@@ -255,7 +257,7 @@ public final class NMSStorage {
|
||||
* Sets new instance
|
||||
* @param instance - new instance
|
||||
*/
|
||||
public final static void setInstance(NMSStorage instance) {
|
||||
public static void setInstance(NMSStorage instance) {
|
||||
NMSStorage.instance = instance;
|
||||
}
|
||||
|
||||
@@ -263,11 +265,11 @@ public final class NMSStorage {
|
||||
* Returns instance
|
||||
* @return instance
|
||||
*/
|
||||
public final static NMSStorage getInstance() {
|
||||
public static NMSStorage getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private final void initializeChatComponents() throws ReflectiveOperationException {
|
||||
private void initializeChatComponents() throws ReflectiveOperationException {
|
||||
if (minorVersion < 7) return;
|
||||
Class<?> ChatBaseComponent = getNMSClass("net.minecraft.network.chat.ChatBaseComponent", "ChatBaseComponent");
|
||||
Class<?> ChatClickable = getNMSClass("net.minecraft.network.chat.ChatClickable", "ChatClickable");
|
||||
@@ -318,7 +320,7 @@ public final class NMSStorage {
|
||||
}
|
||||
}
|
||||
|
||||
private final void initializeChatPacket() throws ReflectiveOperationException {
|
||||
private void initializeChatPacket() throws ReflectiveOperationException {
|
||||
Class<?> PacketPlayOutChat = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutChat", "PacketPlayOutChat", "Packet3Chat");
|
||||
if (minorVersion >= 12) {
|
||||
ChatMessageType = getNMSClass("net.minecraft.network.chat.ChatMessageType", "ChatMessageType");
|
||||
@@ -335,7 +337,7 @@ public final class NMSStorage {
|
||||
}
|
||||
}
|
||||
|
||||
private final void initializeDataWatcher() throws ReflectiveOperationException {
|
||||
private void initializeDataWatcher() throws ReflectiveOperationException {
|
||||
if (minorVersion >= 9) {
|
||||
Class<?> DataWatcherObject = getNMSClass("net.minecraft.network.syncher.DataWatcherObject", "DataWatcherObject");
|
||||
DataWatcherRegistry = getNMSClass("net.minecraft.network.syncher.DataWatcherRegistry", "DataWatcherRegistry");
|
||||
@@ -352,7 +354,7 @@ public final class NMSStorage {
|
||||
registry = new DataWatcherRegistry(this);
|
||||
}
|
||||
|
||||
private final void initializeEntityPackets() throws ReflectiveOperationException {
|
||||
private void initializeEntityPackets() throws ReflectiveOperationException {
|
||||
if (minorVersion >= 17 || serverVersion.getMinorVersion() >= 17) {
|
||||
newPacketPlayOutSpawnEntityLiving = PacketPlayOutSpawnEntityLiving.getConstructor(EntityLiving);
|
||||
newPacketPlayOutEntityTeleport = PacketPlayOutEntityTeleport.getConstructor(Entity);
|
||||
@@ -395,7 +397,7 @@ public final class NMSStorage {
|
||||
}
|
||||
}
|
||||
|
||||
private final void initializeHeaderFooterPacket() throws ReflectiveOperationException {
|
||||
private void initializeHeaderFooterPacket() throws ReflectiveOperationException {
|
||||
if (minorVersion < 8) return;
|
||||
Class<?> PacketPlayOutPlayerListHeaderFooter = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutPlayerListHeaderFooter", "PacketPlayOutPlayerListHeaderFooter");
|
||||
PacketPlayOutPlayerListHeaderFooter_HEADER = getFields(PacketPlayOutPlayerListHeaderFooter, IChatBaseComponent).get(0);
|
||||
@@ -407,7 +409,7 @@ public final class NMSStorage {
|
||||
}
|
||||
}
|
||||
|
||||
private final void initializePlayerInfoPacket() throws ReflectiveOperationException {
|
||||
private void initializePlayerInfoPacket() throws ReflectiveOperationException {
|
||||
if (minorVersion < 8) return;
|
||||
PacketPlayOutPlayerInfo = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo", "PacketPlayOutPlayerInfo");
|
||||
Class<?> EnumPlayerInfoAction = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo$EnumPlayerInfoAction", "PacketPlayOutPlayerInfo$EnumPlayerInfoAction", "EnumPlayerInfoAction", "net.minecraft.class_2703$class_5893");
|
||||
@@ -425,7 +427,7 @@ public final class NMSStorage {
|
||||
EnumGamemode_values = getEnumValues(EnumGamemode);
|
||||
}
|
||||
|
||||
private final void initializeScoreboardPackets() throws ReflectiveOperationException {
|
||||
private void initializeScoreboardPackets() throws ReflectiveOperationException {
|
||||
List<Field> list = getFields(PacketPlayOutScoreboardObjective, int.class);
|
||||
PacketPlayOutScoreboardObjective_METHOD = list.get(list.size()-1);
|
||||
Class<?> EnumScoreboardAction = null;
|
||||
@@ -452,15 +454,15 @@ public final class NMSStorage {
|
||||
}
|
||||
}
|
||||
|
||||
private final void initializeTeamPackets() throws ReflectiveOperationException {
|
||||
private void initializeTeamPackets() throws ReflectiveOperationException {
|
||||
PacketPlayOutScoreboardTeam = getNMSClass("net.minecraft.network.protocol.game.PacketPlayOutScoreboardTeam", "PacketPlayOutScoreboardTeam", "Packet209SetScoreboardTeam");
|
||||
Class<?> ScoreboardTeam = getNMSClass("net.minecraft.world.scores.ScoreboardTeam", "ScoreboardTeam");
|
||||
newScoreboardTeam = ScoreboardTeam.getConstructor(Scoreboard, String.class);
|
||||
PacketPlayOutScoreboardTeam_NAME = getFields(PacketPlayOutScoreboardTeam, String.class).get(0);
|
||||
PacketPlayOutScoreboardTeam_PLAYERS = getFields(PacketPlayOutScoreboardTeam, Collection.class).get(0);
|
||||
ScoreboardTeam_getPlayerNameSet = getMethods(ScoreboardTeam, Collection.class).get(0);
|
||||
ScoreboardTeam_setAllowFriendlyFire = getMethod(ScoreboardTeam, new String[]{"setAllowFriendlyFire", "a"}, boolean.class);
|
||||
ScoreboardTeam_setCanSeeFriendlyInvisibles = getMethod(ScoreboardTeam, new String[]{"setCanSeeFriendlyInvisibles", "b"}, boolean.class);
|
||||
ScoreboardTeam_setAllowFriendlyFire = getMethod(ScoreboardTeam, new String[]{"setAllowFriendlyFire", "a", "func_96660_a"}, boolean.class);
|
||||
ScoreboardTeam_setCanSeeFriendlyInvisibles = getMethod(ScoreboardTeam, new String[]{"setCanSeeFriendlyInvisibles", "b", "func_98300_b"}, boolean.class);
|
||||
if (minorVersion >= 8) {
|
||||
Class<?> EnumNameTagVisibility = getNMSClass("net.minecraft.world.scores.ScoreboardTeamBase$EnumNameTagVisibility", "ScoreboardTeamBase$EnumNameTagVisibility", "EnumNameTagVisibility");
|
||||
EnumNameTagVisibility_values = getEnumValues(EnumNameTagVisibility);
|
||||
@@ -519,14 +521,14 @@ public final class NMSStorage {
|
||||
private Class<?> getLegacyClass(String name) throws ClassNotFoundException {
|
||||
try {
|
||||
return Class.forName("net.minecraft.server." + serverPackage + "." + name);
|
||||
} catch (ClassNotFoundException e) {
|
||||
} catch (ClassNotFoundException | NullPointerException e) {
|
||||
try {
|
||||
//modded server?
|
||||
Class<?> clazz = Main.class.getClassLoader().loadClass("net.minecraft.server." + serverPackage + "." + name);
|
||||
if (clazz != null) return clazz;
|
||||
throw new ClassNotFoundException(name);
|
||||
} catch (ClassNotFoundException e1) {
|
||||
//fabric
|
||||
} catch (ClassNotFoundException | NullPointerException e1) {
|
||||
//maybe fabric?
|
||||
return Class.forName(name);
|
||||
}
|
||||
}
|
||||
@@ -548,7 +550,21 @@ public final class NMSStorage {
|
||||
//not the first method in array
|
||||
}
|
||||
}
|
||||
throw new NoSuchMethodException("No method found with possible names " + Arrays.toString(names) + " with parameters " + Arrays.toString(parameterTypes) + " in class " + clazz.getName());
|
||||
List<String> list = new ArrayList<>();
|
||||
for (Method m : clazz.getMethods()) {
|
||||
if (m.getParameterCount() != parameterTypes.length) continue;
|
||||
Class<?>[] types = m.getParameterTypes();
|
||||
boolean valid = true;
|
||||
for (int i=0; i<types.length; i++) {
|
||||
if (types[i] != parameterTypes[i]) {
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (valid) list.add(m.getName());
|
||||
}
|
||||
throw new NoSuchMethodException("No method found with possible names " + Arrays.toString(names) + " with parameters " +
|
||||
Arrays.toString(parameterTypes) + " in class " + clazz.getName() + ". Methods with matching parameters: " + list);
|
||||
}
|
||||
|
||||
private Method getMethod(Class<?> clazz, String name, Class<?>... parameterTypes) throws NoSuchMethodException {
|
||||
@@ -558,7 +574,10 @@ public final class NMSStorage {
|
||||
Class<?>[] types = m.getParameterTypes();
|
||||
boolean valid = true;
|
||||
for (int i=0; i<types.length; i++) {
|
||||
if (types[i] != parameterTypes[i]) valid = false;
|
||||
if (types[i] != parameterTypes[i]) {
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (valid) list.add(m);
|
||||
}
|
||||
@@ -573,7 +592,10 @@ public final class NMSStorage {
|
||||
Class<?>[] types = m.getParameterTypes();
|
||||
boolean valid = true;
|
||||
for (int i=0; i<types.length; i++) {
|
||||
if (types[i] != parameterTypes[i]) valid = false;
|
||||
if (types[i] != parameterTypes[i]) {
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (valid) list.add(m);
|
||||
}
|
||||
|
||||
+6
-4
@@ -11,7 +11,7 @@ import me.neznamy.tab.platforms.bukkit.nms.NMSStorage;
|
||||
*/
|
||||
public class DataWatcher {
|
||||
|
||||
//datawatcher data
|
||||
//DataWatcher data
|
||||
private final Map<Integer, DataWatcherItem> dataValues = new HashMap<>();
|
||||
|
||||
//a helper for easier data write
|
||||
@@ -54,7 +54,8 @@ public class DataWatcher {
|
||||
/**
|
||||
* Converts the class into an instance of NMS.DataWatcher
|
||||
* @return an instance of NMS.DataWatcher with same data
|
||||
* @throws ReflectiveOperationException
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public Object toNMS() throws ReflectiveOperationException {
|
||||
NMSStorage nms = NMSStorage.getInstance();
|
||||
@@ -79,9 +80,10 @@ public class DataWatcher {
|
||||
|
||||
/**
|
||||
* Reads NMS data watcher and returns and instance of this class with same data
|
||||
* @param nmsWatcher - NMS datawatcher to read
|
||||
* @param nmsWatcher - NMS DataWatcher to read
|
||||
* @return an instance of this class with same values
|
||||
* @throws ReflectiveOperationException
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static DataWatcher fromNMS(Object nmsWatcher) throws ReflectiveOperationException {
|
||||
|
||||
+2
-2
@@ -9,14 +9,14 @@ import me.neznamy.tab.platforms.bukkit.nms.NMSStorage;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
|
||||
/**
|
||||
* A class to help assigning DataWatcher items as positions often change per-version
|
||||
* A class to help to assign DataWatcher items as positions often change per-version
|
||||
*/
|
||||
public class DataWatcherHelper {
|
||||
|
||||
//position of armor stand flags
|
||||
private final int armorStandFlagsPosition = getArmorStandFlagsPosition();
|
||||
|
||||
//original datawatcher to write to
|
||||
//original DataWatcher to write to
|
||||
private final DataWatcher data;
|
||||
|
||||
//data watcher registry
|
||||
|
||||
+2
-1
@@ -25,7 +25,8 @@ public class DataWatcherItem {
|
||||
* Returns and instance of this class from given NMS item
|
||||
* @param nmsItem - NMS item
|
||||
* @return instance of this class with same data
|
||||
* @throws ReflectiveOperationException
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public static DataWatcherItem fromNMS(Object nmsItem) throws ReflectiveOperationException {
|
||||
NMSStorage nms = NMSStorage.getInstance();
|
||||
|
||||
+2
-2
@@ -5,7 +5,7 @@ package me.neznamy.tab.platforms.bukkit.nms.datawatcher;
|
||||
*/
|
||||
public class DataWatcherObject {
|
||||
|
||||
//position in datawatcher
|
||||
//position in DataWatcher
|
||||
private final int position;
|
||||
|
||||
//value class type used since 1.9
|
||||
@@ -13,7 +13,7 @@ public class DataWatcherObject {
|
||||
|
||||
/**
|
||||
* Constructs a new instance of this class with given parameters
|
||||
* @param position - position in datawatcher
|
||||
* @param position - position in DataWatcher
|
||||
* @param classType - value class type
|
||||
*/
|
||||
public DataWatcherObject(int position, Object classType){
|
||||
|
||||
@@ -131,7 +131,7 @@ scoreboard:
|
||||
- "* &eOnline&7: &f%online%&7/&4%maxplayers%"
|
||||
- "* &eCurrent World&7: &f%worldonline%"
|
||||
- "* &eStaff&7: &f%staffonline%"
|
||||
- ""
|
||||
- " "
|
||||
- "&6Server Info:"
|
||||
- "* &bTPS&7: %tps%"
|
||||
- "* &bUptime&7: &f%server_uptime%"
|
||||
@@ -145,9 +145,9 @@ scoreboard:
|
||||
- "* &eKills&7: &f%statistic_player_kills%"
|
||||
- "* &eDeaths&7: &f%statistic_deaths%"
|
||||
- "* &eHealth&7: &f%health%"
|
||||
- ""
|
||||
- " "
|
||||
- "&6Personal Info:"
|
||||
- "* &bRank&7: &f%rank%"
|
||||
- "* &bRank&7: &f%group%"
|
||||
- "* &bPing&7: &f%ping%&7ms"
|
||||
- "* &bWorld&7: &f%world%"
|
||||
- "%animation:MyAnimation1%"
|
||||
@@ -163,9 +163,6 @@ placeholders:
|
||||
date-format: "dd.MM.yyyy"
|
||||
time-format: "[HH:mm:ss / h:mm a]"
|
||||
time-offset: 0
|
||||
remove-strings:
|
||||
- "[]"
|
||||
- "< >"
|
||||
|
||||
placeholder-output-replacements:
|
||||
"%essentials_vanished%":
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
name: @name@
|
||||
name: TAB
|
||||
version: @version@
|
||||
author: NEZNAMY
|
||||
main: me.neznamy.tab.platforms.bukkit.Main
|
||||
api-version: 1.13
|
||||
softdepend: [PlaceholderAPI, Vault, UltraPermissions, LuckPerms, Essentials, LibsDisguises, ProtocolSupport, ViaVersion]
|
||||
softdepend: [PlaceholderAPI, Vault, UltraPermissions, LuckPerms, Essentials, LibsDisguises, ProtocolSupport, ViaVersion, floodgate]
|
||||
website: "https://github.com/NEZNAMY/TAB"
|
||||
description: @description@
|
||||
commands:
|
||||
tab:
|
||||
description: Plugin's main command
|
||||
+16
-19
@@ -1,53 +1,50 @@
|
||||
package me.neznamy.tab.platforms.bungeecord;
|
||||
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.features.PluginMessageHandler;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.event.ChatEvent;
|
||||
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
|
||||
import net.md_5.bungee.api.event.ServerSwitchEvent;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
import net.md_5.bungee.event.EventPriority;
|
||||
|
||||
/**
|
||||
* The core for bungeecord forwarding events into all enabled features
|
||||
* The core for BungeeCord forwarding events into all enabled features
|
||||
*/
|
||||
public class BungeeEventListener implements Listener {
|
||||
|
||||
private final PluginMessageHandler plm;
|
||||
|
||||
public BungeeEventListener(PluginMessageHandler plm) {
|
||||
this.plm = plm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect event listener to forward the event to all features
|
||||
* @param e - disconnect event
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
@EventHandler
|
||||
public void onQuit(PlayerDisconnectEvent e){
|
||||
if (TAB.getInstance().isDisabled()) return;
|
||||
TAB.getInstance().getFeatureManager().onQuit(TAB.getInstance().getPlayer(e.getPlayer().getUniqueId()));
|
||||
TAB.getInstance().getCPUManager().runTask("processing PlayerDisconnectEvent", () ->
|
||||
TAB.getInstance().getFeatureManager().onQuit(TAB.getInstance().getPlayer(e.getPlayer().getUniqueId())));
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener to join / server switch to forward the event to all features
|
||||
* @param e
|
||||
* @param e
|
||||
* switch event
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
@EventHandler
|
||||
public void onSwitch(ServerSwitchEvent e){
|
||||
if (TAB.getInstance().isDisabled()) return;
|
||||
if (TAB.getInstance().getPlayer(e.getPlayer().getUniqueId()) == null) {
|
||||
TAB.getInstance().getFeatureManager().onJoin(new BungeeTabPlayer(e.getPlayer(), plm));
|
||||
} else {
|
||||
TAB.getInstance().getFeatureManager().onServerChange(e.getPlayer().getUniqueId(), e.getPlayer().getServer().getInfo().getName());
|
||||
}
|
||||
TAB.getInstance().getCPUManager().runTask("processing ServerSwitchEvent", () -> {
|
||||
if (TAB.getInstance().getPlayer(e.getPlayer().getUniqueId()) == null) {
|
||||
TAB.getInstance().getFeatureManager().onJoin(new BungeeTabPlayer(e.getPlayer()));
|
||||
} else {
|
||||
TAB.getInstance().getFeatureManager().onServerChange(e.getPlayer().getUniqueId(), e.getPlayer().getServer().getInfo().getName());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener to chat packets to forward the event to all features
|
||||
* @param e
|
||||
* @param e
|
||||
* chat event
|
||||
*/
|
||||
@EventHandler
|
||||
public void onChat(ChatEvent e) {
|
||||
|
||||
+5
-14
@@ -18,7 +18,6 @@ import me.neznamy.tab.api.protocol.PacketPlayOutScoreboardTeam;
|
||||
import me.neznamy.tab.api.protocol.PacketPlayOutPlayerInfo.EnumGamemode;
|
||||
import me.neznamy.tab.api.protocol.PacketPlayOutPlayerInfo.EnumPlayerInfoAction;
|
||||
import me.neznamy.tab.api.protocol.PacketPlayOutPlayerInfo.PlayerInfoData;
|
||||
import me.neznamy.tab.api.protocol.PacketPlayOutScoreboardObjective.EnumScoreboardHealthDisplay;
|
||||
import net.md_5.bungee.protocol.packet.BossBar;
|
||||
import net.md_5.bungee.protocol.packet.Chat;
|
||||
import net.md_5.bungee.protocol.packet.PlayerListHeaderFooter;
|
||||
@@ -107,10 +106,10 @@ public class BungeePacketBuilder extends PacketBuilder {
|
||||
public Object build(PacketPlayOutScoreboardTeam packet, ProtocolVersion clientVersion) {
|
||||
int color = 0;
|
||||
if (clientVersion.getMinorVersion() >= 13) {
|
||||
color = (packet.getColor() != null ? packet.getColor() : EnumChatFormat.lastColorsOf(packet.getPlayerPrefix())).getNetworkId();
|
||||
color = (packet.getColor() != null ? packet.getColor() : EnumChatFormat.lastColorsOf(packet.getPlayerPrefix())).ordinal();
|
||||
}
|
||||
return new Team(packet.getName(), (byte)packet.getMethod(), jsonOrCut(packet.getName(), clientVersion, 16), jsonOrCut(packet.getPlayerPrefix(), clientVersion, 16), jsonOrCut(packet.getPlayerSuffix(), clientVersion, 16),
|
||||
packet.getNametagVisibility(), packet.getCollisionRule(), color, (byte)packet.getOptions(), packet.getPlayers().toArray(new String[0]));
|
||||
packet.getNameTagVisibility(), packet.getCollisionRule(), color, (byte)packet.getOptions(), packet.getPlayers().toArray(new String[0]));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -124,20 +123,12 @@ public class BungeePacketBuilder extends PacketBuilder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketPlayOutScoreboardObjective readObjective(Object bungeePacket, ProtocolVersion clientVersion) {
|
||||
ScoreboardObjective packet = (ScoreboardObjective) bungeePacket;
|
||||
String title;
|
||||
if (clientVersion.getMinorVersion() >= 13) {
|
||||
title = packet.getValue() == null ? null : IChatBaseComponent.deserialize(packet.getValue()).toLegacyText();
|
||||
} else {
|
||||
title = packet.getValue();
|
||||
}
|
||||
EnumScoreboardHealthDisplay renderType = (packet.getType() == null ? null : EnumScoreboardHealthDisplay.valueOf(packet.getType().toString().toUpperCase()));
|
||||
return new PacketPlayOutScoreboardObjective(packet.getAction(), packet.getName(), title, renderType);
|
||||
public PacketPlayOutScoreboardObjective readObjective(Object bungeePacket) {
|
||||
return new PacketPlayOutScoreboardObjective(((ScoreboardObjective) bungeePacket).getAction(), ((ScoreboardObjective) bungeePacket).getName(), null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketPlayOutScoreboardDisplayObjective readDisplayObjective(Object bungeePacket, ProtocolVersion clientVersion){
|
||||
public PacketPlayOutScoreboardDisplayObjective readDisplayObjective(Object bungeePacket){
|
||||
return new PacketPlayOutScoreboardDisplayObjective(((ScoreboardDisplay) bungeePacket).getPosition(), ((ScoreboardDisplay) bungeePacket).getName());
|
||||
}
|
||||
}
|
||||
+11
-13
@@ -28,7 +28,7 @@ import net.md_5.bungee.protocol.packet.Team;
|
||||
|
||||
public class BungeePipelineInjector extends PipelineInjector {
|
||||
|
||||
//packets that must be deserialized and bungeecord does not do it automatically
|
||||
//packets that must be deserialized and BungeeCord does not do it automatically
|
||||
private final Map<Class<? extends DefinedPacket>, Supplier<DefinedPacket>> extraPackets = new HashMap<>();
|
||||
|
||||
/**
|
||||
@@ -48,7 +48,7 @@ public class BungeePipelineInjector extends PipelineInjector {
|
||||
public class BungeeChannelDuplexHandler extends ChannelDuplexHandler {
|
||||
|
||||
//injected player
|
||||
private TabPlayer player;
|
||||
private final TabPlayer player;
|
||||
|
||||
/**
|
||||
* Constructs new instance with given player
|
||||
@@ -61,8 +61,8 @@ public class BungeePipelineInjector extends PipelineInjector {
|
||||
@Override
|
||||
public void write(ChannelHandlerContext context, Object packet, ChannelPromise channelPromise) {
|
||||
long time = System.nanoTime();
|
||||
Object modifiedPacket = packet instanceof ByteBuf && bytebufDeserialization ? deserialize((ByteBuf) packet) : packet;
|
||||
TAB.getInstance().getCPUManager().addTime("Packet deserializing", TabConstants.CpuUsageCategory.BYTEBUF, System.nanoTime()-time);
|
||||
Object modifiedPacket = packet instanceof ByteBuf && byteBufDeserialization ? deserialize((ByteBuf) packet) : packet;
|
||||
TAB.getInstance().getCPUManager().addTime("Packet deserializing", TabConstants.CpuUsageCategory.BYTE_BUF, System.nanoTime()-time);
|
||||
try {
|
||||
switch(modifiedPacket.getClass().getSimpleName()) {
|
||||
case "PlayerListItem":
|
||||
@@ -74,9 +74,7 @@ public class BungeePipelineInjector extends PipelineInjector {
|
||||
}
|
||||
break;
|
||||
case "ScoreboardDisplay":
|
||||
if (TAB.getInstance().getFeatureManager().onDisplayObjective(player, modifiedPacket)) {
|
||||
return;
|
||||
}
|
||||
TAB.getInstance().getFeatureManager().onDisplayObjective(player, modifiedPacket);
|
||||
break;
|
||||
case "ScoreboardObjective":
|
||||
TAB.getInstance().getFeatureManager().onObjective(player, modifiedPacket);
|
||||
@@ -114,7 +112,7 @@ public class BungeePipelineInjector extends PipelineInjector {
|
||||
col.remove(getName(p));
|
||||
}
|
||||
}
|
||||
RedisBungeeSupport redis = (RedisBungeeSupport) TAB.getInstance().getFeatureManager().getFeature("redisbungee");
|
||||
RedisBungeeSupport redis = (RedisBungeeSupport) TAB.getInstance().getFeatureManager().getFeature(TabConstants.Feature.REDIS_BUNGEE);
|
||||
if (redis != null) {
|
||||
for (RedisPlayer p : redis.getRedisPlayers().values()) {
|
||||
if (col.contains(p.getName()) && !packet.getName().equals(p.getTeamName())) {
|
||||
@@ -124,11 +122,11 @@ public class BungeePipelineInjector extends PipelineInjector {
|
||||
}
|
||||
}
|
||||
packet.setPlayers(col.toArray(new String[0]));
|
||||
TAB.getInstance().getCPUManager().addTime("Nametags", TabConstants.CpuUsageCategory.ANTI_OVERRIDE, System.nanoTime()-time);
|
||||
TAB.getInstance().getCPUManager().addTime("NameTags", TabConstants.CpuUsageCategory.ANTI_OVERRIDE, System.nanoTime()-time);
|
||||
}
|
||||
|
||||
private String getName(TabPlayer p) {
|
||||
NickCompatibility nick = (NickCompatibility) TAB.getInstance().getFeatureManager().getFeature("nick");
|
||||
NickCompatibility nick = (NickCompatibility) TAB.getInstance().getFeatureManager().getFeature(TabConstants.Feature.NICK_COMPATIBILITY);
|
||||
if (nick != null) {
|
||||
return nick.getNickname(p);
|
||||
}
|
||||
@@ -136,10 +134,10 @@ public class BungeePipelineInjector extends PipelineInjector {
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes bytebuf in case it is one of the tracked packets coming from backend server and returns it.
|
||||
* Deserializes byte buf in case it is one of the tracked packets coming from backend server and returns it.
|
||||
* If the packet is not one of them, returns input
|
||||
* @param buf - bytebuf to deserialize
|
||||
* @return deserialized packet or input bytebuf if packet is not tracked
|
||||
* @param buf - byte buf to deserialize
|
||||
* @return deserialized packet or input byte buf if packet is not tracked
|
||||
*/
|
||||
private Object deserialize(ByteBuf buf) {
|
||||
int marker = buf.readerIndex();
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ import net.md_5.bungee.api.config.ServerInfo;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
|
||||
/**
|
||||
* Bungeecord registry to register bungeecord-only placeholders
|
||||
* BungeeCord registry to register BungeeCord-only placeholders
|
||||
*/
|
||||
public class BungeePlaceholderRegistry extends ProxyPlaceholderRegistry {
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package me.neznamy.tab.platforms.bungeecord;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import com.imaginarycode.minecraft.redisbungee.RedisBungeeAPI;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import me.neznamy.tab.api.chat.EnumChatFormat;
|
||||
import me.neznamy.tab.api.protocol.PacketBuilder;
|
||||
@@ -10,6 +11,7 @@ import me.neznamy.tab.platforms.bungeecord.event.TabLoadEvent;
|
||||
import me.neznamy.tab.platforms.bungeecord.event.TabPlayerLoadEvent;
|
||||
import me.neznamy.tab.platforms.bungeecord.redisbungee.RedisBungeeSupport;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.TabConstants;
|
||||
import me.neznamy.tab.shared.features.PluginMessageHandler;
|
||||
import me.neznamy.tab.shared.permission.LuckPerms;
|
||||
import me.neznamy.tab.shared.permission.PermissionPlugin;
|
||||
@@ -22,7 +24,7 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* Bungeecord implementation of Platform
|
||||
* BungeeCord implementation of Platform
|
||||
*/
|
||||
public class BungeePlatform extends ProxyPlatform {
|
||||
|
||||
@@ -56,14 +58,19 @@ public class BungeePlatform extends ProxyPlatform {
|
||||
@Override
|
||||
public void loadFeatures() {
|
||||
TAB tab = TAB.getInstance();
|
||||
if (tab.getConfiguration().isPipelineInjection()) tab.getFeatureManager().registerFeature("injection", new BungeePipelineInjector());
|
||||
if (tab.getConfiguration().isPipelineInjection())
|
||||
tab.getFeatureManager().registerFeature(TabConstants.Feature.PIPELINE_INJECTION, new BungeePipelineInjector());
|
||||
new BungeePlaceholderRegistry().registerPlaceholders(tab.getPlaceholderManager());
|
||||
super.loadFeatures();
|
||||
if (ProxyServer.getInstance().getPluginManager().getPlugin("RedisBungee") != null) {
|
||||
tab.getFeatureManager().registerFeature("redisbungee", new RedisBungeeSupport(plugin));
|
||||
if (RedisBungeeAPI.getRedisBungeeApi() != null) {
|
||||
tab.getFeatureManager().registerFeature(TabConstants.Feature.REDIS_BUNGEE, new RedisBungeeSupport(plugin));
|
||||
} else {
|
||||
TAB.getInstance().getErrorManager().criticalError("RedisBungee plugin was detected, but it returned null API instance. Disabling hook.", null);
|
||||
}
|
||||
}
|
||||
for (ProxiedPlayer p : ProxyServer.getInstance().getPlayers()) {
|
||||
tab.addPlayer(new BungeeTabPlayer(p, plm));
|
||||
tab.addPlayer(new BungeeTabPlayer(p));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+8
-7
@@ -33,14 +33,15 @@ public class BungeePluginMessageHandler extends PluginMessageHandler implements
|
||||
*/
|
||||
@EventHandler
|
||||
public void on(PluginMessageEvent event){
|
||||
if (!event.getTag().equalsIgnoreCase(channelName)) return;
|
||||
if (!event.getTag().equals(channelName)) return;
|
||||
if (event.getReceiver() instanceof ProxiedPlayer) {
|
||||
long time = System.nanoTime();
|
||||
BungeeTabPlayer receiver = (BungeeTabPlayer) TAB.getInstance().getPlayer(((ProxiedPlayer) event.getReceiver()).getUniqueId());
|
||||
if (receiver == null) return;
|
||||
onPluginMessage(receiver, ByteStreams.newDataInput(event.getData()));
|
||||
event.setCancelled(true);
|
||||
TAB.getInstance().getCPUManager().addTime("Plugin message handling", TabConstants.CpuUsageCategory.PLUGIN_MESSAGE, System.nanoTime()-time);
|
||||
TAB.getInstance().getCPUManager().runMeasuredTask("processing PluginMessageEvent", "Plugin message handling",
|
||||
TabConstants.CpuUsageCategory.PLUGIN_MESSAGE, () -> {
|
||||
BungeeTabPlayer receiver = (BungeeTabPlayer) TAB.getInstance().getPlayer(((ProxiedPlayer) event.getReceiver()).getUniqueId());
|
||||
if (receiver == null) return;
|
||||
onPluginMessage(receiver, ByteStreams.newDataInput(event.getData()));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +49,6 @@ public class BungeePluginMessageHandler extends PluginMessageHandler implements
|
||||
public void sendPluginMessage(TabPlayer player, byte[] message) {
|
||||
if (((ProxiedPlayer) player.getPlayer()).getServer() == null) return; //not connected to any server yet
|
||||
((ProxiedPlayer) player.getPlayer()).getServer().sendData(channelName, message);
|
||||
TAB.getInstance().getCPUManager().packetSent("Plugin Message");
|
||||
TAB.getInstance().getCPUManager().packetSent("Plugin Message (" + new String(message) + ")");
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,6 @@ import java.lang.reflect.Method;
|
||||
import de.myzelyam.api.vanish.BungeeVanishAPI;
|
||||
import me.neznamy.tab.api.ProtocolVersion;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.features.PluginMessageHandler;
|
||||
import me.neznamy.tab.shared.proxy.ProxyTabPlayer;
|
||||
import net.md_5.bungee.UserConnection;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
@@ -27,9 +26,6 @@ public class BungeeTabPlayer extends ProxyTabPlayer {
|
||||
private static Object directionData;
|
||||
private static Method getId;
|
||||
|
||||
/**
|
||||
* Initializes fields to get player channel later
|
||||
*/
|
||||
static {
|
||||
try {
|
||||
Field f = Protocol.class.getDeclaredField("TO_CLIENT");
|
||||
@@ -46,10 +42,10 @@ public class BungeeTabPlayer extends ProxyTabPlayer {
|
||||
|
||||
/**
|
||||
* Constructs new instance for given player
|
||||
* @param p - bungeecord player
|
||||
* @param p - BungeeCord player
|
||||
*/
|
||||
public BungeeTabPlayer(ProxiedPlayer p, PluginMessageHandler plm) {
|
||||
super(plm, p, p.getUniqueId(), p.getName(), p.getServer() != null ? p.getServer().getInfo().getName() : "-", "N/A");
|
||||
public BungeeTabPlayer(ProxiedPlayer p) {
|
||||
super(p, p.getUniqueId(), p.getName(), p.getServer() != null ? p.getServer().getInfo().getName() : "-");
|
||||
try {
|
||||
channel = ((ChannelWrapper) wrapperField.get(getPlayer().getPendingConnection())).getHandle();
|
||||
} catch (IllegalAccessException e) {
|
||||
|
||||
Loaded 100 of 242 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user