Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0f5f7e48dd
|
||
|
|
35e5791926
|
||
|
|
6ca711435f
|
||
|
|
e8be71a34a
|
||
|
|
7d0beb6ff2 | ||
|
|
68d0cdcbe7 | ||
|
|
93cfd74fc0 | ||
|
|
79eb6a9078 | ||
|
|
2e9e5042e1 | ||
|
|
bb520edd53 | ||
|
|
2beb9563bb | ||
|
|
87c15f7611 | ||
|
|
655bc176fa | ||
|
|
66cb30d235 | ||
|
|
cbe0b25b5f | ||
|
|
a8ccf4e1c9 | ||
|
|
cce29c51e3 | ||
|
|
242015b0cc | ||
|
|
f209e1b0f9 | ||
|
|
8a1ab06585 | ||
|
|
50e817a86d | ||
|
|
dbd596f079 | ||
|
|
f8e3a07e6f | ||
|
|
ccd4ac3271 | ||
|
|
fce1925448 | ||
|
|
335eb5ef4d | ||
|
|
654c40b892 | ||
|
|
a937243cdf | ||
|
|
665d6baf1c | ||
|
|
b4d326b52c | ||
|
|
3aacec826b | ||
|
|
3261856385 | ||
|
|
8cf479bf3b | ||
|
|
3c3ef636eb | ||
|
|
3bd0b13740 | ||
|
|
92349227a2 | ||
|
|
4dfc2a638a | ||
|
|
d7c73a8072 | ||
|
|
297acc0322 | ||
|
|
1126b3b471 | ||
|
|
ac59973283 | ||
|
|
4b130ed71d | ||
|
|
ce90a33ce9 | ||
|
|
50fee32218 | ||
|
|
39334a4cd9 | ||
|
|
fec2131ba8 | ||
|
|
7c63436da4 | ||
|
|
de8fe63bd0 | ||
|
|
1c22f2387b | ||
|
|
e1b277582a | ||
|
|
94acc4f356 | ||
|
|
9afb62a6a4 | ||
|
|
95ed957d54 | ||
|
|
58814bc2da | ||
|
|
9e7556c3c1 | ||
|
|
abaf723fb7 | ||
|
|
f52e99c86e | ||
|
|
d6e70c35d8 | ||
|
|
4c91e73f0e | ||
|
|
d083fc6e43 | ||
|
|
ff2df25e3b | ||
|
|
86c2342097 | ||
|
|
6dbd176683 | ||
|
|
141aab1c22 | ||
|
|
126ea4f456 | ||
|
|
a0e5a97594 | ||
|
|
0420c11937 | ||
|
|
27472fd387 | ||
|
|
104bdc646f | ||
|
|
cbc4c275d1 | ||
|
|
372d51f873 | ||
|
|
0dfd404215 | ||
|
|
21b7393274 | ||
|
|
dcd5f5a3e6 | ||
|
|
bf313b3ba1 | ||
|
|
5b4e3c479c | ||
|
|
6dedb05c29 | ||
|
|
5f78e01342 | ||
|
|
881506a3d5 | ||
|
|
e26fc661b2 | ||
|
|
f921758ec0 | ||
|
|
01d65ba780 | ||
|
|
d77e2d6f45 | ||
|
|
7c30f55f31 | ||
|
|
c2d63865d5 | ||
|
|
f406b518c0 | ||
|
|
78f8c99f11 | ||
|
|
f97b9a419f | ||
|
|
f2b88b8cd6 | ||
|
|
cd06700c82 | ||
|
|
fa69040e00 | ||
|
|
fd88c1c0bb | ||
|
|
cae7d8d061 | ||
|
|
2e1e24c225 | ||
|
|
da0307b14f | ||
|
|
082c94ac07 | ||
|
|
2ed4b1b6fc | ||
|
|
8c7c8042e5 | ||
|
|
cca15a2b04 | ||
|
|
5f40411be0 | ||
|
|
191273a728 | ||
|
|
9eb9e9589f | ||
|
|
fdd45952c7 | ||
|
|
98378b222d | ||
|
|
15a0446d70 | ||
|
|
7bd1b7c670 | ||
|
|
46aaa47fdd | ||
|
|
2027e9f58e | ||
|
|
162e4690e9 | ||
|
|
c360575dec | ||
|
|
5b0354c2c0 | ||
|
|
52b0f21bd9 | ||
|
|
1e3cbde3b3 | ||
|
|
267fb727c7 | ||
|
|
68904f58ec | ||
|
|
5cbb1bb5dd | ||
|
|
038d221206 | ||
|
|
22d6ebd0d4 | ||
|
|
e8dd46c701 | ||
|
|
1150d07dbe | ||
|
|
5c294f4ad3 | ||
|
|
1b5bf0aab7 | ||
|
|
8d8a03602e | ||
|
|
df7bdb7a0c | ||
|
|
00a5eb2588 | ||
|
|
90631c66e0 | ||
|
|
c1ba692a79 | ||
|
|
8f3324e0d8 | ||
|
|
5a09a9ce78 | ||
|
|
33fcee7641 | ||
|
|
12b91940c7 | ||
|
|
0e6246f044 | ||
|
|
7f7cf97408 | ||
|
|
090fe9ccb6 | ||
|
|
ffae161282 | ||
|
|
1443850344 | ||
|
|
63f9daf334 | ||
|
|
b277d0973a | ||
|
|
33c0f1672a | ||
|
|
4224922ebb | ||
|
|
6eb30d84b4 | ||
|
|
592a75b53f | ||
|
|
8e08ea4e44 | ||
|
|
cff1e831d0 | ||
|
|
83b5a0f88a | ||
|
|
2ba535111e | ||
|
|
4bbf0bb0f1 | ||
|
|
1e80070d2d | ||
|
|
0afe0f28e1 | ||
|
|
fbc04b1183 | ||
|
|
bdd2a139e1 | ||
|
|
e956e59888 | ||
|
|
1debc54db6 | ||
|
|
37786935c3 | ||
|
|
425748af12 | ||
|
|
c0deaa40ed | ||
|
|
70be098f8a | ||
|
|
838ef437d8 | ||
|
|
44d7473c71 | ||
|
|
b8a7dfe543 | ||
|
|
4c4bf79371 | ||
|
|
a4b4bd0146 | ||
|
|
9553e310e4 | ||
|
|
e00caddb1e | ||
|
|
898887225d | ||
|
|
8eef805418 | ||
|
|
8509718d32 | ||
|
|
f2cb7c564f | ||
|
|
9335e5af65 | ||
|
|
5a5eadac1f | ||
|
|
bcd015b6eb | ||
|
|
91c6b8f08e | ||
|
|
c7251295a1 | ||
|
|
db2110b11e | ||
|
|
be1122ce50 | ||
|
|
cf265987db | ||
|
|
cd82e75514 | ||
|
|
74d36f1ab5 | ||
|
|
67da0ff32b | ||
|
|
aabad04e28 | ||
|
|
9236da40dd | ||
|
|
88ff78b7e3 | ||
|
|
21ebd68607 | ||
|
|
9adad40aa9 | ||
|
|
f63b3de63a | ||
|
|
767933e522 | ||
|
|
0fb86ddf6c | ||
|
|
d52969597f | ||
|
|
70e1537bc0 | ||
|
|
605a09b290 | ||
|
|
8e2f8d67f3 | ||
|
|
d00764e548 | ||
|
|
953472a41a | ||
|
|
6be5bb4757 | ||
|
|
b48a9e4f22 | ||
|
|
6d42e252a1 | ||
|
|
ef98b15c86 | ||
|
|
6945e8ee81 | ||
|
|
9c9edbff75 | ||
|
|
b8e3a07980 | ||
|
|
06279e3708 | ||
|
|
9812345f71 | ||
|
|
e1f667079a | ||
|
|
6edc3babc8 | ||
|
|
309c67969a | ||
|
|
bd681229db | ||
|
|
4f0a4feb03 | ||
|
|
2d84a60c84 | ||
|
|
0f66bc7264 | ||
|
|
9283f969c4 | ||
|
|
dbcad7b11d | ||
|
|
8e96fc1595 | ||
|
|
fa46427b1f | ||
|
|
5a112bff22 | ||
|
|
1a8bc5ee34 | ||
|
|
1001bcd507 | ||
|
|
2f6f5f4958 | ||
|
|
863cceb175 | ||
|
|
d07d604f7c | ||
|
|
9035f8b57f | ||
|
|
43bc22b8be | ||
|
|
1d59eb5787 | ||
|
|
5383b87c3f | ||
|
|
5c3815aee0 | ||
|
|
69b9acdc83 | ||
|
|
3b68fe9bdd | ||
|
|
4d9dd1cf83 | ||
|
|
0854fd674f | ||
|
|
75478b59ae | ||
|
|
d39f6fd061 | ||
|
|
a532cd4fc1 | ||
|
|
a6afd9de0a | ||
|
|
9a8df8c890 | ||
|
|
cd435cc716 | ||
|
|
b0bdc36b59 | ||
|
|
1971513acc | ||
|
|
99646f2113 | ||
|
|
78349176d6 | ||
|
|
92115ed493 | ||
|
|
4ef8508c65 | ||
|
|
1feafa884e | ||
|
|
02bff23b1f | ||
|
|
d80742bf20 | ||
|
|
7bde3d9996 | ||
|
|
4d86beb268 | ||
|
|
b039cbb7b6 | ||
|
|
7d8af7efc9 | ||
|
|
7019044837 | ||
|
|
5916ec5d07 | ||
|
|
4508fcf4b3 | ||
|
|
2de69557d2 | ||
|
|
b01e793a26 | ||
|
|
1f67ab7bdb | ||
|
|
43ae5add60 | ||
|
|
971620818b | ||
|
|
c997b99935 | ||
|
|
ae83ce1f42 | ||
|
|
2410717510 | ||
|
|
5270a156b3 | ||
|
|
07d807a7bd | ||
|
|
5fb80f5661 | ||
|
|
ce6bef7f19 | ||
|
|
facedfdea7 | ||
|
|
e8fa66dac0 | ||
|
|
997d824d12 | ||
|
|
86baf27ca0 | ||
|
|
2b8b5303c8 | ||
|
|
24bd58130b | ||
|
|
907bbdb52b | ||
|
|
26c491ce22 | ||
|
|
73def64743 | ||
|
|
d021d213f6 | ||
|
|
dfd5ccf525 | ||
|
|
a4cfe9f81b | ||
|
|
8402088cba | ||
|
|
2adcc0d45b | ||
|
|
da25752b73 | ||
|
|
ac348cf207 | ||
|
|
6afe8f0081 | ||
|
|
86c294592f | ||
|
|
3deba4a0f3 | ||
|
|
cfb3d10a7d | ||
|
|
458fa4e416 | ||
|
|
6e7d2338a4 | ||
|
|
d0bd1b4b0b | ||
|
|
2076b589b4 | ||
|
|
a4b8c2b730 | ||
|
|
0cc83325bc | ||
|
|
f2fa63315e | ||
|
|
9631abf430 | ||
|
|
084123132a | ||
|
|
4e9d2df0b2 | ||
|
|
e3a3a65987 | ||
|
|
17feac0501 | ||
|
|
84e280a562 | ||
|
|
906e304018 | ||
|
|
48cdeb7283 | ||
|
|
4efb55f685 | ||
|
|
3ed6f8158d | ||
|
|
c89a38b0da | ||
|
|
eb40cf873f | ||
|
|
892c626312 | ||
|
|
7e0d447e75 | ||
|
|
49b2723c19 | ||
|
|
5140d912e1 | ||
|
|
0fa1165652 | ||
|
|
375d2297e7 | ||
|
|
fbd089d87a | ||
|
|
5076c80e2c | ||
|
|
4fcbec7a4a | ||
|
|
cb82d3ad13 | ||
|
|
a6172c705d | ||
|
|
3c2c480c11 | ||
|
|
da1a839014 | ||
|
|
bf6628c6a2 | ||
|
|
42674bbfdd | ||
|
|
225164b7b6 | ||
|
|
35ce37acf8 | ||
|
|
2df5b00e07 | ||
|
|
3fa25c0662 | ||
|
|
b7e233834e | ||
|
|
ff80a4807f | ||
|
|
c56592c19a | ||
|
|
e93df8e38d | ||
|
|
15664bc9fb | ||
|
|
9cedbabd75 | ||
|
|
a98ecee8f3 | ||
|
|
f64d0d7b41 | ||
|
|
7a1f1ed484 | ||
|
|
85ade0dd15 | ||
|
|
9c70f5a187 | ||
|
|
f622d0c8b3 | ||
|
|
a3c4362a90 | ||
|
|
05609ca436 | ||
|
|
fde7fefe9f | ||
|
|
19f45aeb4d | ||
|
|
540eafc41b | ||
|
|
1ba62e0ae9 | ||
|
|
07b213d0af | ||
|
|
0528baaa64 | ||
|
|
264b8e69d8 | ||
|
|
b4c6da418d | ||
|
|
3811f942a1 | ||
|
|
6d295960d5 | ||
|
|
983d6a055b | ||
|
|
9de3fc4bbb | ||
|
|
f4c986f0de | ||
|
|
434f629c0b | ||
|
|
dac32b6daf | ||
|
|
dd845013ce | ||
|
|
b9bad50dbd | ||
|
|
56540df419 | ||
|
|
d0b0c55ab8 | ||
|
|
6f2b92e044 | ||
|
|
5da16e8055 | ||
|
|
a522ea9902 | ||
|
|
36801184a5 | ||
|
|
d212eb108d | ||
|
|
cbc1de0f33 | ||
|
|
fcdc04e228 | ||
|
|
890f1ee131 | ||
|
|
f3aec47ac3 | ||
|
|
bcf1c828b5 | ||
|
|
5fd319a152 | ||
|
|
abecb58a8d | ||
|
|
135166b01e | ||
|
|
0770293452 | ||
|
|
f3c40ad582 | ||
|
|
aacc115a36 | ||
|
|
b7ba07b78d | ||
|
|
e13445f55d | ||
|
|
bd527d3868 | ||
|
|
f288112eb2 | ||
|
|
6b415e64a8 | ||
|
|
cfb2cb6b0a | ||
|
|
622deb6fd7 | ||
|
|
7f41421d65 | ||
|
|
73e706465a | ||
|
|
a8c543ca9e | ||
|
|
9594ff452b | ||
|
|
d5c81298dd | ||
|
|
88faacb240 | ||
|
|
0d2a04b3a5 | ||
|
|
f8a90b28b5 | ||
|
|
a948febb18 | ||
|
|
8e33481b97 | ||
|
|
f54be214f9 | ||
|
|
d50b47acb5 | ||
|
|
31011c243a | ||
|
|
f4aa03f20d | ||
|
|
28aacaea45 | ||
|
|
d4fd9a2b78 | ||
|
|
663e0be357 | ||
|
|
14d29577c5 | ||
|
|
951f8072c1 | ||
|
|
05f042eda0 | ||
|
|
b00c2fbcb4 | ||
|
|
dde4866e50 | ||
|
|
9fa6b21c08 | ||
|
|
e95e6fc20c | ||
|
|
c7a3b00c3c | ||
|
|
74bc0e0cb7 | ||
|
|
6248008b4d | ||
|
|
2d91e165ce | ||
|
|
b1220550eb | ||
|
|
680ff3412f | ||
|
|
799f6b8215 | ||
|
|
1be224b7de | ||
|
|
a32adfbfc7 | ||
|
|
dda415351a | ||
|
|
685e4b9faa | ||
|
|
1f842563b3 | ||
|
|
f237b61065 | ||
|
|
19d6d06791 | ||
|
|
6873c59505 | ||
|
|
e7ae62db7b | ||
|
|
d4362f2ed2 | ||
|
|
9247f3d4fb | ||
|
|
b4993b657e | ||
|
|
b73aa93d01 | ||
|
|
bce689e672 | ||
|
|
f4468261cf | ||
|
|
cc926ff974 | ||
|
|
6c3831ded4 | ||
|
|
3c55866d46 | ||
|
|
dfc9359f04 | ||
|
|
ea0897db31 | ||
|
|
25cf6c95e8 | ||
|
|
f5e2910e0b | ||
|
|
fda35986a4 | ||
|
|
b97e86c2ed | ||
|
|
ebb02717b5 | ||
|
|
1b82ebfd25 | ||
|
|
3fb788ef6d | ||
|
|
11bc06182c | ||
|
|
2fe5dc833d | ||
|
|
317cb975ce | ||
|
|
9bb2a97e50 | ||
|
|
53dcc60587 | ||
|
|
db347bc192 | ||
|
|
608b8307dd | ||
|
|
4c027da093 | ||
|
|
bef60e688c | ||
|
|
b987ad99f4 | ||
|
|
3036e2d523 | ||
|
|
1bab2d0025 | ||
|
|
4cac6c659e | ||
|
|
c7c59238e1 | ||
|
|
f51e74c066 | ||
|
|
52f8801638 | ||
|
|
4e5c5a7073 | ||
|
|
436f3879c4 | ||
|
|
c1395e26d4 | ||
|
|
3750d6ddb1 | ||
|
|
45c3601b49 | ||
|
|
957da1d040 | ||
|
|
43932eb6b3 | ||
|
|
024ddeefb4 | ||
|
|
94190b5cd7 | ||
|
|
5d72f90a0f | ||
|
|
90c30023c2 | ||
|
|
d39a89659b | ||
|
|
79f4386b62 | ||
|
|
39c4d8ae96 | ||
|
|
c8b2abbb3e | ||
|
|
06b7bbd711 | ||
|
|
11afd15610 | ||
|
|
4951025e61 | ||
|
|
2337a122da | ||
|
|
072333bf48 | ||
|
|
2bd8924df7 | ||
|
|
23cdc3721d | ||
|
|
957e4ba0c0 | ||
|
|
71a19c63d8 | ||
|
|
657327e7ee | ||
|
|
efeea7cf0f | ||
|
|
7a4637368d | ||
|
|
2e6ccd078b | ||
|
|
827197f916 | ||
|
|
c8454ec0c1 | ||
|
|
7127a77d92 | ||
|
|
b23912b52f | ||
|
|
4b21148a03 | ||
|
|
2d5ef95e54 | ||
|
|
b5e2d376dd | ||
|
|
c40b337edc | ||
|
|
f8583642a8 | ||
|
|
707f28df16 | ||
|
|
dd78da089d | ||
|
|
c4ea65ed70 | ||
|
|
aabba806c4 | ||
|
|
88167fc42d | ||
|
|
e4d7005e46 | ||
|
|
5ee27f7ed7 | ||
|
|
9a4492c401 | ||
|
|
39a2aee5a0 | ||
|
|
5184ef170f | ||
|
|
29a35cf1cc | ||
|
|
f26516ecae | ||
|
|
f26a7ad2b1 | ||
|
|
96e0a29573 | ||
|
|
f30d667ca8 | ||
|
|
8db7a1d6d9 | ||
|
|
d285a0512e | ||
|
|
256d0d5c84 | ||
|
|
b808e1f9d1 | ||
|
|
07cd781ec1 | ||
|
|
9115b687f4 | ||
|
|
7c51377203 | ||
|
|
193cd02072 | ||
|
|
dbb6d91f0c | ||
|
|
a82714e811 | ||
|
|
bcd1bbac62 | ||
|
|
2fde0e68ca | ||
|
|
e6e9b1c5ae | ||
|
|
48b789c51d | ||
|
|
433b39209d | ||
|
|
b6df7a9f33 | ||
|
|
ad1d55537f | ||
|
|
9982d2c6ef | ||
|
|
1e3f622a98 | ||
|
|
ce05d5f6a6 | ||
|
|
19378e2095 | ||
|
|
0d992f1e50 | ||
|
|
de7cabfd54 | ||
|
|
cfe73a00ee | ||
|
|
35a7acbbd9 | ||
|
|
20eebca395 | ||
|
|
7c2a4deb1a | ||
|
|
e227e6a0f4 | ||
|
|
e015c29a3d | ||
|
|
a2859937e2 | ||
|
|
cd26252444 | ||
|
|
47894a6e74 | ||
|
|
bcf94180d5 | ||
|
|
6d2eeda28c | ||
|
|
049c768013 | ||
|
|
ffae488d1e | ||
|
|
3ea0ae6e5b | ||
|
|
530c25655c | ||
|
|
ca830fd64c | ||
|
|
4272476230 | ||
|
|
b7e44246ce | ||
|
|
33b9578fd1 | ||
|
|
df0a96843d | ||
|
|
5b5f7dfc12 | ||
|
|
8b094adcca | ||
|
|
de9d9ab844 | ||
|
|
2fd6d2f50b | ||
|
|
349c9eca4b | ||
|
|
1f119233d7 | ||
|
|
17c2d63892 | ||
|
|
79c76e913d | ||
|
|
6501480980 | ||
|
|
5ad9bbba37 | ||
|
|
f012448758 | ||
|
|
99b6d635d7 | ||
|
|
5f742627e9 | ||
|
|
a9e725002a | ||
|
|
49150f9b1e | ||
|
|
89aa1ba94c | ||
|
|
6aca313bd8 | ||
|
|
f76d5a958f | ||
|
|
b833a10de4 | ||
|
|
f3ce5632fb | ||
|
|
f5bf4c3831 | ||
|
|
08a3acc5e0 | ||
|
|
5b63034607 | ||
|
|
d4543032d9 | ||
|
|
254a91c3bd | ||
|
|
4c01ddaaef | ||
|
|
2993d1450a | ||
|
|
582c3a4c1a | ||
|
|
dd6b964405 | ||
|
|
16827bfbac | ||
|
|
3c4d72bb71 | ||
|
|
004036e019 | ||
|
|
ba06f80baa | ||
|
|
ee47428a80 | ||
|
|
1e40cae27b | ||
|
|
f5b7bb5549 | ||
|
|
115883f8d0 | ||
|
|
a73446a1c5 | ||
|
|
7501c4f76b | ||
|
|
9f038fae63 | ||
|
|
a61a520570 | ||
|
|
885783cd9a | ||
|
|
181f850c58 | ||
|
|
fe8742b580 | ||
|
|
daeba7caa9 | ||
|
|
1340e6dc1b | ||
|
|
cba7655f0d | ||
|
|
ac7e2a9aef | ||
|
|
fcc0bfbf32 | ||
|
|
a7e86bdb64 | ||
|
|
c3eecd8d14 | ||
|
|
25e6da3ac5 | ||
|
|
a7e5786fee | ||
|
|
a6bccc3dd3 | ||
|
|
d8cd39dc3e | ||
|
|
6eacf833f5 | ||
|
|
dbdd417e0d | ||
|
|
4c8dd52f28 | ||
|
|
31a2d8a02b | ||
|
|
f246d57a7e | ||
|
|
4ae856630f | ||
|
|
8652baf2ae | ||
|
|
4a18853e8c | ||
|
|
a60be9d8c1 | ||
|
|
e16b47409c | ||
|
|
6f14cbe746 | ||
|
|
ea79c9c5dd | ||
|
|
650d13ed71 | ||
|
|
169b8b8e94 | ||
|
|
8cef4a5bcb | ||
|
|
70b40802cc | ||
|
|
416e707cda | ||
|
|
12578293bc | ||
|
|
042ab6850b | ||
|
|
09fc042630 | ||
|
|
c73d351bf1 | ||
|
|
4d4e0a9c2a | ||
|
|
2fd29b2347 | ||
|
|
f332068318 | ||
|
|
186c79f93c | ||
|
|
3770066485 | ||
|
|
17b0ffe52b | ||
|
|
d259b5bb78 | ||
|
|
f6c8d24177 | ||
|
|
ab3bd61d3c | ||
|
|
6a5cee8f0e | ||
|
|
549732fc8b | ||
|
|
09d400c6fb | ||
|
|
7e1cdafa78 | ||
|
|
434c0216d5 | ||
|
|
d5a0ae8e71 | ||
|
|
79e56c6a30 | ||
|
|
11cc1c3f25 | ||
|
|
8b343bcfb6 | ||
|
|
ecd83beb7d | ||
|
|
438f21fb11 | ||
|
|
dd1524cf31 | ||
|
|
0f85aa5384 | ||
|
|
4644a0ae96 | ||
|
|
84b3efe0fc | ||
|
|
511acbd5ff | ||
|
|
8749b3b354 | ||
|
|
b66e63d242 | ||
|
|
ba951238c3 | ||
|
|
a4eb76f1cf | ||
|
|
c486899dcf | ||
|
|
b212f0d5be | ||
|
|
caa534ff7f | ||
|
|
9c2fac6749 | ||
|
|
2a4f918a10 | ||
|
|
b45e2afe4c | ||
|
|
2c7237e5d9 | ||
|
|
26477e3150 | ||
|
|
cba8cb57d5 | ||
|
|
599b4822e5 | ||
|
|
fbd150b353 | ||
|
|
10b252e934 | ||
|
|
e9dfcdeb10 | ||
|
|
9cb2f27754 | ||
|
|
a090a83b7d | ||
|
|
992e661e4c | ||
|
|
3b993d114e | ||
|
|
d181d62466 | ||
|
|
968cef7a12 | ||
|
|
390c2395eb | ||
|
|
adc9444794 | ||
|
|
f086318082 | ||
|
|
1cef4400b9 | ||
|
|
1f879ac91e | ||
|
|
bec129d98e | ||
|
|
152c04e68f | ||
|
|
d6cdacef43 | ||
|
|
09891a075d | ||
|
|
9500bab5b7 | ||
|
|
231edd4bd4 | ||
|
|
433572e759 | ||
|
|
3ec772e87f | ||
|
|
ae8287157c | ||
|
|
f005907b41 | ||
|
|
8ea16044f1 | ||
|
|
e787a28353 | ||
|
|
6925d9564c | ||
|
|
ccd4ea785a | ||
|
|
63e88c09d4 | ||
|
|
296191b502 | ||
|
|
af0151f446 | ||
|
|
2bdfaa167e | ||
|
|
cd96476f9e | ||
|
|
9b0545aa1a | ||
|
|
63823123f8 | ||
|
|
e91728be98 | ||
|
|
e7ecbf1245 | ||
|
|
28c2363b67 | ||
|
|
21a3d4fb55 | ||
|
|
4b459a3ed1 | ||
|
|
ebc6a1b842 | ||
|
|
b72b0f269a | ||
|
|
4cbcd69ed2 | ||
|
|
6ef8b7748c | ||
|
|
8b567cb976 | ||
|
|
d8c231b9ce | ||
|
|
cc4347c881 | ||
|
|
7cc572feb5 | ||
|
|
96d1d1feb4 | ||
|
|
a7d9bd9ab5 | ||
|
|
1cdfdf1d43 | ||
|
|
0762a5e689 | ||
|
|
3e2906ccf8 | ||
|
|
13761e032c | ||
|
|
fb8fa3fa54 | ||
|
|
b89bf5933b | ||
|
|
1c4f404fd2 | ||
|
|
9fe1560f1a | ||
|
|
6a9cca37c6 | ||
|
|
bfde75d4b1 | ||
|
|
a83f98580d | ||
|
|
673542d8e4 | ||
|
|
81c5d89a25 | ||
|
|
bf0bcb0b96 | ||
|
|
ac7a664303 | ||
|
|
182dc67a49 | ||
|
|
27ee82d17c | ||
|
|
9405e4e45d | ||
|
|
8616769e32 | ||
|
|
5d85c4697b | ||
|
|
c54a2b7353 | ||
|
|
35075e88e3 | ||
|
|
1266d34176 | ||
|
|
66ddf0e3ca | ||
|
|
88ab129737 | ||
|
|
bcd293a255 | ||
|
|
4a5ebe6dbd | ||
|
|
ef1c3b1b3b | ||
|
|
f7e68ffb6b | ||
|
|
2cf2153c4d | ||
|
|
7e7d0025fa | ||
|
|
8252b6486e | ||
|
|
378041cb16 | ||
|
|
ee5ff07565 | ||
|
|
80c63dd414 | ||
|
|
e182366566 | ||
|
|
acee89cce3 | ||
|
|
3ef3d14c10 | ||
|
|
74365780a7 | ||
|
|
f6ad80370f | ||
|
|
87eb544936 | ||
|
|
cde0389380 | ||
|
|
9e46ffc4e1 | ||
|
|
f3c35de780 | ||
|
|
75f5378c8c | ||
|
|
19d32127e8 | ||
|
|
2f00aa7750 | ||
|
|
07f5dc68b5 | ||
|
|
96a39d7037 | ||
|
|
409f1c4230 | ||
|
|
c3d2f9aeea | ||
|
|
380b3dd1f6 | ||
|
|
c15a6009a2 | ||
|
|
e4e7c364fd | ||
|
|
438361eed2 | ||
|
|
684b35f2df | ||
|
|
1d603ae76f | ||
|
|
a342b23890 | ||
|
|
c0dde2eaa7 | ||
|
|
6245fe9553 | ||
|
|
fb5be9e2aa | ||
|
|
918620a7dc | ||
|
|
d2855449f0 | ||
|
|
f59326c0ae | ||
|
|
033b9ed035 | ||
|
|
5c299767ec | ||
|
|
818701cd07 | ||
|
|
9b5e63aa25 | ||
|
|
1ad285bd79 | ||
|
|
4507bb179a | ||
|
|
2dd79295a9 | ||
|
|
b21d840e60 | ||
|
|
f3fa40bb0a | ||
|
|
d8e14de0cf | ||
|
|
f7b96eceeb | ||
|
|
6f760939f3 | ||
|
|
5273ad0c5f | ||
|
|
ac12abfb8b | ||
|
|
e5146e7f53 | ||
|
|
62d1210872 | ||
|
|
0d0177cd40 | ||
|
|
227ecf9c9d | ||
|
|
562cd50762 | ||
|
|
ec56d530a6 | ||
|
|
6350714508 | ||
|
|
1b251dad6a | ||
|
|
7765b51a55 | ||
|
|
ff6ba6a8e9 | ||
|
|
ce3485c823 | ||
|
|
90a99d3a79 | ||
|
|
7248dc4fef | ||
|
|
d704db55fa | ||
|
|
0f581e47b1 | ||
|
|
48013f9b3c | ||
|
|
258c8ce989 | ||
|
|
c56a703028 | ||
|
|
4b9ce1b067 | ||
|
|
39b56725dd | ||
|
|
b281b18a4e | ||
|
|
b85487375d | ||
|
|
9ccdc0cf7e | ||
|
|
51b1bcf507 | ||
|
|
0afe598f3c | ||
|
|
4227b0c702 | ||
|
|
2a4e4a4e2e | ||
|
|
a9fa8291de | ||
|
|
007c0abc95 | ||
|
|
f9752b7090 | ||
|
|
b44b91f8cc | ||
|
|
352721540a | ||
|
|
1ab5f49c3b | ||
|
|
976e6e397a | ||
|
|
e95139b79e | ||
|
|
a75f50dcf6 | ||
|
|
87334c586c | ||
|
|
eddec70a99 | ||
|
|
d1d3279c8e | ||
|
|
13ff1dfb18 | ||
|
|
e0d09132dd | ||
|
|
99478e7f33 | ||
|
|
02087c735a | ||
|
|
cd13d588d6 | ||
|
|
6efc23cc15 | ||
|
|
5c28711b26 | ||
|
|
e9ae57aff5 | ||
|
|
92e4b1749e | ||
|
|
854eed74d7 | ||
|
|
7c5ef3aa8a | ||
|
|
78670b5d90 | ||
|
|
f43d54b6f6 | ||
|
|
db0dd75e27 | ||
|
|
d6d1649975 | ||
|
|
f0f0e40897 | ||
|
|
43c1116ac7 | ||
|
|
225f30a257 | ||
|
|
ae03436592 | ||
|
|
8a6014fd02 | ||
|
|
dcc0fafe66 | ||
|
|
bc33679a1f | ||
|
|
d69efe76e5 | ||
|
|
11babe4293 | ||
|
|
2ba7492f24 | ||
|
|
6c65ffb701 | ||
|
|
864e30b3db | ||
|
|
b9124ef873 | ||
|
|
77165a5ffb | ||
|
|
54a519de0b | ||
|
|
462d38373f | ||
|
|
44234422d0 | ||
|
|
c71fcf51c1 | ||
|
|
33cc4b2aad | ||
|
|
6485356c74 | ||
|
|
d0476a93ba | ||
|
|
2eb3548008 | ||
|
|
028a58c2ae | ||
|
|
7675fc11b6 | ||
|
|
7a10a9e8f2 | ||
|
|
8ee869830b | ||
|
|
63ecd7b2a2 | ||
|
|
a125076033 | ||
|
|
12153f5783 | ||
|
|
fdcec16181 | ||
|
|
0c4d653921 | ||
|
|
f488f18a55 | ||
|
|
6164dd8f5f | ||
|
|
270062cfe4 | ||
|
|
014e197a41 | ||
|
|
bed587d6ba | ||
|
|
c15934fdea | ||
|
|
385516f373 | ||
|
|
c50f5e7728 | ||
|
|
494bd7368d | ||
|
|
b6e8f4c1a7 | ||
|
|
392e97df2c | ||
|
|
45dbd8c4b2 | ||
|
|
a0ac7d3324 | ||
|
|
4dd7ce5b98 | ||
|
|
1a96101672 | ||
|
|
88f40ab457 | ||
|
|
70403042d2 | ||
|
|
ff5a9fa3a9 | ||
|
|
5ead664cf9 | ||
|
|
bba2b6f2e8 | ||
|
|
4b25571e1a | ||
|
|
407d0eaeac | ||
|
|
05bb3a5fa9 | ||
|
|
714a72c849 | ||
|
|
9ba8f149f7 | ||
|
|
c9bb38c036 | ||
|
|
3241f1cf41 | ||
|
|
8a7099a6ab | ||
|
|
65c6adcdb2 | ||
|
|
f3f2e69bcf | ||
|
|
335f0a3d6f | ||
|
|
a7e711850c | ||
|
|
6fb2a7ce76 | ||
|
|
56a6e34847 | ||
|
|
cfa4c869ca | ||
|
|
d548fbcb74 | ||
|
|
d40fbced1a | ||
|
|
21c251b40b | ||
|
|
ec3371085b | ||
|
|
3779f38c5d | ||
|
|
5b62fe2be7 | ||
|
|
ea223bbcb4 | ||
|
|
7f4a56149a | ||
|
|
52a620c479 | ||
|
|
593aaf8039 | ||
|
|
cebb6ea626 | ||
|
|
337dc1c4d5 | ||
|
|
e110f942e8 | ||
|
|
6bd5f9dab1 | ||
|
|
09149c559d | ||
|
|
f9a1130e4b | ||
|
|
91304233aa | ||
|
|
99286578c1 | ||
|
|
81888d9aa5 | ||
|
|
f2e4b1b94a | ||
|
|
ab269ad740 | ||
|
|
5a1df75526 | ||
|
|
b74ed1d14e | ||
|
|
d087db38e3 | ||
|
|
ff8c406823 | ||
|
|
7e12a75bea | ||
|
|
aa7fb09399 | ||
|
|
a805b3fe90 | ||
|
|
63d9122440 | ||
|
|
f9293c9c92 | ||
|
|
4892fd5817 | ||
|
|
cf4a8ae98d | ||
|
|
f0edfeeebf | ||
|
|
4d54ad35ff | ||
|
|
b6b512f788 | ||
|
|
a6076eb6ac | ||
|
|
01b74f0a6e | ||
|
|
6c6752c348 | ||
|
|
73873ac193 | ||
|
|
6542dad7bd | ||
|
|
9bf4a2b555 | ||
|
|
66d18a4469 | ||
|
|
7a489067e6 | ||
|
|
600d6de132 | ||
|
|
48e35e7abd | ||
|
|
8613e9d734 | ||
|
|
9ed277d80d | ||
|
|
26345d00a3 | ||
|
|
be70eea0f8 | ||
|
|
01357d9ce4 | ||
|
|
05afafbc45 | ||
|
|
68f7272128 | ||
|
|
caa0ab723a | ||
|
|
ee0d6002c8 | ||
|
|
48f0d04305 | ||
|
|
6516b80bf0 | ||
|
|
b0403ff94b | ||
|
|
77f88edf08 | ||
|
|
be70664c84 | ||
|
|
37ca992233 | ||
|
|
620904de1c | ||
|
|
9c0fac5c44 | ||
|
|
8846c5a9fe | ||
|
|
880d2a8570 | ||
|
|
45b6591518 | ||
|
|
c6ce99d527 | ||
|
|
7a7861fd9c | ||
|
|
3c11630a6c | ||
|
|
3b9f4c9884 | ||
|
|
0757fc4352 | ||
|
|
c1af721ad2 | ||
|
|
0ea04394f9 | ||
|
|
576c178b4f | ||
|
|
674708cea6 | ||
|
|
179b05f992 | ||
|
|
e2c768bb56 | ||
|
|
79e492b230 | ||
|
|
708bc5c302 | ||
|
|
9543cd5b5f | ||
|
|
0bc8313897 | ||
|
|
91986926cb | ||
|
|
ac638add7a | ||
|
|
9551783d49 | ||
|
|
85cf2b3e91 | ||
|
|
f98ccb9e44 | ||
|
|
066d50e492 | ||
|
|
6c823e86fe | ||
|
|
6d3ea577d5 | ||
|
|
2826e39ea2 | ||
|
|
d855f04612 | ||
|
|
99eb93e66f | ||
|
|
e91110d049 | ||
|
|
8e1bb8519c | ||
|
|
61df01ed1c | ||
|
|
c219aa83b1 | ||
|
|
71109b397d | ||
|
|
4fe4c2981d | ||
|
|
2f9f2f722c | ||
|
|
40009d018c | ||
|
|
251480fd4a | ||
|
|
6295145d5b | ||
|
|
17f2e67334 | ||
|
|
fe4130a846 | ||
|
|
141201b7aa | ||
|
|
3b3c511572 | ||
|
|
8c6cf8ee22 | ||
|
|
231fd36ce9 | ||
|
|
fb9dd0a899 | ||
|
|
d98bcdb4e8 | ||
|
|
f94a87e6d5 | ||
|
|
1501d5e71e | ||
|
|
a7d955266d | ||
|
|
9633a6c176 | ||
|
|
9d50090dbd | ||
|
|
8b96a8e654 | ||
|
|
453288bf77 | ||
|
|
26fb0ec2e9 | ||
|
|
2671052cad | ||
|
|
7f1bcd69c8 | ||
|
|
5fe83af514 | ||
|
|
89dc2f09fc | ||
|
|
7ce564409a | ||
|
|
2e34069d14 | ||
|
|
e435501501 | ||
|
|
51402637c6 | ||
|
|
44593f7a75 | ||
|
|
48596efa77 | ||
|
|
3e323df70d | ||
|
|
0d89cef519 | ||
|
|
f758fdf8f3 | ||
|
|
44b9f06087 | ||
|
|
d1155d5e7a | ||
|
|
51ccd029ca | ||
|
|
1df83dac91 | ||
|
|
a3c1d643fd | ||
|
|
4350e311e7 | ||
|
|
89ec9355bd | ||
|
|
f2be7220f3 | ||
|
|
0cbac252a5 | ||
|
|
3ea60971be | ||
|
|
8ea76e2016 | ||
|
|
86d2d732eb | ||
|
|
55ce84a5ae | ||
|
|
0f0e4de682 | ||
|
|
ad60372cf2 | ||
|
|
3cf5fd7cbd | ||
|
|
ce090566cc | ||
|
|
866f645eed | ||
|
|
64f3bebd3d | ||
|
|
239cc461d5 | ||
|
|
b832784977 | ||
|
|
0f37b0be54 | ||
|
|
bb428af3af | ||
|
|
1c4d9704f2 | ||
|
|
53a5eae721 | ||
|
|
049ab257e2 | ||
|
|
0ece5319ea | ||
|
|
b847cc1178 | ||
|
|
422da3e1ba | ||
|
|
868c6baebf | ||
|
|
9a3cf167ed | ||
|
|
cdf47ebab0 | ||
|
|
929d1f945b | ||
|
|
2671242d2c | ||
|
|
78cff8dea8 | ||
|
|
7ac3840831 | ||
|
|
556ee6df01 | ||
|
|
2eca28e497 | ||
|
|
76ff5d49e2 | ||
|
|
2a919aa6b7 | ||
|
|
c83f806e4c | ||
|
|
afbfd38dfd | ||
|
|
6874916ce0 | ||
|
|
143c4fc7e4 | ||
|
|
f85e945a32 | ||
|
|
d0110c9a4f | ||
|
|
4307768bee | ||
|
|
88773e3232 | ||
|
|
8f32772f83 | ||
|
|
17b3c28d91 | ||
|
|
45945d9a13 | ||
|
|
ba9741a084 | ||
|
|
3bcad371d2 | ||
|
|
1e9bf68671 | ||
|
|
f57df6a536 | ||
|
|
793536d2d3 | ||
|
|
9a348da34f | ||
|
|
4819bf63b6 | ||
|
|
5777d49861 | ||
|
|
7540c61fde | ||
|
|
308da4cbac | ||
|
|
615af41de8 | ||
|
|
7c473a4e3f | ||
|
|
79b4f9821b | ||
|
|
80825ee701 | ||
|
|
aa0e60b091 | ||
|
|
718cfb682d | ||
|
|
66f0426e6a | ||
|
|
145671ecdd | ||
|
|
43d71f7e49 | ||
|
|
150de771d5 | ||
|
|
50da728abf | ||
|
|
656ce6ecad | ||
|
|
8a758dffec | ||
|
|
52bd538ed0 | ||
|
|
115c5ac890 | ||
|
|
0f7d15a4d0 | ||
|
|
5b6e07d5d3 | ||
|
|
8579ed322d | ||
|
|
44464b605d | ||
|
|
e8124dd280 | ||
|
|
0105fc2087 | ||
|
|
39e7b26128 | ||
|
|
ddbc13fc27 | ||
|
|
80660fa6cf | ||
|
|
b4a94e8da5 | ||
|
|
051c9a8c85 | ||
|
|
840b1ea4a2 | ||
|
|
ea57695a31 | ||
|
|
90778bc84c | ||
|
|
949216325f | ||
|
|
cdb521de1f | ||
|
|
e50b39c559 | ||
|
|
80afb497e0 | ||
|
|
e83a12aaee | ||
|
|
461860bb17 | ||
|
|
cff4e3e6b0 | ||
|
|
dddf0b35a2 | ||
|
|
35ec2bf215 | ||
|
|
607b60b323 | ||
|
|
bb6ad72962 | ||
|
|
4fb8420d69 | ||
|
|
74af19a9d9 | ||
|
|
737ac70e6e | ||
|
|
bfc72b735c | ||
|
|
323412f935 | ||
|
|
db34ba4995 | ||
|
|
15d7eb6d91 | ||
|
|
e2b95df2e4 | ||
|
|
1117094412 | ||
|
|
4bab076642 | ||
|
|
d602818f67 | ||
|
|
1a76321062 | ||
|
|
4b056529dd | ||
|
|
bdbf3ba5b1 | ||
|
|
aab9a650b0 | ||
|
|
f8487f07a6 | ||
|
|
e38721fa69 | ||
|
|
18e52f2f10 | ||
|
|
f1300410b8 | ||
|
|
e17059f1f7 | ||
|
|
f3e9f7cf06 | ||
|
|
63ed24d136 | ||
|
|
66008cd767 | ||
|
|
1852c1b5c4 | ||
|
|
9a4fc2fc73 | ||
|
|
6846a78833 | ||
|
|
d3d9e85a7f | ||
|
|
f867b6b2ea | ||
|
|
6b38954694 | ||
|
|
9eb350df30 | ||
|
|
639aa5e251 | ||
|
|
f089e26998 | ||
|
|
9070a6aadc | ||
|
|
c68e135c66 | ||
|
|
8693b4fe8f | ||
|
|
9390a402ff | ||
|
|
7fda2c5f88 | ||
|
|
cb394007a4 | ||
|
|
cd92910281 | ||
|
|
7f0b2e2b13 | ||
|
|
bdc44d46c8 | ||
|
|
8d8480469a | ||
|
|
a91fe6db36 | ||
|
|
20d734aa80 | ||
|
|
f053bbd544 | ||
|
|
7eba26cab1 | ||
|
|
5f77dd0adb | ||
|
|
4ef94d3c60 | ||
|
|
36006045e2 | ||
|
|
d5d025c2c9 | ||
|
|
5b7053d500 | ||
|
|
ce2e60c268 | ||
|
|
8e9b575c37 | ||
|
|
beab7d5a4f | ||
|
|
d2f5fc4d69 | ||
|
|
fb9a7f693b | ||
|
|
1d2d636270 | ||
|
|
37ec5ee442 | ||
|
|
5ed67cf5f8 | ||
|
|
76fc47d5bd | ||
|
|
aa856beee1 | ||
|
|
e6f2cc3eda | ||
|
|
02fd45587b | ||
|
|
7cef6eeb61 | ||
|
|
da919bc43b | ||
|
|
2b661d6c5b | ||
|
|
ee0ced63ef | ||
|
|
736dad5819 | ||
|
|
11f36e8a22 | ||
|
|
2cddf0b313 | ||
|
|
36a2d449b7 | ||
|
|
b6786456a2 | ||
|
|
76e8e1af6f | ||
|
|
ff55838a54 | ||
|
|
b14b6828cc | ||
|
|
be7fb67988 | ||
|
|
ae0be45d7d | ||
|
|
ba237d5dc4 | ||
|
|
bdf5cd8751 | ||
|
|
9a6d309840 | ||
|
|
9a6e92a58c | ||
|
|
1bc018918b | ||
|
|
f32f8f5cdd | ||
|
|
39585de3f0 | ||
|
|
9ce81fc68e | ||
|
|
0d56f0da98 | ||
|
|
14a3d8da12 | ||
|
|
e4fa99b865 | ||
|
|
96af2cb573 | ||
|
|
f53ec58b2f | ||
|
|
2ff30dda83 | ||
|
|
c0972f8faf | ||
|
|
9663e1aa7e | ||
|
|
d83a61b30a | ||
|
|
96d83da9b7 | ||
|
|
f1d881e0ba | ||
|
|
d1285c7e04 | ||
|
|
d4476e2d4c | ||
|
|
3124d51381 | ||
|
|
b6ae1a79d4 | ||
|
|
42d7b598bf | ||
|
|
052e828d5a | ||
|
|
55d4f8da6b | ||
|
|
1c5a4bbacc | ||
|
|
565d4bdeec | ||
|
|
3d9ef7d252 | ||
|
|
161bcbb236 | ||
|
|
c8af0ab5bc | ||
|
|
98e9c167c5 | ||
|
|
ed815c5767 | ||
|
|
f6e53ac91f | ||
|
|
3e5df50f9e | ||
|
|
1e28a93c5f | ||
|
|
717bdd3550 | ||
|
|
3bee514bb9 | ||
|
|
678d4b8db7 | ||
|
|
d76e5e7f9b | ||
|
|
9629192305 | ||
|
|
eef7debdba | ||
|
|
138d9f7f46 | ||
|
|
e4abd9ec2f | ||
|
|
8efce72e26 | ||
|
|
15ebca2d11 | ||
|
|
6583489523 | ||
|
|
5610d52813 | ||
|
|
618b61dd60 | ||
|
|
2de58f7a3b | ||
|
|
2bd94158f9 | ||
|
|
4e7ab43ac9 | ||
|
|
33529d0cfd | ||
|
|
a5b929bdf5 | ||
|
|
d10bd3358d | ||
|
|
ffe928fbe8 | ||
|
|
fd61739d96 | ||
|
|
e1602a5655 | ||
|
|
a936302fd2 | ||
|
|
7f0d4df6ca | ||
|
|
35ab0c67c5 | ||
|
|
090633140f | ||
|
|
8efe02c2ef | ||
|
|
2dbcaf029c | ||
|
|
ce758534bd | ||
|
|
15caf70170 | ||
|
|
c07c3a3a4f | ||
|
|
b9000af55e | ||
|
|
ed15ba29bb | ||
|
|
2fb8da022a | ||
|
|
ed65088cb8 | ||
|
|
f367542096 | ||
|
|
00e457542d | ||
|
|
b0c423b2dd | ||
|
|
eb5e3d637c | ||
|
|
4acd24b829 | ||
|
|
f8576834fe | ||
|
|
1e9888a8b5 | ||
|
|
d99b6643e9 | ||
|
|
0b98d98867 | ||
|
|
d040b0faf5 | ||
|
|
d53c20da56 | ||
|
|
fad035699f | ||
|
|
c7ab2b93a3 | ||
|
|
4b75144276 | ||
|
|
99edcf68c1 | ||
|
|
9b6f1ce955 | ||
|
|
b570020944 | ||
|
|
e91ba4ef79 | ||
|
|
a1fbefb13f | ||
|
|
340592d951 | ||
|
|
a1c0bf7dec | ||
|
|
a62f20469e | ||
|
|
3f1f78315b | ||
|
|
12d8bc75cd | ||
|
|
c1cf02ee9f | ||
|
|
7ac240af76 | ||
|
|
82c34a33b5 | ||
|
|
d2330337ef | ||
|
|
af38bd0383 | ||
|
|
c0a9ede377 | ||
|
|
555ba3eb73 | ||
|
|
6f0e757ad6 | ||
|
|
077b8fee96 | ||
|
|
643df47437 | ||
|
|
9e1ea4678d | ||
|
|
f3576b678b | ||
|
|
2b49bce998 | ||
|
|
896048ffff | ||
|
|
04cb14f790 | ||
|
|
bd22b0c08b | ||
|
|
95ce52bbeb | ||
|
|
6b411f5cce | ||
|
|
c15b0d178b | ||
|
|
f5ffb69675 | ||
|
|
24e59d970f | ||
|
|
4ece4b66cd | ||
|
|
7852d244bb | ||
|
|
d1c2487ba4 | ||
|
|
4ea789efcf | ||
|
|
43fc97c671 | ||
|
|
a20378d5cb | ||
|
|
7c0384c96b | ||
|
|
7d4419b300 | ||
|
|
393af9b5c5 | ||
|
|
559e423a1d | ||
|
|
a2d68e14e6 | ||
|
|
580b67d9ed | ||
|
|
080654f703 | ||
|
|
002a002749 | ||
|
|
7e888e46f9 | ||
|
|
199ca94acd | ||
|
|
67455bd47d | ||
|
|
fbb0e252c5 | ||
|
|
2566972ac7 | ||
|
|
9455294060 | ||
|
|
6870b42a1a | ||
|
|
32cd414a51 | ||
|
|
35f63b7075 | ||
|
|
f9097b11b6 | ||
|
|
dc5acdf729 | ||
|
|
e5fb25daee | ||
|
|
33b6867c02 | ||
|
|
d572973b60 | ||
|
|
3d240f0f7d | ||
|
|
3a4973d760 | ||
|
|
811c9716a2 | ||
|
|
771f6db89a | ||
|
|
97f515f573 | ||
|
|
c589dfb281 | ||
|
|
82efe5b4d1 | ||
|
|
765f593b88 | ||
|
|
21e5de25cb | ||
|
|
4333e44f6d | ||
|
|
7070fd886b | ||
|
|
89480a9018 | ||
|
|
19ce873037 | ||
|
|
977007b427 | ||
|
|
218c1c9d9a | ||
|
|
f358ac9d9c | ||
|
|
58fe2b4582 | ||
|
|
211624b1a9 | ||
|
|
6874369a48 | ||
|
|
f8c52d3577 | ||
|
|
376bf5314d | ||
|
|
2346df67a0 | ||
|
|
e63c7b43e1 | ||
|
|
578691fe8c | ||
|
|
189d8a82d5 | ||
|
|
9412d9cc28 | ||
|
|
75b2bfa14c | ||
|
|
7fcb5c8aa3 | ||
|
|
9827711111 | ||
|
|
16aecd65e6 | ||
|
|
c143ecc6ae | ||
|
|
2935f9e205 | ||
|
|
a6a33a79d4 | ||
|
|
82f9d8ddee | ||
|
|
daa6012b36 | ||
|
|
5001c82f23 | ||
|
|
59dbad9abf | ||
|
|
945c7cc7b8 | ||
|
|
3391f7646c | ||
|
|
88070aa2b2 | ||
|
|
c792296746 | ||
|
|
18a13f777d | ||
|
|
469529b324 | ||
|
|
4715a5ab9d | ||
|
|
be305162a6 | ||
|
|
7a1bc16e9d | ||
|
|
eb2c80deb8 | ||
|
|
0863b77bf0 | ||
|
|
769a698509 | ||
|
|
53870b2c81 | ||
|
|
e198a5df88 | ||
|
|
ac947f698b | ||
|
|
ecabd62b6b | ||
|
|
f350d200ac | ||
|
|
97d5a3f7ef | ||
|
|
f15f3efc3f | ||
|
|
7563b6b946 | ||
|
|
421c53e6be | ||
|
|
3db8666951 | ||
|
|
ecc6e01cf9 | ||
|
|
becf81db00 | ||
|
|
92f5b337c9 | ||
|
|
3ddf884c23 | ||
|
|
116117af55 | ||
|
|
0980bcfca5 | ||
|
|
20e2e8ded6 | ||
|
|
13af0b7b2b | ||
|
|
cbcbfdcbf1 | ||
|
|
38eb294667 | ||
|
|
71d16ff906 | ||
|
|
395058d771 | ||
|
|
d8af7c454c | ||
|
|
2f10084e7a | ||
|
|
5af387b32d | ||
|
|
4b7144f705 | ||
|
|
0fbbbb6485 | ||
|
|
f033d78785 | ||
|
|
2ea79eb57d | ||
|
|
226ee0db9d | ||
|
|
8a62f21e84 | ||
|
|
c353c39086 | ||
|
|
2b2c877ab2 | ||
|
|
016af4bfee | ||
|
|
b3d26d91de | ||
|
|
a7a7f409eb | ||
|
|
f44ccec712 | ||
|
|
1c0887733c | ||
|
|
7ee3c35785 | ||
|
|
01b725cf38 | ||
|
|
1ac6d90633 | ||
|
|
9704193237 | ||
|
|
69b150b391 | ||
|
|
7ffb3edda5 | ||
|
|
046eb68ce6 | ||
|
|
816d80a27c | ||
|
|
957037e5f4 | ||
|
|
9ca179a71f | ||
|
|
cb4d96f1ba | ||
|
|
7d57522775 | ||
|
|
902565f1b1 | ||
|
|
2f8de436af | ||
|
|
38bd035d99 | ||
|
|
88b6d1a3ca | ||
|
|
a74878e7bb | ||
|
|
2b6eba7c4d | ||
|
|
0de1b86ef5 | ||
|
|
ae0ab6471b | ||
|
|
c24cdaa8a4 | ||
|
|
df1442dd8a | ||
|
|
b17d5306db | ||
|
|
88d5294b8e | ||
|
|
8c3405d01f | ||
|
|
9f83ba700c | ||
|
|
ae147211ca | ||
|
|
01d305eba0 | ||
|
|
08c30574a9 | ||
|
|
39c4725a2f | ||
|
|
7002aeefaf | ||
|
|
f1201cc5bc | ||
|
|
0b99d4ac52 | ||
|
|
642cb701dd | ||
|
|
66d6aee115 | ||
|
|
38d8eb1108 | ||
|
|
f9941c5dff | ||
|
|
855a6f447a | ||
|
|
fa0a1f8553 | ||
|
|
0d1fee1636 | ||
|
|
ec8269332f | ||
|
|
00fe9400e6 | ||
|
|
8389b1e151 | ||
|
|
2289d10d6c | ||
|
|
b30af4f144 | ||
|
|
041322c53f | ||
|
|
548968bcfc | ||
|
|
6d405b70e7 | ||
|
|
1b4d4acc63 | ||
|
|
6f498089fb | ||
|
|
8e27cba0f6 | ||
|
|
ae48041a96 | ||
|
|
bad16a4cdc | ||
|
|
07baf769dd | ||
|
|
ab409643f6 | ||
|
|
c745a61601 | ||
|
|
c4e8e83d1e | ||
|
|
9133f3d792 | ||
|
|
b779d584a5 | ||
|
|
05bb61b3ab | ||
|
|
5d2885e662 | ||
|
|
ef645c1058 | ||
|
|
52a476fd0a | ||
|
|
7386c45f06 | ||
|
|
1a508ddedf | ||
|
|
a8675f254a | ||
|
|
0f70cd789e | ||
|
|
b8f594f42c | ||
|
|
7857527ce1 | ||
|
|
05c41a5469 | ||
|
|
f11f8afdc4 | ||
|
|
fa499aa46d | ||
|
|
e8a7cc026f | ||
|
|
433ef6a8a7 | ||
|
|
fc4b5a7bcd | ||
|
|
bd43134d58 | ||
|
|
557970ba4e | ||
|
|
d3418e0067 | ||
|
|
b8d1845d4e | ||
|
|
32e360409d | ||
|
|
c54a778af9 | ||
|
|
ce25698f87 | ||
|
|
4d95cc838a | ||
|
|
67fa0a231e | ||
|
|
3c2e8c81c4 | ||
|
|
484d46252b | ||
|
|
a2e3c67298 | ||
|
|
b2ea05d8dd | ||
|
|
1477f47962 | ||
|
|
273ce49c14 | ||
|
|
96b6790646 | ||
|
|
38227ec878 | ||
|
|
11da632972 | ||
|
|
3721b9fe22 | ||
|
|
ecb697e5fb | ||
|
|
c754772280 | ||
|
|
5f2b4ba0b3 | ||
|
|
0ab60becfc | ||
|
|
1dcfb7d6dc | ||
|
|
3c0b44b365 | ||
|
|
ec4aec50ef | ||
|
|
9c86cfe056 | ||
|
|
6bb2337276 | ||
|
|
4702ca255b | ||
|
|
ab47aa36cc | ||
|
|
4bb14c4a4e | ||
|
|
1dd75162f9 | ||
|
|
a2242e3c27 | ||
|
|
26ecf494a9 | ||
|
|
659af5d0b3 | ||
|
|
382a5ee7fc | ||
|
|
7364496844 | ||
|
|
d342316b87 | ||
|
|
b38141da88 | ||
|
|
98f80f7dae | ||
|
|
c134ec6bfe | ||
|
|
4e3f759243 | ||
|
|
a5f2e0157b | ||
|
|
fd21032e51 | ||
|
|
c4f5f9b7d3 | ||
|
|
6baf5a7068 | ||
|
|
d3460174de | ||
|
|
f9f19628ca | ||
|
|
04e48fea5d | ||
|
|
3e99e22fce | ||
|
|
0b244d5ff7 | ||
|
|
703f2ff316 | ||
|
|
34a2bbdbae | ||
|
|
cd8697c1a4 | ||
|
|
ed2dc2dd51 | ||
|
|
2dfdc1b993 | ||
|
|
6f2d7f1194 | ||
|
|
30009ef127 | ||
|
|
051a422331 | ||
|
|
fab6489e9c | ||
|
|
a448614e4a | ||
|
|
84ad874b2a | ||
|
|
19ba978291 | ||
|
|
e304469e55 | ||
|
|
7ce9e2592a | ||
|
|
681b812c7b | ||
|
|
ee1ab6785d | ||
|
|
57704b6622 | ||
|
|
7fe804e0fc | ||
|
|
a71529b641 | ||
|
|
4055173bdb | ||
|
|
3f8841a276 | ||
|
|
15c38851bc | ||
|
|
05030ae817 | ||
|
|
255fa11371 | ||
|
|
a074c0bf74 | ||
|
|
6ccd649fc4 | ||
|
|
21dbea07dd | ||
|
|
4c21d9d127 | ||
|
|
766002b079 | ||
|
|
2ce430ec41 | ||
|
|
cf2b151045 | ||
|
|
92216179df | ||
|
|
a2a95b8591 | ||
|
|
4a22dc111a | ||
|
|
5df7ecc245 | ||
|
|
d4ef520f26 | ||
|
|
e0f8737865 | ||
|
|
37b13a54a7 | ||
|
|
d9d28d31d0 | ||
|
|
66bf5da3f5 | ||
|
|
840c721afc | ||
|
|
859e705a48 | ||
|
|
7375070b21 | ||
|
|
3e2eda6a71 | ||
|
|
798d327dcb | ||
|
|
f5ca9139e6 | ||
|
|
f35e8cfa51 | ||
|
|
0f6953711b | ||
|
|
e2c5e6f9ac | ||
|
|
5ef5d6ddba | ||
|
|
5b19a5d798 | ||
|
|
bf804e8923 | ||
|
|
f47b8b5528 | ||
|
|
c353f6787a | ||
|
|
1b7d5c1a5c | ||
|
|
956456f157 | ||
|
|
49077bd798 | ||
|
|
019a0287b2 | ||
|
|
a71dac28c0 | ||
|
|
155886e000 | ||
|
|
ed4c303d2e | ||
|
|
9da0db5f74 | ||
|
|
562a973c84 | ||
|
|
967980ddf7 | ||
|
|
81d3675a87 | ||
|
|
7be786bbaf | ||
|
|
f41c9be1f7 | ||
|
|
e88062d028 | ||
|
|
edb2828643 | ||
|
|
58c189cd0e | ||
|
|
012994847e | ||
|
|
d87801be5f | ||
|
|
6d78c0c104 | ||
|
|
3a83519122 | ||
|
|
a9f940ebed | ||
|
|
db73d9ef81 | ||
|
|
e2bd21c717 | ||
|
|
871215b7b5 | ||
|
|
a6153ef46f | ||
|
|
35475a6103 | ||
|
|
bf77ffc1a5 | ||
|
|
7a64a9a534 | ||
|
|
68e057b99c | ||
|
|
7338afff96 | ||
|
|
97ae7813aa | ||
|
|
c0f3667ac1 | ||
|
|
d5c5502abe | ||
|
|
194e8ffbd9 | ||
|
|
ef39458abd | ||
|
|
6a6907fb0a | ||
|
|
8bb7c4a4a6 | ||
|
|
91700e7ed0 | ||
|
|
661c2e6fc3 | ||
|
|
3d053a6149 | ||
|
|
34179e4f62 | ||
|
|
a23e5d9f50 | ||
|
|
1cbcbf70d9 | ||
|
|
0a7371aaec | ||
|
|
da13e2d861 | ||
|
|
5b18fa8c25 | ||
|
|
347231850a | ||
|
|
b1f9bdc26c | ||
|
|
03c9b95041 | ||
|
|
6e7e1d783b | ||
|
|
cfb9b0a029 | ||
|
|
b7ea6e5af6 | ||
|
|
44104df712 | ||
|
|
5de20d1c58 | ||
|
|
d156303740 | ||
|
|
6e36eb3554 | ||
|
|
f7f3891817 | ||
|
|
1ec28856ff | ||
|
|
9658e0b74d | ||
|
|
86cd8d4151 | ||
|
|
2418eb206e | ||
|
|
08fa715d26 | ||
|
|
52426de283 | ||
|
|
64b3da14c4 | ||
|
|
bf7341c52c | ||
|
|
e3490564a2 | ||
|
|
6218f0ed16 | ||
|
|
54e8e1ea98 | ||
|
|
4cd50fb3d5 | ||
|
|
590286a6c2 | ||
|
|
6c96650dcc | ||
|
|
7c83a74fd8 | ||
|
|
7b3f60cb3b | ||
|
|
bfc845088a | ||
|
|
e67d93a592 | ||
|
|
b518b980ae | ||
|
|
744bc1403a | ||
|
|
e11113073f | ||
|
|
3615818812 | ||
|
|
0cdef12caf | ||
|
|
dda8c6c053 | ||
|
|
8c3327f553 | ||
|
|
c037a14e1f | ||
|
|
bd661360ee | ||
|
|
317fabbc87 | ||
|
|
87161446c5 | ||
|
|
7db8b2e84b | ||
|
|
5f3fa2b317 | ||
|
|
64c15730a6 | ||
|
|
e5ab46b8ad | ||
|
|
3060d8cc2b | ||
|
|
f5d6ba462e | ||
|
|
81fdeece96 | ||
|
|
8f60439ef3 | ||
|
|
c5420ead90 | ||
|
|
99d372d03c | ||
|
|
1219a9822f | ||
|
|
d40c182af9 | ||
|
|
785e986a72 | ||
|
|
e8b80f455b | ||
|
|
2d545f1bf1 | ||
|
|
d4713dc7f4 | ||
|
|
cd96c13670 | ||
|
|
808607faf0 | ||
|
|
bc403f5c23 | ||
|
|
bfc67e1953 | ||
|
|
a186c16c34 | ||
|
|
f9be9d4c4b | ||
|
|
79fc3ce33f | ||
|
|
055ff8749e | ||
|
|
d36410e851 | ||
|
|
0fed5dca7f | ||
|
|
dd34ffc5b2 | ||
|
|
2cd5ac85f9 | ||
|
|
571f949f50 | ||
|
|
81e32957b2 | ||
|
|
4639016ffb | ||
|
|
dabc2b49dc | ||
|
|
2dec389c8c | ||
|
|
bfe5b5960e | ||
|
|
e352967a17 | ||
|
|
930917f285 | ||
|
|
b9747f7fbe | ||
|
|
5ac9dcec37 | ||
|
|
8328b43783 | ||
|
|
131fcfe144 | ||
|
|
709cb967b5 | ||
|
|
3370b83087 | ||
|
|
5c44bd500c | ||
|
|
ab8a345944 | ||
|
|
337dd56c87 | ||
|
|
de78ae30db | ||
|
|
3f64185389 | ||
|
|
5077cbbc9a | ||
|
|
4d522ba5f5 | ||
|
|
4f1180b3f5 | ||
|
|
577a3f2551 | ||
|
|
8623ab053e | ||
|
|
6d0f99eaf1 | ||
|
|
f9490d2652 | ||
|
|
9d321e4a31 | ||
|
|
b8c2625b80 | ||
|
|
8e42f328dc | ||
|
|
0c6b4efba5 | ||
|
|
0821ed4dae | ||
|
|
8bc38e25f9 | ||
|
|
7a7a4e6da2 | ||
|
|
f7d703ed1e | ||
|
|
443d7fd082 | ||
|
|
b6114625c1 | ||
|
|
4a3eb78f12 | ||
|
|
fa117a671a | ||
|
|
6448fb975a | ||
|
|
1c685ce0bb | ||
|
|
1662fa8d60 | ||
|
|
2787b1735b | ||
|
|
e58390e30b | ||
|
|
41a10a61bf | ||
|
|
fdcc7d5e7c | ||
|
|
50b39e462f | ||
|
|
4bc781f0da | ||
|
|
aca4c00083 | ||
|
|
77b820ad4d | ||
|
|
328f604236 | ||
|
|
2f77bf3d10 | ||
|
|
23eb55aa06 | ||
|
|
32b7356bc0 | ||
|
|
6091641ed9 | ||
|
|
e368213d18 | ||
|
|
58f9bb6fca | ||
|
|
79798199b8 | ||
|
|
c8d20f8479 | ||
|
|
c0498a60b4 | ||
|
|
faa01ddfc2 | ||
|
|
a2f628e267 | ||
|
|
66007b9121 | ||
|
|
9e0056b603 | ||
|
|
b15cc3a6af | ||
|
|
5393f869e7 | ||
|
|
f8088402e8 | ||
|
|
979ff7d2b8 | ||
|
|
bdbde58f42 | ||
|
|
1e26e0bd13 | ||
|
|
be3c00d17e | ||
|
|
d542bb67de | ||
|
|
a79cdfaa1c | ||
|
|
42db715421 | ||
|
|
2228d5a35d | ||
|
|
c434d0eafd | ||
|
|
414a3a971f | ||
|
|
b8a22a2561 | ||
|
|
bc1dc2f84f | ||
|
|
904c4f27aa | ||
|
|
b19e5435ef | ||
|
|
78fbcd829a | ||
|
|
a255844a92 | ||
|
|
c7a548c575 | ||
|
|
90a4bab114 | ||
|
|
a1633d146a | ||
|
|
87bf4b03df | ||
|
|
7731aea0d6 | ||
|
|
e66350111e | ||
|
|
7e5df68626 | ||
|
|
8e3e7de4ee | ||
|
|
0ee535fbd5 | ||
|
|
1b471d266c | ||
|
|
19a4f6ea1f | ||
|
|
7cc8d71224 | ||
|
|
b843475a0a | ||
|
|
027c0fa771 | ||
|
|
c08e76f110 | ||
|
|
b837fe7d15 | ||
|
|
d4d1bed408 | ||
|
|
8870295d54 | ||
|
|
79cd6e4ae2 | ||
|
|
8e5ea29c40 | ||
|
|
287b51a0bf | ||
|
|
28cbf952fa | ||
|
|
598c35a3aa | ||
|
|
b8b67a64ab | ||
|
|
7f6020ef34 | ||
|
|
aeed453e15 | ||
|
|
71dddcca4c | ||
|
|
46cdf79e20 | ||
|
|
d7af96823b | ||
|
|
5a228bd6b3 | ||
|
|
fcd95655ce | ||
|
|
7f5b57f8d2 | ||
|
|
f596877716 | ||
|
|
1802c8fd90 | ||
|
|
e05856facc | ||
|
|
45cfc3abb0 | ||
|
|
2d39579861 | ||
|
|
431f4bb4d5 | ||
|
|
7bc9d38176 | ||
|
|
7536447a8f | ||
|
|
059b796061 | ||
|
|
a89942484f | ||
|
|
c28be3fd65 | ||
|
|
5f1116795c | ||
|
|
4f54d2f6b2 | ||
|
|
6b7bedbe2d | ||
|
|
20ff225c31 | ||
|
|
af2700798e | ||
|
|
f9c280bbdc | ||
|
|
6ee31c2c3f | ||
|
|
cbd944f6f2 | ||
|
|
cc20748f31 | ||
|
|
c9545165aa | ||
|
|
05c10bf2e7 | ||
|
|
67aeae2094 | ||
|
|
1cc85a0647 | ||
|
|
988c0f8b4c | ||
|
|
62306fa5d6 | ||
|
|
641c5a49c3 | ||
|
|
5637402435 | ||
|
|
728d6c9a25 | ||
|
|
22d3ba2877 | ||
|
|
d1e032e010 | ||
|
|
80c4316826 | ||
|
|
3addeba256 | ||
|
|
c52db733b7 | ||
|
|
07a492e353 | ||
|
|
3c1ec478c2 | ||
|
|
f3f614c3de | ||
|
|
a6627ac6c6 | ||
|
|
8d1040518f | ||
|
|
ca5d17e6ec | ||
|
|
b9fab42510 | ||
|
|
22f1ef43c4 | ||
|
|
ffbd4bf26b | ||
|
|
4d6f93e975 | ||
|
|
cb45cff77f | ||
|
|
4718040345 | ||
|
|
afffefcce1 | ||
|
|
4580f47563 | ||
|
|
e51f4bb3a1 | ||
|
|
e8c8d1dee7 | ||
|
|
3559afaef7 | ||
|
|
fc29420eb3 | ||
|
|
023cd3fb75 | ||
|
|
2781d9f232 | ||
|
|
d31e5de449 | ||
|
|
245fcdf917 | ||
|
|
e3ef3ffa68 | ||
|
|
95c3608c3f | ||
|
|
7c2236dc96 | ||
|
|
b83ef0e352 | ||
|
|
2865871d04 | ||
|
|
7f7b76a11e | ||
|
|
52569e4c65 | ||
|
|
0a0ae6c83b | ||
|
|
6c8a41388e | ||
|
|
fe94e33d85 | ||
|
|
ca1be457cf | ||
|
|
550b6350ea | ||
|
|
76470c880d | ||
|
|
a315bd88b3 | ||
|
|
bb62930525 | ||
|
|
b7490f0002 | ||
|
|
42f3851339 | ||
|
|
34f39ac8d5 | ||
|
|
8c16330119 | ||
|
|
8323c21c3e | ||
|
|
2a3ca932a4 | ||
|
|
e339928caa | ||
|
|
3eeb025f23 | ||
|
|
f19c1f1baa | ||
|
|
003e6a6adb | ||
|
|
95d435d61c | ||
|
|
bbc4e1d767 | ||
|
|
ae46adf8b9 | ||
|
|
461ef988d3 | ||
|
|
307d21cc85 | ||
|
|
e2beac6570 | ||
|
|
75e455f078 | ||
|
|
19c832d370 | ||
|
|
9cd4afe1d4 | ||
|
|
3b00f07f78 | ||
|
|
0b5008c087 | ||
|
|
76f210db03 | ||
|
|
85c8d9f1b9 | ||
|
|
a795fc7f77 | ||
|
|
7742ab8220 | ||
|
|
3e235a8f18 | ||
|
|
30f9888f6a | ||
|
|
d1f8886e2b | ||
|
|
3c037f9aa6 | ||
|
|
c70346c57c | ||
|
|
bd40dd85af | ||
|
|
eacd929b0f | ||
|
|
0ff5f17b7d | ||
|
|
57fa01151e | ||
|
|
e7bc1fc74b | ||
|
|
897f35ab53 | ||
|
|
7f8b738a69 | ||
|
|
079302fb05 | ||
|
|
630fcc9e50 | ||
|
|
c1601ca487 | ||
|
|
d035b9cb80 | ||
|
|
8db5e4d8ba | ||
|
|
4d51bb39d7 | ||
|
|
7eb0231e08 | ||
|
|
6412461576 | ||
|
|
5732eb366b | ||
|
|
ed3df8bb68 | ||
|
|
787f531203 | ||
|
|
cf5d888901 | ||
|
|
1969e5f755 | ||
|
|
8d12ee0958 | ||
|
|
c3bbc89c5b | ||
|
|
625c7cf3c2 | ||
|
|
14f0321992 | ||
|
|
e5294c596a | ||
|
|
c83290a99a | ||
|
|
8c66310af0 | ||
|
|
5ae91bf89e | ||
|
|
d5dc1b7bdb | ||
|
|
864eee3349 | ||
|
|
88932e3a5e | ||
|
|
4ebc60ff00 | ||
|
|
b0cb63b05d | ||
|
|
1db40ee2d5 | ||
|
|
fd3f0ebd21 | ||
|
|
ce73069345 | ||
|
|
088f2748e3 | ||
|
|
d9a8c69f43 | ||
|
|
16ff503b6a | ||
|
|
68c78b9c73 | ||
|
|
0c9d78a644 | ||
|
|
99d22642e2 | ||
|
|
dc762eacf8 | ||
|
|
5a44f30140 | ||
|
|
82e86b0f8a | ||
|
|
9c4eb4359c | ||
|
|
827c380463 | ||
|
|
7c4fc324c8 | ||
|
|
46215f3304 | ||
|
|
1accc21365 | ||
|
|
b74c2f62f7 | ||
|
|
9d14c0c923 | ||
|
|
650fda5781 | ||
|
|
286ccf5836 | ||
|
|
dfa310666c | ||
|
|
06595241ab | ||
|
|
0f80dd1cfd | ||
|
|
7bc5be264c | ||
|
|
e31784fb1e | ||
|
|
ae156f424b | ||
|
|
cfe0b3883e | ||
|
|
fc6beaa0a5 | ||
|
|
5f2140b147 | ||
|
|
c497bdff39 | ||
|
|
7c84b6432e | ||
|
|
3f787c3b0b | ||
|
|
2046a39e99 | ||
|
|
2ccf89e396 | ||
|
|
efaebc3cb0 | ||
|
|
d7c952cc36 | ||
|
|
1d3ea37129 | ||
|
|
1e9c47398d | ||
|
|
5a1f48f1a5 | ||
|
|
ed65554d30 | ||
|
|
0f19970401 | ||
|
|
b419499710 | ||
|
|
14a5f30b74 | ||
|
|
302cdf200f | ||
|
|
bdde257cac | ||
|
|
73af013bca | ||
|
|
e421427007 | ||
|
|
169a180d68 | ||
|
|
16a19bf578 | ||
|
|
5b39204a8a | ||
|
|
b2bb125248 | ||
|
|
980354104b | ||
|
|
b27571dcaa | ||
|
|
b215bf9000 | ||
|
|
ab75b13b3f | ||
|
|
31cd2aeb08 | ||
|
|
8b6b33b314 | ||
|
|
1b66257ece | ||
|
|
bed9fcf212 | ||
|
|
692f309750 | ||
|
|
2c9c9b502a | ||
|
|
3da8fd2a77 | ||
|
|
ba6826f3d1 | ||
|
|
68b3629437 | ||
|
|
8bc5962d1c | ||
|
|
b8aa1982e4 | ||
|
|
e0a427732e | ||
|
|
8d1f60f5fa | ||
|
|
5cd7fdf385 | ||
|
|
e54d342ac5 | ||
|
|
9019261c2a | ||
|
|
b1a5092053 | ||
|
|
ef8bdbb40f | ||
|
|
0d67826b3d | ||
|
|
6c99e28d51 | ||
|
|
13931aafa5 | ||
|
|
089e7ce8b5 | ||
|
|
54287c8a29 | ||
|
|
5ebc5dee21 | ||
|
|
bedbdbcca9 | ||
|
|
a1c35adf4c | ||
|
|
81b6a9be8b | ||
|
|
88eee58329 | ||
|
|
2f02a5bda4 | ||
|
|
ba716df634 | ||
|
|
988292b82a | ||
|
|
d52cfdd6e6 | ||
|
|
b13a49539f | ||
|
|
32a39a361c | ||
|
|
0e2e9b9ae6 | ||
|
|
331faefde2 | ||
|
|
1603ebe9fc | ||
|
|
bad4359469 | ||
|
|
a860b463ed | ||
|
|
b3b0a96bb8 | ||
|
|
c211724d13 | ||
|
|
0fb9a832ca | ||
|
|
7ce1a97c93 | ||
|
|
1d461c1adf | ||
|
|
5ec09c37bc | ||
|
|
95a20766c3 | ||
|
|
87feb1c2bf | ||
|
|
8c732ac7e9 | ||
|
|
977c1f4d74 | ||
|
|
65ac22aadb | ||
|
|
8e7a14bdb8 | ||
|
|
4693a297b6 | ||
|
|
af69dcd9b5 | ||
|
|
71110fc722 | ||
|
|
c2af5632a2 | ||
|
|
399e813ca4 | ||
|
|
daac7c6171 | ||
|
|
940352ef2c | ||
|
|
c70b909c0f | ||
|
|
dcc2eb9217 | ||
|
|
5425b3b6ea | ||
|
|
a90ea3e3fa | ||
|
|
6d52b7b615 | ||
|
|
51635a7322 | ||
|
|
481b33ba55 | ||
|
|
22c785fc99 | ||
|
|
42d4159b69 | ||
|
|
6d95a2f06d | ||
|
|
7f0b1d8a2e | ||
|
|
a3fecd0fea | ||
|
|
f3d6a54a2a | ||
|
|
1d434f2557 | ||
|
|
b3500086e4 | ||
|
|
bf9202af38 | ||
|
|
bd2c683568 | ||
|
|
c03feaab23 | ||
|
|
9cb9ccbd2a | ||
|
|
4606ebd588 | ||
|
|
679be83c5a | ||
|
|
afe868bb95 | ||
|
|
c9ce3aa23e | ||
|
|
11a49c4874 | ||
|
|
65d2a0fba9 | ||
|
|
c1219195c7 | ||
|
|
fca0dfc91b | ||
|
|
7f1cc3063c | ||
|
|
e444c25287 | ||
|
|
476354e407 | ||
|
|
9f84d3f22f | ||
|
|
4608ff360c | ||
|
|
68b12e199d | ||
|
|
4b1151f769 | ||
|
|
6687214f2a | ||
|
|
a57757258e | ||
|
|
3a6060c45d | ||
|
|
ee375c1b60 | ||
|
|
c9d870cca0 | ||
|
|
3ad8015cc1 | ||
|
|
33609c322f | ||
|
|
431b89c487 | ||
|
|
35a146992c | ||
|
|
dedee114c4 | ||
|
|
9d42af0388 | ||
|
|
8f5d81bc33 | ||
|
|
b17f5563dd | ||
|
|
0ab8bb363a | ||
|
|
ac5fca86bd | ||
|
|
28c2c2e193 | ||
|
|
904c0b6a17 | ||
|
|
f3c31bc92c | ||
|
|
6016b84889 | ||
|
|
cfb5cb3a9f | ||
|
|
1746f6b1d0 | ||
|
|
9c3979a0d9 | ||
|
|
810676c69f | ||
|
|
d0892a245a | ||
|
|
f539b1b93b | ||
|
|
adfa64a29f | ||
|
|
d4f86ee79d | ||
|
|
6ebe31b737 | ||
|
|
dcbd5e62d4 | ||
|
|
a7e6e49363 | ||
|
|
d115257ff7 | ||
|
|
d578be276c | ||
|
|
e338f57441 | ||
|
|
c87321b5b0 | ||
|
|
84bb9b449b | ||
|
|
9d613fc24d | ||
|
|
3f2ae3131e | ||
|
|
0e9f53bd58 | ||
|
|
3981815b63 | ||
|
|
3ef99e4e7c | ||
|
|
76767a0958 | ||
|
|
1683943d58 | ||
|
|
cc0dbe8623 | ||
|
|
b056251e07 | ||
|
|
3b352c66e2 | ||
|
|
b4f0ea73c1 | ||
|
|
1c683788b5 | ||
|
|
250597df2d | ||
|
|
0d2d1d5aaa | ||
|
|
061375d1e7 | ||
|
|
5b05614305 | ||
|
|
69db2e0e53 | ||
|
|
00ef364324 | ||
|
|
de68312b6b | ||
|
|
ddac08bcbc | ||
|
|
517e285bb3 | ||
|
|
81a08a6b51 | ||
|
|
4dfef1d032 | ||
|
|
5d38e28cae | ||
|
|
66a12d10c4 | ||
|
|
1a4027c8d5 | ||
|
|
2a0243c51a | ||
|
|
4851d09e70 | ||
|
|
3cdf3accfd | ||
|
|
fd1f094216 | ||
|
|
25ece1ecb8 | ||
|
|
802e65c280 | ||
|
|
882688f056 | ||
|
|
97d60d0ab3 | ||
|
|
9ef99daed1 | ||
|
|
71c85d9d39 | ||
|
|
b981ab46be | ||
|
|
016633e494 | ||
|
|
1db862ab56 | ||
|
|
3563786310 | ||
|
|
ac8851dd6a | ||
|
|
53ab2d9793 | ||
|
|
2a58c86ffc | ||
|
|
fa46d527ae | ||
|
|
667bd38305 | ||
|
|
faba439466 | ||
|
|
c301157758 | ||
|
|
8d09d425a4 | ||
|
|
11f03d5a10 | ||
|
|
83625202a1 | ||
|
|
eb4b715a88 | ||
|
|
89dce941cf | ||
|
|
6371b67e9e | ||
|
|
966e27418a | ||
|
|
4adf7d1734 | ||
|
|
1a4c4a6fe8 | ||
|
|
7ff36592ae | ||
|
|
1b513412d2 | ||
|
|
f2bb43fbcd | ||
|
|
df5d07d885 | ||
|
|
0ad2f33c4c | ||
|
|
dee48fccb3 | ||
|
|
9ca372ab13 | ||
|
|
58a849a902 | ||
|
|
895072ec35 | ||
|
|
2b2c4d2c39 | ||
|
|
d534b6e2e8 | ||
|
|
783e9d9931 | ||
|
|
a109d9b55b | ||
|
|
5ce59ce44f | ||
|
|
1e9195a9bc | ||
|
|
3099d16468 | ||
|
|
c9c6af346c | ||
|
|
af80a43628 | ||
|
|
dc3c98ec91 | ||
|
|
dffa2c83f6 | ||
|
|
dc66f253a7 | ||
|
|
17498cbfc2 | ||
|
|
96e4d30168 | ||
|
|
c9d1934bb9 | ||
|
|
8bec083194 | ||
|
|
abf047be23 | ||
|
|
4a95399d56 | ||
|
|
885bf5154e | ||
|
|
3e146fc496 | ||
|
|
95710bcaf5 | ||
|
|
edd620f17d | ||
|
|
9c466d8b1e | ||
|
|
b385ab70fb | ||
|
|
140224840b | ||
|
|
2078cd5a5f | ||
|
|
27bae7fdbd | ||
|
|
174b4214de | ||
|
|
4ac524840c | ||
|
|
dd4ce4e2c3 | ||
|
|
2a03d69628 | ||
|
|
c28252e6ce | ||
|
|
da1768d833 | ||
|
|
b58c3e6b47 | ||
|
|
c7575bdc8f | ||
|
|
e275d22061 | ||
|
|
b5600ef22a | ||
|
|
b8e14c9256 | ||
|
|
1af5b9a308 | ||
|
|
2dd719c3a5 | ||
|
|
45d94694cd | ||
|
|
3ce8c6a192 | ||
|
|
7deb86f105 | ||
|
|
d9b4f6a43f | ||
|
|
54a7fb8721 | ||
|
|
d1dcb2f437 | ||
|
|
a92bab617a | ||
|
|
57e34bc595 | ||
|
|
953baa273c | ||
|
|
c403cb3187 | ||
|
|
ffd6dc5bb9 | ||
|
|
0f6504a3dc | ||
|
|
f376fea598 | ||
|
|
4896cdff91 | ||
|
|
b4c87431bc | ||
|
|
1cffbab97d | ||
|
|
9b0711075a | ||
|
|
17a8e902eb | ||
|
|
4bdb5ba245 | ||
|
|
fd7748d280 | ||
|
|
317b0292ff | ||
|
|
b87be649bc | ||
|
|
e2dda54011 | ||
|
|
d17518c39b | ||
|
|
48541dd0bd | ||
|
|
b83b023fee | ||
|
|
60e0c78033 | ||
|
|
a395f7f01f | ||
|
|
09c36ef69e | ||
|
|
9d5fa685a0 | ||
|
|
6794f593fa | ||
|
|
5e9965276f | ||
|
|
1473038955 | ||
|
|
2041ca57f3 | ||
|
|
098782d820 | ||
|
|
87e9a6defd | ||
|
|
3d896ff828 | ||
|
|
bf93240888 | ||
|
|
0b0e30c3c9 | ||
|
|
84d3816bd1 | ||
|
|
04ff606947 | ||
|
|
1cb8e6e238 | ||
|
|
4a2226170d | ||
|
|
1469124cfc | ||
|
|
0826095e73 | ||
|
|
1bd698adde | ||
|
|
1058d269ff | ||
|
|
bacd87b78e | ||
|
|
5befbe8780 | ||
|
|
e159b2adae | ||
|
|
52f7418853 | ||
|
|
76061f7ccd | ||
|
|
7d39e21eae | ||
|
|
fee3723474 | ||
|
|
2f0e4c6888 | ||
|
|
b04cb6d3c5 | ||
|
|
a9228a698a | ||
|
|
27102495d8 | ||
|
|
d1bf96ab33 | ||
|
|
3360dbb468 | ||
|
|
d224e7584e | ||
|
|
6373540076 | ||
|
|
5f78aca997 | ||
|
|
145d944d33 | ||
|
|
ac91940e3b | ||
|
|
ef8452be73 | ||
|
|
47e0810697 | ||
|
|
1f30f225c7 | ||
|
|
fcbfd60ddb | ||
|
|
46f9033713 | ||
|
|
7e65018a0e | ||
|
|
9ef3485968 | ||
|
|
257f8f1145 | ||
|
|
8d65cbb0e5 | ||
|
|
20d221e3ca | ||
|
|
64528c913c |
No files matched your search
@@ -0,0 +1,8 @@
|
||||
* text=auto
|
||||
|
||||
*.sh text eol=lf
|
||||
gradlew text eol=lf
|
||||
*.bat text eol=crlf
|
||||
|
||||
*.jar binary
|
||||
.gitea/CODEOWNERS linguist-detectable=false
|
||||
@@ -0,0 +1,3 @@
|
||||
# Pull requests request review from the eligible staff team(s).
|
||||
# One approval from either an Admin or Developer satisfies branch protection.
|
||||
* @trueog/Admins @trueog/Developers
|
||||
@@ -1,63 +0,0 @@
|
||||
name: Bug Report
|
||||
description: Plugin does not work as described.
|
||||
labels: ["Type: Bug"]
|
||||
body:
|
||||
- type: input
|
||||
attributes:
|
||||
label: Server version
|
||||
description: Version and type of used server software where TAB is installed.
|
||||
placeholder: Spigot 1.18.1
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: TAB version
|
||||
description: Full version in numbers, "latest" is not a version.
|
||||
placeholder: 3.0.2
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe the bug
|
||||
description: How the plugin behaves
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Expected behavior
|
||||
description: How the plugin is supposed to behave instead with your configuration.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: What to do in order to reproduce this issue
|
||||
placeholder: |
|
||||
Step 1: ..
|
||||
Step 2: ..
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional info
|
||||
description: Anything else you want to provide that will help in resolving the issue faster, such as screenshots or videos.
|
||||
validations:
|
||||
required: false
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Checklist
|
||||
description: Let's make sure this report is valid
|
||||
options:
|
||||
- label: I am running latest version of the plugin
|
||||
required: true
|
||||
- label: I have read the wiki to make sure it's not an issue with configuration
|
||||
required: true
|
||||
- label: I ticked all of the boxes without actually reading them
|
||||
required: false
|
||||
- label: I have read the Compatibility wiki page and am not trying to run the plugin on an unsupported server version / platform
|
||||
required: true
|
||||
@@ -1,57 +0,0 @@
|
||||
name: Error
|
||||
description: Error message with a stack trace in console or error file.
|
||||
labels: ["Type: Error"]
|
||||
body:
|
||||
- type: input
|
||||
attributes:
|
||||
label: Server version
|
||||
description: Version and type of used server software where TAB is installed.
|
||||
placeholder: Spigot 1.18.1
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: TAB version
|
||||
description: Full version in numbers, "latest" is not a version.
|
||||
placeholder: 3.0.2
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Stack trace
|
||||
description: The error message and stack trace you received in console or errors.log file.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Steps to reproduce (if known)
|
||||
description: What to do in order to reproduce this issue
|
||||
placeholder: |
|
||||
Step 1: ..
|
||||
Step 2: ..
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional info
|
||||
description: Any other info you want to provide.
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Checklist
|
||||
description: Let's make sure this report is valid
|
||||
options:
|
||||
- label: I am running latest version of the plugin
|
||||
required: true
|
||||
- label: I have included a paste of the error
|
||||
required: true
|
||||
- label: I ticked all of the boxes without actually reading them
|
||||
required: false
|
||||
- label: I have read the Compatibility wiki page and am not trying to run the plugin on an unsupported server version / platform
|
||||
required: true
|
||||
@@ -1,29 +0,0 @@
|
||||
name: Wiki change
|
||||
description: Change to text on a wiki page or adding a new section.
|
||||
labels: ["Type: Wiki change"]
|
||||
body:
|
||||
- type: input
|
||||
attributes:
|
||||
label: Page link
|
||||
description: Link to the page that should receive the change.
|
||||
placeholder: https://github.com/NEZNAMY/TAB/wiki/Installation
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Current text (if applicable)
|
||||
description: Current version of the text (if modifying), ignore in case of new section.
|
||||
placeholder: |
|
||||
Installation on Bukkit/Spigot/Paper is as simple as it can be. Just put the plugin into plugins folder and restart the server. You can also run `/plugman load tab` to load the plugin while server is running.
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: New text
|
||||
description: What the text should be changed to / how should new section look
|
||||
placeholder: |
|
||||
Put the plugin into plugins folder and restart the server. In case you don't want to restart your server, loading with plugins like PlugMan is supported.
|
||||
validations:
|
||||
required: true
|
||||
@@ -1,45 +0,0 @@
|
||||
name: Build
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- v3
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
jobs:
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3.3.0 #https://github.com/actions/checkout/releases
|
||||
with:
|
||||
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
|
||||
- name: Set up JDK 11
|
||||
uses: actions/setup-java@v3.9.0 #https://github.com/actions/setup-java/releases
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 11
|
||||
- name: Cache SonarCloud packages
|
||||
uses: actions/cache@v3.2.3 #https://github.com/actions/cache/releases
|
||||
with:
|
||||
path: ~/.sonar/cache
|
||||
key: ${{ runner.os }}-sonar
|
||||
restore-keys: ${{ runner.os }}-sonar
|
||||
- name: Cache Gradle
|
||||
uses: actions/cache@v3.2.3 #https://github.com/actions/cache/releases
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
~/.gradle/wrapper
|
||||
key: "${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}"
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
- name: Build and analyze
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
|
||||
run: ./gradlew clean build
|
||||
- name: Upload a Build Artifact
|
||||
uses: actions/upload-artifact@v3.1.2 #https://github.com/actions/upload-artifact/releases
|
||||
with:
|
||||
name: Jar
|
||||
path: jar/build/libs/TAB-**.jar
|
||||
@@ -33,7 +33,6 @@ hs_err_pid*
|
||||
.idea/
|
||||
|
||||
# other
|
||||
.gitattributes
|
||||
*.iml
|
||||
run/
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
If this plugin has helped you in any way, and you would like to return something back
|
||||
to make the plugin even better, there is a lot of ways to contribute:
|
||||
* Open a **pull request** containing a new feature or a bug fix, which you believe many users will benefit from.
|
||||
* Make detailed high-quality **bug reports**. The difference between a bug getting fixed in 1 week vs 1 hour
|
||||
is in quality of the report (typically providing correct steps to reproduce that actually work).
|
||||
* Test **experimental builds**, which can be found in [GitHub Actions](https://github.com/NEZNAMY/TAB/actions) for problems of any kind including bugs.
|
||||
This way you will help make the actual releases more stable / help get stable releases sooner.
|
||||
* Help improve the wiki by opening a [Wiki change issue](https://github.com/NEZNAMY/TAB/issues/new?assignees=&labels=Wiki&template=wiki_change.yml),
|
||||
where you can improve existing descriptions, add information you found missing, fix typos / grammar mistakes or add more examples.
|
||||
* Create spark reports and then send them to me. I will analyze them and try to find optimizations to make the plugin run faster. Commands:
|
||||
* `/spark profiler start --timeout 300 --thread * --interval 0.1`
|
||||
* `/spark profiler start --timeout 300 --thread * --interval 0.1 --alloc`
|
||||
@@ -0,0 +1,174 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
@@ -1,43 +1,27 @@
|
||||
# About
|
||||
TAB aims to be a superior all-in-one minecraft plugin for displaying information that outperforms all
|
||||
similar plugins in terms of features, performance, compatibility and support.
|
||||
More information can be found at [Why TAB?](https://github.com/NEZNAMY/TAB/wiki/Why-TAB%3F) wiki page.
|
||||
# TAB-OG
|
||||
|
||||
# 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, customer support is only provided to
|
||||
customers who have purchased the plugin.
|
||||
TAB-OG is a soft fork of [TAB](https://github.com/NEZNAMY/TAB) for
|
||||
[TrueOG Network](https://true-og.net/), based on upstream commit `93cfd74`.
|
||||
|
||||
# Compiling
|
||||
Compilation requires JDK 8 and up.
|
||||
To compile the plugin, run `./gradlew build` from the terminal.
|
||||
Once the plugin compiles, grab the jar from `/jar/build/libs/` folder.
|
||||
Differences from upstream TAB:
|
||||
- Versioned `5.9.9` (upstream is on `6.x`), targeting Purpur 1.19.4 serving 1.8–1.21.11
|
||||
clients through ViaVersion, ViaBackwards, and ViaRewind.
|
||||
- Builds only Bukkit `v1_19_R3`, BungeeCord, and Velocity; drops Fabric, Forge, NeoForge,
|
||||
and the unused Bukkit/Paper NMS modules.
|
||||
- Uses LuckPerms `5.5` (Vault removed) with a GraalVM JDK 17 toolchain, producing one
|
||||
universal shaded JAR.
|
||||
- TrueOG compatibility fixes: [Vanish-OG](https://git.trueog.net/trueog/Vanish-OG), the
|
||||
[AFK-OG](https://git.trueog.net/trueog/AFK-OG) indicator, legacy scoreboard team colors,
|
||||
and disabled scoreboard number formats.
|
||||
- Legacy (1.8–1.12.2) nametag rendering: over-head names drop the rank brackets (the
|
||||
tablist keeps them), sit one space after the rank in its color, bold the AFK indicator
|
||||
for every client, and fit within the 16-character team prefix/suffix limits. A bold
|
||||
rank is kept only when the whole tag can render bold — legacy clients width-count
|
||||
everything after `§l` as bold and never receive a `§r`, so a plain-rendered name after
|
||||
a bold rank pads the nametag end with phantom pixels; when it cannot fit, bold is
|
||||
stripped over-head. Keeping bold requires `add-teamcolor-to-prefix: false` in the
|
||||
ViaBackwards config, otherwise the appended team color un-bolds the name again.
|
||||
- Ships live TrueOG Network config values.
|
||||
|
||||
# Links
|
||||
Download the plugin for free: [GitHub releases](https://github.com/NEZNAMY/TAB/releases),
|
||||
[BuiltByBit](https://builtbybit.com/resources/20631/), [Modrinth](https://modrinth.com/plugin/tab-was-taken)
|
||||
Support my work & receive customer support: [BuiltByBit](https://builtbybit.com/resources/14009/), [Polymart](https://polymart.org/resource/484)
|
||||
Other links: [Discord support for customers](https://discord.gg/EaSvdk6), [Wiki](https://github.com/NEZNAMY/TAB/wiki)
|
||||
|
||||
# Issues
|
||||
The [Issues](https://github.com/NEZNAMY/TAB/issues) section is **only** available for cases included in templates.
|
||||
In other words, they **are not available for**:
|
||||
* **Support** - support is provided on discord for buyers, where roles are given to verified users
|
||||
allowing us to know who bought it and who didn't. It also serves as a much faster way of communication.
|
||||
* **Feature requests** - closed indefinitely.
|
||||
|
||||
**If you're a customer, please use discord for reporting bugs, especially if you aren't good at making bug reports.
|
||||
You will be provided with a much faster and higher quality service.**
|
||||
|
||||
# Contributing
|
||||
If this plugin has helped you in any way, and you would like to return something back
|
||||
to make the plugin even better, there is a lot of ways to contribute:
|
||||
* Open a **pull request** containing a new feature or a bug fix, which you believe many users will benefit from.
|
||||
* Make detailed high-quality **bug reports**. The difference between a bug getting fixed in 1 week vs 1 hour
|
||||
is in quality of the report (typically providing correct steps to reproduce that actually work).
|
||||
* Test **experimental builds**, which can be found in [Github Actions](https://github.com/NEZNAMY/TAB/actions) for problems of any kind including bugs.
|
||||
This way you will help make the actual releases more stable / help get stable releases sooner.
|
||||
* Help improve the wiki by opening a [Wiki change issue](https://github.com/NEZNAMY/TAB/issues/new?assignees=&labels=Wiki&template=wiki_change.yml),
|
||||
where you can improve existing descriptions, add information you found missing, fix typos / grammar mistakes or add more examples of usage of functions.
|
||||
* [Buy a copy](https://builtbybit.com/resources/14009/) of the plugin or [send a donation](https://paypal.me/neznamy1) to keep the plugin active.
|
||||
Build with `./gradlew build` (JAR in `jar/build/libs/`). Requires LuckPerms; bold legacy
|
||||
nametags additionally require ViaBackwards with `add-teamcolor-to-prefix: false`.
|
||||
@@ -0,0 +1,2 @@
|
||||
# Security Policy
|
||||
If you found a security issue, send me a private message anywhere.
|
||||
+1
-19
@@ -1,23 +1,5 @@
|
||||
plugins {
|
||||
id("net.kyori.blossom") version "1.2.0"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnlyApi(libs.netty)
|
||||
api(libs.jsonSimple) {
|
||||
exclude("junit", "junit")
|
||||
}
|
||||
compileOnlyApi(libs.snakeyaml)
|
||||
api(libs.yamlAssist)
|
||||
compileOnlyApi(libs.gson)
|
||||
compileOnlyApi(libs.adventureMiniMessage)
|
||||
compileOnlyApi(libs.adventureApi)
|
||||
compileOnlyApi(libs.adventureLegacy)
|
||||
}
|
||||
|
||||
blossom {
|
||||
replaceToken("@plugin_version@", project.version)
|
||||
replaceTokenIn("src/main/java/me/neznamy/tab/api/TabConstants.java")
|
||||
compileOnlyApi("org.jetbrains:annotations:26.0.2")
|
||||
}
|
||||
|
||||
tasks.javadoc {
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
package me.neznamy.tab.api;
|
||||
|
||||
/**
|
||||
* Interface representing an armor stand attached to player
|
||||
* for displaying text in game.
|
||||
*/
|
||||
public interface ArmorStand {
|
||||
|
||||
/**
|
||||
* Returns true if offset is static, false if not
|
||||
*
|
||||
* @return true if static, false if dynamic
|
||||
*/
|
||||
boolean hasStaticOffset();
|
||||
|
||||
/**
|
||||
* Changes offset of the armor stand
|
||||
*
|
||||
* @param offset
|
||||
* new offset
|
||||
*/
|
||||
void setOffset(double offset);
|
||||
|
||||
/**
|
||||
* Returns offset of the armor stand
|
||||
*
|
||||
* @return offset from base
|
||||
*/
|
||||
double getOffset();
|
||||
|
||||
/**
|
||||
* Returns property for armor stand's name
|
||||
*
|
||||
* @return property for armor stand's name
|
||||
*/
|
||||
Property getProperty();
|
||||
|
||||
/**
|
||||
* Teleports armor stand to owner's current location for everyone in range
|
||||
*/
|
||||
void teleport();
|
||||
|
||||
/**
|
||||
* Teleports armor stand to owner's current location for specified player
|
||||
*
|
||||
* @param viewer
|
||||
* player to send packet to
|
||||
*/
|
||||
void teleport(TabPlayer viewer);
|
||||
|
||||
/**
|
||||
* Changes sneaking flag and sends packets to everyone in range
|
||||
*
|
||||
* @param sneaking
|
||||
* new sneaking status
|
||||
*/
|
||||
void sneak(boolean sneaking);
|
||||
|
||||
/**
|
||||
* DeSpawns armor stand for everyone
|
||||
*/
|
||||
void destroy();
|
||||
|
||||
/**
|
||||
* DeSpawns armor stand for specified player
|
||||
*
|
||||
* @param viewer
|
||||
* player to send packet to
|
||||
*/
|
||||
void destroy(TabPlayer viewer);
|
||||
|
||||
/**
|
||||
* Updates armor stand's name if needed
|
||||
*/
|
||||
void refresh();
|
||||
|
||||
/**
|
||||
* Updates visibility if needed
|
||||
*
|
||||
* @param force
|
||||
* if refresh should be forced
|
||||
*/
|
||||
void updateVisibility(boolean force);
|
||||
|
||||
/**
|
||||
* Returns entity ID of this armor stand
|
||||
*
|
||||
* @return entity ID of this armor stand
|
||||
*/
|
||||
int getEntityId();
|
||||
|
||||
/**
|
||||
* Spawns armor stand for specified player
|
||||
*
|
||||
* @param viewer
|
||||
* player to spawn for
|
||||
*/
|
||||
void spawn(TabPlayer viewer);
|
||||
|
||||
/**
|
||||
* Sends respawn packets to specified player to make position
|
||||
* change instant instead of teleport animation
|
||||
*
|
||||
* @param viewer
|
||||
* Player to send armor stand respawn packets to
|
||||
*/
|
||||
void respawn(TabPlayer viewer);
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package me.neznamy.tab.api;
|
||||
|
||||
/**
|
||||
* A helper class for easy management of armor stands of a player
|
||||
*/
|
||||
public interface ArmorStandManager {
|
||||
|
||||
/**
|
||||
* Sends destroy packet of all armor stands to everyone and clears nearby players list
|
||||
*/
|
||||
void destroy();
|
||||
|
||||
/**
|
||||
* Refreshes text of all armor stands for all nearby players
|
||||
*
|
||||
* @param force
|
||||
* If refresh should be force despite no update seemingly being needed
|
||||
*/
|
||||
void refresh(boolean force);
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
package me.neznamy.tab.api;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Feature manager allows registration and work with features.
|
||||
*/
|
||||
public interface FeatureManager {
|
||||
|
||||
/**
|
||||
* Registers a feature, which will start receiving events
|
||||
*
|
||||
* @param name
|
||||
* name of feature
|
||||
* @param feature
|
||||
* the handler
|
||||
*/
|
||||
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
|
||||
*/
|
||||
void unregisterFeature(String name);
|
||||
|
||||
/**
|
||||
* Returns whether a feature with said name is registered or not
|
||||
*
|
||||
* @param name
|
||||
* name of feature defined in registerFeature method
|
||||
* @return true if feature exists, false if not
|
||||
*/
|
||||
boolean isFeatureEnabled(String 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
|
||||
*/
|
||||
TabFeature getFeature(String name);
|
||||
|
||||
/**
|
||||
* Calls onQuit(TabPlayer) to all enabled features
|
||||
*
|
||||
* @param disconnectedPlayer
|
||||
* player who disconnected
|
||||
*/
|
||||
void onQuit(TabPlayer disconnectedPlayer);
|
||||
|
||||
/**
|
||||
* Calls onJoin(TabPlayer) to all enabled features
|
||||
*
|
||||
* @param connectedPlayer
|
||||
* player who connected
|
||||
*/
|
||||
void onJoin(TabPlayer connectedPlayer);
|
||||
|
||||
/**
|
||||
* Calls onServerChange(TabPlayer, String, String) to all enabled features
|
||||
*
|
||||
* @param playerUUID
|
||||
* player who switched server
|
||||
* @param to
|
||||
* name of the new server
|
||||
*/
|
||||
void onServerChange(UUID playerUUID, String to);
|
||||
|
||||
/**
|
||||
* Calls onWorldChange(TabPlayer, String, String) to all enabled features
|
||||
*
|
||||
* @param playerUUID
|
||||
* player who switched world
|
||||
* @param to
|
||||
* name of the new world
|
||||
*/
|
||||
void onWorldChange(UUID playerUUID, String to);
|
||||
|
||||
/**
|
||||
* Calls onCommand(TabPlayer, String) to all enabled features
|
||||
*
|
||||
* @param sender
|
||||
* command sender
|
||||
* @param command
|
||||
* command line including /
|
||||
* @return {@code true} if some feature marked the command for cancel, {@code false} if not
|
||||
*/
|
||||
boolean onCommand(TabPlayer sender, String command);
|
||||
|
||||
/**
|
||||
* Internal function that marks objective packet deserialization
|
||||
* when at least 1 feature uses it.
|
||||
* <p>
|
||||
* Internal use only.
|
||||
*/
|
||||
void markObjective();
|
||||
|
||||
/**
|
||||
* Internal function that marks display objective packet deserialization
|
||||
* when at least 1 feature uses it.
|
||||
* <p>
|
||||
* Internal use only.
|
||||
*/
|
||||
void markDisplayObjective();
|
||||
|
||||
/**
|
||||
* Returns array of all currently enabled features
|
||||
*
|
||||
* @return array of all currently enabled features
|
||||
*/
|
||||
TabFeature[] getValues();
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
package me.neznamy.tab.api;
|
||||
|
||||
/**
|
||||
* An interface representing a property assigned to a player,
|
||||
* which may contain placeholders and can be changed using the API.
|
||||
*/
|
||||
public interface Property {
|
||||
|
||||
/**
|
||||
* Returns original raw value ignoring API calls
|
||||
*
|
||||
* @return original raw value
|
||||
*/
|
||||
String getOriginalRawValue();
|
||||
|
||||
/**
|
||||
* Temporarily overrides current raw value with an API call
|
||||
*
|
||||
* @param temporaryValue
|
||||
* temporary value to be assigned
|
||||
*/
|
||||
void setTemporaryValue(String temporaryValue);
|
||||
|
||||
/**
|
||||
* Returns current temporary value
|
||||
*
|
||||
* @return temporary value or null if not set
|
||||
*/
|
||||
String getTemporaryValue();
|
||||
|
||||
/**
|
||||
* Returns temporary value (via API) if present, raw value otherwise
|
||||
*
|
||||
* @return current raw value
|
||||
*/
|
||||
String getCurrentRawValue();
|
||||
|
||||
/**
|
||||
* Returns last known value
|
||||
*
|
||||
* @return last known value
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
String updateAndGet();
|
||||
|
||||
/**
|
||||
* Returns value for defined viewer by applying relational placeholders to last known value
|
||||
*
|
||||
* @param viewer
|
||||
* the viewer
|
||||
* @return format for the viewer
|
||||
*/
|
||||
String getFormat(TabPlayer viewer);
|
||||
}
|
||||
@@ -2,13 +2,19 @@ package me.neznamy.tab.api;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import lombok.NonNull;
|
||||
import lombok.Setter;
|
||||
import me.neznamy.tab.api.bossbar.BossBarManager;
|
||||
import me.neznamy.tab.api.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;
|
||||
import me.neznamy.tab.api.team.TeamManager;
|
||||
import me.neznamy.tab.api.tablist.SortingManager;
|
||||
import me.neznamy.tab.api.tablist.HeaderFooterManager;
|
||||
import me.neznamy.tab.api.tablist.TabListFormatManager;
|
||||
import me.neznamy.tab.api.nametag.NameTagManager;
|
||||
import me.neznamy.tab.api.tablist.layout.LayoutManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* The primary API class to get instances of other API classes
|
||||
@@ -16,14 +22,7 @@ import me.neznamy.tab.api.team.TeamManager;
|
||||
public abstract class TabAPI {
|
||||
|
||||
/** Instance of the API */
|
||||
private static TabAPI instance;
|
||||
|
||||
/**
|
||||
* Constructs new instance and sets it as new API instance
|
||||
*/
|
||||
public TabAPI() {
|
||||
instance = this;
|
||||
}
|
||||
@Setter private static TabAPI instance;
|
||||
|
||||
/**
|
||||
* Returns API instance. If instance was not set by the plugin, throws
|
||||
@@ -35,9 +34,13 @@ public abstract class TabAPI {
|
||||
* @throws IllegalStateException
|
||||
* If instance is {@code null}
|
||||
*/
|
||||
public static TabAPI getInstance() {
|
||||
if (instance == null) throw new IllegalStateException("API instance is null. This likely means you shaded TAB's API into your project" +
|
||||
" instead of only using it, which is not allowed.");
|
||||
public static @NotNull TabAPI getInstance() {
|
||||
if (instance == null) throw new IllegalStateException("The API instance is null. This can have 2 possible causes: \n" +
|
||||
"#1 - API was called before TAB was loaded. This means your plugin was loaded before TAB was. To make sure your " +
|
||||
"plugin loads after TAB, add it as a depend or soft depend of your plugin.\n" +
|
||||
"#2 - You shaded TAB's classes into your plugin, instead of only using them. This is not allowed. To verify this " +
|
||||
"is your case, unzip your plugin and check for TAB's classes. If they are there, you will need to fix your compiler " +
|
||||
"to not include them, such as scope provided for maven compilation.");
|
||||
return instance;
|
||||
}
|
||||
|
||||
@@ -48,7 +51,7 @@ public abstract class TabAPI {
|
||||
* Player UUID
|
||||
* @return player object from given UUID
|
||||
*/
|
||||
public abstract TabPlayer getPlayer(UUID id);
|
||||
public abstract @Nullable TabPlayer getPlayer(@NonNull UUID id);
|
||||
|
||||
/**
|
||||
* Returns player object from given name
|
||||
@@ -57,157 +60,76 @@ public abstract class TabAPI {
|
||||
* Player name
|
||||
* @return player object from given name
|
||||
*/
|
||||
public abstract TabPlayer getPlayer(String name);
|
||||
public abstract @Nullable TabPlayer getPlayer(@NonNull String name);
|
||||
|
||||
/**
|
||||
* Returns collection of all online players. Will return empty list if plugin is disabled (due to a broken configuration file for example).
|
||||
*
|
||||
* @return collection of online players
|
||||
*/
|
||||
public abstract TabPlayer[] getOnlinePlayers();
|
||||
public abstract @NotNull TabPlayer[] getOnlinePlayers();
|
||||
|
||||
/**
|
||||
* Return BossBar manager instance if the feature is enabled. If not, returns {@code null}.
|
||||
*
|
||||
* @return BossBar manager
|
||||
*/
|
||||
public abstract BossBarManager getBossBarManager();
|
||||
public abstract @Nullable BossBarManager getBossBarManager();
|
||||
|
||||
/**
|
||||
* Returns scoreboard manager instance if the feature is enabled. If not, returns {@code null}.
|
||||
*
|
||||
* @return scoreboard manager
|
||||
*/
|
||||
public abstract ScoreboardManager getScoreboardManager();
|
||||
public abstract @Nullable ScoreboardManager getScoreboardManager();
|
||||
|
||||
/**
|
||||
* Returns team manager instance if the feature is enabled. If not, returns {@code null}.
|
||||
*
|
||||
* @return team manager
|
||||
*/
|
||||
public abstract TeamManager getTeamManager();
|
||||
public abstract @Nullable NameTagManager getNameTagManager();
|
||||
|
||||
/**
|
||||
* Returns header/footer manager instance if the feature is enabled. If not, returns {@code null}.
|
||||
*
|
||||
* @return Header/footer manager
|
||||
*/
|
||||
public abstract HeaderFooterManager getHeaderFooterManager();
|
||||
public abstract @Nullable HeaderFooterManager getHeaderFooterManager();
|
||||
|
||||
/**
|
||||
* Returns PlaceholderManager instance
|
||||
*
|
||||
* @return PlaceholderManager instance
|
||||
*/
|
||||
public abstract PlaceholderManager getPlaceholderManager();
|
||||
public abstract @NotNull PlaceholderManager getPlaceholderManager();
|
||||
|
||||
/**
|
||||
* Returns feature manager instance
|
||||
* Returns TabList name format manager instance if the feature is enabled. If not, returns {@code null}.
|
||||
*
|
||||
* @return feature manager instance
|
||||
* @return TabList name format manager
|
||||
*/
|
||||
public abstract FeatureManager getFeatureManager();
|
||||
public abstract @Nullable TabListFormatManager getTabListFormatManager();
|
||||
|
||||
/**
|
||||
* Returns Tablist name format manager instance if the feature is enabled. If not, returns {@code null}.
|
||||
* Returns Layout manager instance if the feature is enabled. If not, returns {@code null}.
|
||||
*
|
||||
* @return Tablist name format manager
|
||||
* @return Layout manager
|
||||
*/
|
||||
public abstract TablistFormatManager getTablistFormatManager();
|
||||
public abstract @Nullable LayoutManager getLayoutManager();
|
||||
|
||||
/**
|
||||
* Returns Sorting manager instance if at least one feature capable of sorting players is enabled.
|
||||
* If not, returns {@code null}.
|
||||
*
|
||||
* @return Sorting manager
|
||||
*/
|
||||
public abstract @Nullable SortingManager getSortingManager();
|
||||
|
||||
/**
|
||||
* Gets the event bus for registering listeners for TAB events.
|
||||
*
|
||||
* @return the event bus
|
||||
*/
|
||||
public abstract EventBus getEventBus();
|
||||
|
||||
/**
|
||||
* Returns server version. On proxy installation returns PROXY.
|
||||
*
|
||||
* @return server version
|
||||
*/
|
||||
public abstract ProtocolVersion getServerVersion();
|
||||
|
||||
/**
|
||||
* Prints message into console
|
||||
*
|
||||
* @param message
|
||||
* message to print
|
||||
* @param translateColors
|
||||
* {@code true} if colors should be translated, {@code false} if not
|
||||
*/
|
||||
public abstract void sendConsoleMessage(String message, boolean translateColors);
|
||||
|
||||
/**
|
||||
* Returns TAB's Thread manager, which allows task submitting
|
||||
*
|
||||
* @return ThreadManager instance
|
||||
*/
|
||||
public abstract ThreadManager getThreadManager();
|
||||
|
||||
/**
|
||||
* Returns TAB's cache file used to store player toggle data
|
||||
*
|
||||
* @return TAB's player cache file
|
||||
*/
|
||||
public abstract ConfigurationFile getPlayerCache();
|
||||
|
||||
/**
|
||||
* Returns TAB's config.yml file
|
||||
*
|
||||
* @return config.yml file
|
||||
*/
|
||||
public abstract ConfigurationFile getConfig();
|
||||
|
||||
/**
|
||||
* Returns TAB's group configuration
|
||||
*
|
||||
* @return TAB's group configuration
|
||||
*/
|
||||
public abstract PropertyConfiguration getGroups();
|
||||
|
||||
/**
|
||||
* Returns TAB's user configuration
|
||||
*
|
||||
* @return TAB's user configuration
|
||||
*/
|
||||
public abstract PropertyConfiguration getUsers();
|
||||
|
||||
/**
|
||||
* Sends a debug message into console if the option
|
||||
* is enabled in config.
|
||||
*
|
||||
* @param message
|
||||
* Message to send
|
||||
*/
|
||||
public abstract void debug(String message);
|
||||
|
||||
/**
|
||||
* Logs an error into errors.log file
|
||||
*
|
||||
* @param message
|
||||
* Error message
|
||||
* @param t
|
||||
* Thrown error
|
||||
*/
|
||||
public abstract void logError(String message, Throwable t);
|
||||
|
||||
/**
|
||||
* Sets name of file with syntax error, which prevented
|
||||
* the plugin from enabling. Internal use only.
|
||||
*
|
||||
* @param file
|
||||
* Name of file with syntax error
|
||||
*/
|
||||
public abstract void setBrokenFile(String file);
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the plugin is currently disabled due to an error,
|
||||
* either a yaml syntax error or an internal startup error. Returns {@code false}
|
||||
* if the plugin is properly running.
|
||||
*
|
||||
* @return {@code true} if disabled, {@code false} if running correctly
|
||||
*/
|
||||
public abstract boolean isPluginDisabled();
|
||||
public abstract @Nullable EventBus getEventBus();
|
||||
}
|
||||
@@ -1,382 +0,0 @@
|
||||
package me.neznamy.tab.api;
|
||||
|
||||
/**
|
||||
* A class containing various constants used everywhere in the plugin
|
||||
* to allow easier overview and modification to prevent inconsistencies.
|
||||
*/
|
||||
public class TabConstants {
|
||||
|
||||
public static final String PLUGIN_VERSION = "@plugin_version@";
|
||||
public static final String NO_GROUP = "NONE";
|
||||
public static final String DEFAULT_GROUP = "_DEFAULT_";
|
||||
public static final String PLUGIN_MESSAGE_CHANNEL_NAME = "tab:bridge-2";
|
||||
public static final String REDIS_CHANNEL_NAME = "TAB";
|
||||
|
||||
/**
|
||||
* Private constructor to prevent the class from being instantiated
|
||||
*/
|
||||
private TabConstants() {}
|
||||
|
||||
/**
|
||||
* Feature sub-category explaining why / when a certain feature
|
||||
* needed CPU time to process tasks.
|
||||
*/
|
||||
public static class CpuUsageCategory {
|
||||
|
||||
public static final String PLAYER_JOIN = "Player Join";
|
||||
public static final String PLAYER_QUIT = "Player Quit";
|
||||
public static final String WORLD_SWITCH = "World Switch";
|
||||
public static final String SERVER_SWITCH = "Server Switch";
|
||||
public static final String COMMAND_PREPROCESS = "Command Preprocess";
|
||||
public static final String PLAYER_SNEAK = "Player Sneak";
|
||||
public static final String PLAYER_RESPAWN = "Player Respawn";
|
||||
public static final String PLUGIN_MESSAGE = "PluginMessageEvent";
|
||||
public static final String REDIS_BUNGEE_MESSAGE = "PubSubMessageEvent";
|
||||
public static final String VANISH_CHANGE = "Vanish status change";
|
||||
public static final String ANTI_OVERRIDE = "Anti override";
|
||||
|
||||
public static final String BYTE_BUF = "ByteBuf";
|
||||
public static final String PACKET_PLAYER_INFO = "PacketPlayOutPlayerInfo";
|
||||
public static final String PACKET_DISPLAY_OBJECTIVE = "PacketPlayOutScoreboardDisplayObjective";
|
||||
public static final String PACKET_OBJECTIVE = "PacketPlayOutScoreboardObjective";
|
||||
public static final String PACKET_JOIN_GAME = "Login Packet";
|
||||
public static final String PACKET_ENTITY_MOVE = "PacketPlayOutEntity";
|
||||
public static final String PACKET_ENTITY_MOVE_PASSENGER = "PacketPlayOutEntity (passenger)";
|
||||
public static final String PACKET_ENTITY_SPAWN = "PacketPlayOutNamedEntitySpawn";
|
||||
public static final String PACKET_ENTITY_DESTROY = "PacketPlayOutEntityDestroy";
|
||||
public static final String RAW_PACKET_IN = "Packet reading (in)";
|
||||
public static final String RAW_PACKET_OUT = "Packet reading (out)";
|
||||
|
||||
public static final String PLACEHOLDER_REFRESHING = "Refreshing placeholders";
|
||||
public static final String GROUP_REFRESHING = "Refreshing groups";
|
||||
|
||||
public static final String REFRESHING_NAME_TAG_VISIBILITY = "Refreshing NameTag visibility";
|
||||
public static final String SCOREBOARD_PACKET_CHECK = "Checking for other plugins";
|
||||
public static final String PROCESSING_PLAYER_MOVEMENT = "Processing player movement";
|
||||
public static final String TELEPORTING_WITHER = "Teleporting wither";
|
||||
|
||||
/**
|
||||
* Private constructor to prevent the class from being instantiated
|
||||
*/
|
||||
private CpuUsageCategory() {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Information why a specific feature sent a packet
|
||||
* and what the packet sent is supposed to do.
|
||||
*/
|
||||
public static class PacketCategory {
|
||||
|
||||
public static final String BOSSBAR_COLOR_STYLE = "BossBar (Color and style)";
|
||||
public static final String BOSSBAR_PROGRESS = "BossBar (Progress)";
|
||||
public static final String BOSSBAR_TEXT = "BossBar (Text)";
|
||||
public static final String BOSSBAR_WITHER_TELEPORT = "BossBar (Teleporting Wither)";
|
||||
|
||||
public static final String GLOBAL_PLAYERLIST_LATENCY = "Global PlayerList (Updating latency)";
|
||||
public static final String GLOBAL_PLAYERLIST_VANISH = "Global PlayerList (Vanishing)";
|
||||
|
||||
public static final String LAYOUT_FIXED_SLOTS = "Layout (Fixed slots)";
|
||||
public static final String LAYOUT_PLAYER_SLOTS = "Layout (Player slots)";
|
||||
public static final String LAYOUT_LATENCY = "Layout (Updating latency)";
|
||||
|
||||
public static final String NAMETAGS_TEAM_REGISTER = "NameTags (Team register)";
|
||||
public static final String NAMETAGS_TEAM_UNREGISTER = "NameTags (Team unregister)";
|
||||
public static final String NAMETAGS_TEAM_UPDATE = "NameTags (Team update)";
|
||||
|
||||
public static final String SORTING_CHANGING_TEAM_NAME = "Sorting (Changing team name)";
|
||||
|
||||
public static final String SCOREBOARD_TITLE = "Scoreboard (Title)";
|
||||
public static final String SCOREBOARD_LINES = "Scoreboard (Lines)";
|
||||
|
||||
public static final String UNLIMITED_NAMETAGS_OFFSET_CHANGE = "Unlimited NameTags (Changing offset)";
|
||||
public static final String UNLIMITED_NAMETAGS_SPAWN = "Unlimited NameTags (Spawning)";
|
||||
public static final String UNLIMITED_NAMETAGS_DESPAWN = "Unlimited NameTags (Despawning)";
|
||||
public static final String UNLIMITED_NAMETAGS_TELEPORT = "Unlimited NameTags (Teleporting)";
|
||||
public static final String UNLIMITED_NAMETAGS_SNEAK = "Unlimited NameTags (Sneaking)";
|
||||
public static final String UNLIMITED_NAMETAGS_METADATA = "Unlimited NameTags (Metadata)";
|
||||
|
||||
/**
|
||||
* Private constructor to prevent the class from being instantiated
|
||||
*/
|
||||
private PacketCategory() {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Permission nodes used by the plugin
|
||||
*/
|
||||
public static class Permission {
|
||||
|
||||
public static final String COMMAND_ALL = "tab.admin";
|
||||
public static final String COMMAND_RELOAD = "tab.reload";
|
||||
public static final String COMMAND_BOSSBAR_ANNOUNCE = "tab.announce.bar";
|
||||
public static final String COMMAND_BOSSBAR_TOGGLE = "tab.bossbar.toggle";
|
||||
public static final String COMMAND_BOSSBAR_SEND = "tab.send.bar";
|
||||
public static final String COMMAND_CPU = "tab.cpu";
|
||||
public static final String COMMAND_DEBUG = "tab.debug";
|
||||
public static final String COMMAND_GROUP_INFO = "tab.groupinfo";
|
||||
public static final String COMMAND_GROUP_LIST = "tab.grouplist";
|
||||
public static final String COMMAND_MYSQL_DOWNLOAD = "tab.mysql.download";
|
||||
public static final String COMMAND_MYSQL_UPLOAD = "tab.mysql.upload";
|
||||
public static final String COMMAND_NAMETAG_TOGGLE = "tab.nametag.toggle";
|
||||
|
||||
public static final String COMMAND_NAMETAG_TOGGLE_OTHER = "tab.nametag.toggle.other";
|
||||
public static final String COMMAND_NAMETAG_PREVIEW = "tab.nametag.preview";
|
||||
|
||||
public static final String COMMAND_NAMETAG_PREVIEW_OTHER = "tab.nametag.preview.other";
|
||||
public static final String COMMAND_PARSE = "tab.parse";
|
||||
public static final String COMMAND_SCOREBOARD_ANNOUNCE = "tab.announce.scoreboard";
|
||||
public static final String COMMAND_SCOREBOARD_TOGGLE = "tab.scoreboard.toggle";
|
||||
public static final String COMMAND_SCOREBOARD_TOGGLE_OTHER = "tab.scoreboard.toggle.other";
|
||||
public static final String COMMAND_SCOREBOARD_SHOW = "tab.scoreboard.show";
|
||||
public static final String COMMAND_SCOREBOARD_SHOW_OTHER = "tab.scoreboard.show.other";
|
||||
public static final String COMMAND_SETCOLLISION = "tab.setcollision";
|
||||
public static final String COMMAND_AUTOCOMPLETE = "tab.tabcomplete";
|
||||
public static final String COMMAND_DATA_REMOVE = "tab.remove";
|
||||
public static final String COMMAND_PROPERTY_CHANGE_PREFIX = "tab.change.";
|
||||
public static final String COMMAND_WIDTH = "tab.width";
|
||||
|
||||
public static final String STAFF = "tab.staff";
|
||||
|
||||
public static final String PER_WORLD_PLAYERLIST_BYPASS = "tab.bypass";
|
||||
public static final String SEE_VANISHED = "tab.seevanished";
|
||||
public static final String SPECTATOR_BYPASS = "tab.spectatorbypass";
|
||||
|
||||
public static final String TEST_PERMISSION = "tab.testpermission";
|
||||
|
||||
public static final String GROUP_PREFIX = "tab.group.";
|
||||
|
||||
/**
|
||||
* Private constructor to prevent the class from being instantiated
|
||||
*/
|
||||
private Permission(){}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal property names used to store text
|
||||
* under a specific key
|
||||
*/
|
||||
public static class Property {
|
||||
|
||||
public static final String HEADER = "header";
|
||||
public static final String FOOTER = "footer";
|
||||
|
||||
public static final String TABPREFIX = "tabprefix";
|
||||
public static final String CUSTOMTABNAME = "customtabname";
|
||||
public static final String TABSUFFIX = "tabsuffix";
|
||||
|
||||
public static final String TAGPREFIX = "tagprefix";
|
||||
public static final String CUSTOMTAGNAME = "customtagname";
|
||||
public static final String TAGSUFFIX = "tagsuffix";
|
||||
|
||||
public static final String ABOVENAME = "abovename";
|
||||
public static final String NAMETAG = "nametag";
|
||||
public static final String BELOWNAME = "belowname";
|
||||
|
||||
public static final String SCOREBOARD_TITLE = "scoreboard-title";
|
||||
|
||||
public static final String BELOWNAME_NUMBER = "belowname-number";
|
||||
public static final String BELOWNAME_TEXT = "belowname-text";
|
||||
|
||||
public static final String YELLOW_NUMBER = "yellow-number";
|
||||
|
||||
/**
|
||||
* Private constructor to prevent the class from being instantiated
|
||||
*/
|
||||
private Property() {}
|
||||
|
||||
public static String bossbarTitle(String name) {
|
||||
return "bossbar-title-" + name;
|
||||
}
|
||||
|
||||
public static String bossbarProgress(String name) {
|
||||
return "bossbar-progress-" + name;
|
||||
}
|
||||
|
||||
public static String bossbarColor(String name) {
|
||||
return "bossbar-color-" + name;
|
||||
}
|
||||
|
||||
public static String bossbarStyle(String name) {
|
||||
return "bossbar-style-" + name;
|
||||
}
|
||||
|
||||
public static String scoreboardPrefix(String scoreboard, int lineNumber) {
|
||||
return scoreboard + "-" + lineNumber + "-prefix";
|
||||
}
|
||||
|
||||
public static String scoreboardName(String scoreboard, int lineNumber) {
|
||||
return scoreboard + "-" + lineNumber + "-name";
|
||||
}
|
||||
|
||||
public static String scoreboardSuffix(String scoreboard, int lineNumber) {
|
||||
return scoreboard + "-" + lineNumber + "-suffix";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Feature names used to register features under in the
|
||||
* feature manager which they can be retrieved by.
|
||||
*/
|
||||
public static class Feature {
|
||||
|
||||
//universal features
|
||||
public static final String HEADER_FOOTER = "HeaderFooter";
|
||||
public static final String GHOST_PLAYER_FIX = "GhostPlayerFix";
|
||||
public static final String PLAYER_LIST = "PlayerList";
|
||||
public static final String SPECTATOR_FIX = "SpectatorFix";
|
||||
public static final String YELLOW_NUMBER = "YellowNumber";
|
||||
public static final String BELOW_NAME = "BelowName";
|
||||
public static final String BELOW_NAME_TEXT = "BelowNameText";
|
||||
public static final String SCOREBOARD = "ScoreBoard";
|
||||
public static final String PING_SPOOF = "PingSpoof";
|
||||
public static final String SORTING = "sorting";
|
||||
public static final String LAYOUT = "layout";
|
||||
public static final String LAYOUT_LATENCY = "layout-latency";
|
||||
public static final String NICK_COMPATIBILITY = "nick";
|
||||
public static final String PIPELINE_INJECTION = "injection";
|
||||
public static final String BOSS_BAR = "BossBar";
|
||||
public static final String NAME_TAGS = "NameTag16";
|
||||
public static final String NAME_TAGS_COLLISION = "NameTagCollision";
|
||||
public static final String NAME_TAGS_VISIBILITY = "NameTagVisibility";
|
||||
public static final String GROUP_MANAGER = "GroupManager";
|
||||
public static final String PLACEHOLDER_MANAGER = "PlaceholderManager";
|
||||
public static final String PET_FIX = "PetFix";
|
||||
public static final String UNLIMITED_NAME_TAGS = "NameTagX";
|
||||
public static final String UNLIMITED_NAME_TAGS_PACKET_LISTENER = "nametagx-packet";
|
||||
public static final String UNLIMITED_NAME_TAGS_VEHICLE_REFRESHER = "nametagx-vehicle";
|
||||
|
||||
//Bukkit only
|
||||
public static final String PER_WORLD_PLAYER_LIST = "PerWorldPlayerList";
|
||||
|
||||
//BungeeCord only
|
||||
public static final String REDIS_BUNGEE = "RedisBungee";
|
||||
public static final String GLOBAL_PLAYER_LIST = "GlobalPlayerList";
|
||||
public static final String GLOBAL_PLAYER_LIST_LATENCY = "GlobalPlayerList-Latency";
|
||||
|
||||
//additional info displayed in cpu command
|
||||
public static final String PACKET_SERIALIZING = "Packet serializing";
|
||||
public static final String PACKET_DESERIALIZING = "Packet deserializing";
|
||||
|
||||
/**
|
||||
* Private constructor to prevent the class from being instantiated
|
||||
*/
|
||||
private Feature(){}
|
||||
|
||||
public static String scoreboardLine(String line) {
|
||||
return "scoreboard-" + line;
|
||||
}
|
||||
|
||||
public static String scoreboardLine(String scoreboard, int index) {
|
||||
return "scoreboard-score-" + scoreboard + "-" + index;
|
||||
}
|
||||
|
||||
public static String layout(String name) {
|
||||
return "layout-" + name;
|
||||
}
|
||||
|
||||
public static String layoutSlot(String layout, int slot) {
|
||||
return "layout-" + layout + "-slot-" + slot;
|
||||
}
|
||||
|
||||
public static String bossBarTitle(String name) {
|
||||
return "BossBar-title-" + name;
|
||||
}
|
||||
|
||||
public static String bossBarProgress(String name) {
|
||||
return "BossBar-progress-" + name;
|
||||
}
|
||||
|
||||
public static String bossBarColorStyle(String name) {
|
||||
return "BossBar-color-style-" + name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* All internal placeholders offered by the plugin
|
||||
*/
|
||||
public static class Placeholder {
|
||||
|
||||
// Universal
|
||||
public static final String DISPLAY_NAME = "%displayname%";
|
||||
public static final String GROUP = "%group%";
|
||||
public static final String VANISHED = "%vanished%";
|
||||
public static final String WORLD = "%world%";
|
||||
public static final String WORLD_ONLINE = "%worldonline%";
|
||||
public static final String SERVER = "%server%";
|
||||
public static final String SERVER_ONLINE = "%serveronline%";
|
||||
public static final String PLAYER = "%player%";
|
||||
public static final String TIME = "%time%";
|
||||
public static final String DATE = "%date%";
|
||||
public static final String PING = "%ping%";
|
||||
public static final String PLAYER_VERSION = "%player-version%";
|
||||
public static final String PLAYER_VERSION_ID = "%player-version-id%";
|
||||
public static final String MEMORY_USED = "%memory-used%";
|
||||
public static final String MEMORY_MAX = "%memory-max%";
|
||||
public static final String MEMORY_USED_GB = "%memory-used-gb%";
|
||||
public static final String MEMORY_MAX_GB = "%memory-max-gb%";
|
||||
public static final String ONLINE = "%online%";
|
||||
public static final String STAFF_ONLINE = "%staffonline%";
|
||||
public static final String NON_STAFF_ONLINE = "%nonstaffonline%";
|
||||
public static final String LUCKPERMS_PREFIX = "%luckperms-prefix%";
|
||||
public static final String LUCKPERMS_SUFFIX = "%luckperms-suffix%";
|
||||
public static final String COUNTDOWN = "%countdown%";
|
||||
|
||||
// Placeholders for internal use
|
||||
public static final String COLLISION = "%collision%";
|
||||
public static final String INVISIBLE = "%invisible%";
|
||||
public static final String VEHICLE = "%vehicle%";
|
||||
|
||||
// Bukkit only
|
||||
public static final String TPS = "%tps%";
|
||||
public static final String MSPT = "%mspt%";
|
||||
public static final String AFK = "%afk%";
|
||||
public static final String ESSENTIALS_NICK = "%essentialsnick%";
|
||||
public static final String VAULT_PREFIX = "%vault-prefix%";
|
||||
public static final String VAULT_SUFFIX = "%vault-suffix%";
|
||||
public static final String HEALTH = "%health%";
|
||||
|
||||
public static final int MINIMUM_REFRESH_INTERVAL = 50;
|
||||
|
||||
|
||||
public static String condition(String name) {
|
||||
return "%condition:" + name + "%";
|
||||
}
|
||||
|
||||
public static String animation(String name) {
|
||||
return "%animation:" + name + "%";
|
||||
}
|
||||
|
||||
public static String globalPlayerListGroup(String group) {
|
||||
return "%playerlist-group_" + group + "%";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* All plugins TAB hooks into
|
||||
*/
|
||||
public static class Plugin {
|
||||
|
||||
public static final String LUCKPERMS = "LuckPerms";
|
||||
public static final String VAULT = "Vault";
|
||||
public static final String PLACEHOLDER_API = "PlaceholderAPI";
|
||||
public static final String LIBS_DISGUISES = "LibsDisguises";
|
||||
public static final String VIAVERSION = "ViaVersion";
|
||||
public static final String PROTOCOL_SUPPORT = "ProtocolSupport";
|
||||
public static final String ESSENTIALS = "Essentials";
|
||||
public static final String REDIS_BUNGEE = "RedisBungee";
|
||||
public static final String PREMIUM_VANISH = "PremiumVanish";
|
||||
}
|
||||
|
||||
/**
|
||||
* TAB's custom metrics charts
|
||||
*/
|
||||
public static class MetricsChart {
|
||||
|
||||
public static final String PERMISSION_SYSTEM = "permission_system";
|
||||
public static final String GLOBAL_PLAYER_LIST_ENABLED = "global_playerlist_enabled";
|
||||
public static final String PLACEHOLDER_API = "placeholderapi";
|
||||
public static final String SERVER_VERSION = "server_version";
|
||||
public static final String UNLIMITED_NAME_TAG_MODE_ENABLED = "unlimited_nametag_mode_enabled";
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,408 +0,0 @@
|
||||
package me.neznamy.tab.api;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import me.neznamy.tab.api.protocol.PacketPlayOutPlayerInfo;
|
||||
import me.neznamy.tab.api.protocol.PacketPlayOutScoreboardDisplayObjective;
|
||||
import me.neznamy.tab.api.protocol.PacketPlayOutScoreboardObjective;
|
||||
|
||||
/**
|
||||
* Abstract class representing a core feature of the plugin.
|
||||
* <p>
|
||||
* It receives all kinds of events and can react to them.
|
||||
*/
|
||||
public abstract class TabFeature {
|
||||
|
||||
/** Feature's name displayed in /tab cpu */
|
||||
private final String featureName;
|
||||
|
||||
/** Feature's function name displayed in place of refreshing in /tab cpu */
|
||||
private final String refreshDisplayName;
|
||||
|
||||
/** Servers where the feature is disabled (or enabled if using whitelist mode) */
|
||||
protected String[] disabledServers = new String[0];
|
||||
|
||||
/** Flag tracking whether disabled server list is a whitelist or blacklist */
|
||||
private boolean serverWhitelistMode = false;
|
||||
|
||||
/** Worlds where the feature is disabled (or enabled if using whitelist mode) */
|
||||
protected String[] disabledWorlds = new String[0];
|
||||
|
||||
/** Flag tracking whether disabled world list is a whitelist or blacklist */
|
||||
private boolean worldWhitelistMode = false;
|
||||
|
||||
/** Players located in currently disabled worlds / servers */
|
||||
private final Set<TabPlayer> disabledPlayers = Collections.newSetFromMap(new WeakHashMap<>());
|
||||
|
||||
/**
|
||||
* List of methods overridden (implemented) by each feature.
|
||||
* If a method is not overridden, it is not called at all.
|
||||
* This avoids a massive spam for every single method
|
||||
* in every single feature in /tab cpu output
|
||||
*/
|
||||
private final List<String> methodOverrides = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters and loads method overrides
|
||||
*
|
||||
* @param featureName
|
||||
* Feature's name in /tab cpu
|
||||
* @param refreshDisplayName
|
||||
* "refreshing" cpu display type name of the feature
|
||||
*/
|
||||
protected TabFeature(String featureName, String refreshDisplayName) {
|
||||
this.featureName = featureName;
|
||||
this.refreshDisplayName = refreshDisplayName;
|
||||
try {
|
||||
if (getClass().getMethod("onCommand", TabPlayer.class, String.class).getDeclaringClass() != TabFeature.class)
|
||||
methodOverrides.add("onCommand");
|
||||
if (getClass().getMethod("onJoin", TabPlayer.class).getDeclaringClass() != TabFeature.class)
|
||||
methodOverrides.add("onJoin");
|
||||
if (getClass().getMethod("onQuit", TabPlayer.class).getDeclaringClass() != TabFeature.class)
|
||||
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");
|
||||
TabAPI.getInstance().getFeatureManager().markDisplayObjective();
|
||||
}
|
||||
if (getClass().getMethod("onLoginPacket", TabPlayer.class).getDeclaringClass() != TabFeature.class)
|
||||
methodOverrides.add("onLoginPacket");
|
||||
if (getClass().getMethod("onObjective", TabPlayer.class, PacketPlayOutScoreboardObjective.class).getDeclaringClass() != TabFeature.class) {
|
||||
methodOverrides.add("onObjective");
|
||||
TabAPI.getInstance().getFeatureManager().markObjective();
|
||||
}
|
||||
if (getClass().getMethod("onPlayerInfo", TabPlayer.class, PacketPlayOutPlayerInfo.class).getDeclaringClass() != TabFeature.class)
|
||||
methodOverrides.add("onPlayerInfo");
|
||||
if (getClass().getMethod("onPacketReceive", TabPlayer.class, Object.class).getDeclaringClass() != TabFeature.class)
|
||||
methodOverrides.add("onPacketReceive");
|
||||
if (getClass().getMethod("onPacketSend", TabPlayer.class, Object.class).getDeclaringClass() != TabFeature.class)
|
||||
methodOverrides.add("onPacketSend");
|
||||
if (getClass().getMethod("refresh", TabPlayer.class, boolean.class).getDeclaringClass() != TabFeature.class)
|
||||
methodOverrides.add("refresh");
|
||||
if (getClass().getMethod("onVanishStatusChange", TabPlayer.class).getDeclaringClass() != TabFeature.class)
|
||||
methodOverrides.add("onVanishStatusChange");
|
||||
} catch (NoSuchMethodException e) {
|
||||
//this will never happen
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters and loads method overrides.
|
||||
* Also loads lists of disabled worlds and servers of this feature with config
|
||||
* section path specified with {@code configSection} parameter.
|
||||
*
|
||||
* @param featureName
|
||||
* Feature's name in /tab cpu
|
||||
* @param refreshDisplayName
|
||||
* "refreshing" cpu display type name of the feature
|
||||
* @param configSection
|
||||
* Configuration section of the feature to load disabled
|
||||
* servers / worlds from
|
||||
*/
|
||||
protected TabFeature(String featureName, String refreshDisplayName, String configSection) {
|
||||
this(featureName, refreshDisplayName);
|
||||
List<String> disabledServers = TabAPI.getInstance().getConfig().getStringList(configSection + ".disable-in-servers");
|
||||
List<String> disabledWorlds = TabAPI.getInstance().getConfig().getStringList(configSection + ".disable-in-worlds");
|
||||
if (disabledServers != null) {
|
||||
this.disabledServers = disabledServers.toArray(new String[0]);
|
||||
serverWhitelistMode = disabledServers.contains("WHITELIST");
|
||||
}
|
||||
if (disabledWorlds != null) {
|
||||
this.disabledWorlds = disabledWorlds.toArray(new String[0]);
|
||||
worldWhitelistMode = disabledWorlds.contains("WHITELIST");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all online players and sends packets
|
||||
*/
|
||||
public void load() {
|
||||
//empty by default
|
||||
}
|
||||
|
||||
/**
|
||||
* Unloads all players and sends clear packets
|
||||
*/
|
||||
public void unload() {
|
||||
//empty by default
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes command from player. This is typically a toggle command.
|
||||
*
|
||||
* @param sender
|
||||
* command sender
|
||||
* @param message
|
||||
* command line
|
||||
* @return {@code true} if event should be cancelled, {@code true} if not
|
||||
*/
|
||||
public boolean onCommand(TabPlayer sender, String message) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes join event
|
||||
*
|
||||
* @param connectedPlayer
|
||||
* player who connected
|
||||
*/
|
||||
public void onJoin(TabPlayer connectedPlayer) {
|
||||
//empty by default
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes quit event
|
||||
*
|
||||
* @param disconnectedPlayer
|
||||
* player who disconnected
|
||||
*/
|
||||
public void onQuit(TabPlayer disconnectedPlayer) {
|
||||
//empty by default
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes world switch
|
||||
*
|
||||
* @param changed
|
||||
* player who switched world
|
||||
* @param from
|
||||
* world player changed from
|
||||
* @param to
|
||||
* world player changed to
|
||||
*/
|
||||
public void onWorldChange(TabPlayer changed, String from, String to) {
|
||||
//empty by default
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes server switch
|
||||
*
|
||||
* @param changed
|
||||
* player who switched server
|
||||
* @param from
|
||||
* server player changed from
|
||||
* @param to
|
||||
* server player changed to
|
||||
*/
|
||||
public void onServerChange(TabPlayer changed, String from, String to) {
|
||||
//empty by default
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the packet send and returns true if packet should be cancelled
|
||||
*
|
||||
* @param receiver
|
||||
* player receiving packet
|
||||
* @param packet
|
||||
* received packet
|
||||
*/
|
||||
public void onDisplayObjective(TabPlayer receiver, PacketPlayOutScoreboardDisplayObjective packet) {
|
||||
//empty by default
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes login packet, only available on BungeeCord
|
||||
*
|
||||
* @param packetReceiver
|
||||
* player receiving client reset packet
|
||||
*/
|
||||
public void onLoginPacket(TabPlayer packetReceiver) {
|
||||
//empty by default
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the packet send
|
||||
*
|
||||
* @param receiver
|
||||
* player receiving packet
|
||||
* @param packet
|
||||
* received packet
|
||||
*/
|
||||
public void onObjective(TabPlayer receiver, PacketPlayOutScoreboardObjective packet) {
|
||||
//empty by default
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the packet send and possibly modifies it
|
||||
*
|
||||
* @param receiver
|
||||
* player receiving packet
|
||||
* @param info
|
||||
* received packet
|
||||
*/
|
||||
public void onPlayerInfo(TabPlayer receiver, PacketPlayOutPlayerInfo info) {
|
||||
//empty by default
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes raw packet sent by client
|
||||
*
|
||||
* @param sender
|
||||
* packet sender
|
||||
* @param packet
|
||||
* packet received
|
||||
* @return true if false should be cancelled, false if not
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public boolean onPacketReceive(TabPlayer sender, Object packet) throws ReflectiveOperationException {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes raw packet sent to client
|
||||
*
|
||||
* @param receiver
|
||||
* packet receiver
|
||||
* @param packet
|
||||
* the packet
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public void onPacketSend(TabPlayer receiver, Object packet) throws ReflectiveOperationException {
|
||||
//empty by default
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs refresh of specified player
|
||||
*
|
||||
* @param refreshed
|
||||
* player to refresh
|
||||
* @param force
|
||||
* if refresh should be forced despite refresh seemingly not needed
|
||||
*/
|
||||
public void refresh(TabPlayer refreshed, boolean force) {
|
||||
//empty by default
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes vanish status change of player
|
||||
*
|
||||
* @param player
|
||||
* Player who changed vanish status
|
||||
*/
|
||||
public void onVanishStatusChange(TabPlayer player){
|
||||
//empty by default
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers this feature as one using specified placeholders
|
||||
*
|
||||
* @param placeholders
|
||||
* placeholders to add as used in this feature
|
||||
*/
|
||||
public void addUsedPlaceholders(Collection<String> placeholders) {
|
||||
if (placeholders.isEmpty()) return;
|
||||
placeholders.forEach(p -> TabAPI.getInstance().getPlaceholderManager().addUsedPlaceholder(p, this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if world or server is disabled, {@code false} if not
|
||||
*
|
||||
* @param server
|
||||
* server to check
|
||||
* @param world
|
||||
* world to check
|
||||
* @return {@code true} if feature should be disabled, {@code false} if not
|
||||
*/
|
||||
public boolean isDisabled(String server, String world) {
|
||||
boolean contains = contains(disabledWorlds, world);
|
||||
if (worldWhitelistMode) contains = !contains;
|
||||
if (contains) return true;
|
||||
contains = contains(disabledServers, server);
|
||||
if (serverWhitelistMode) contains = !contains;
|
||||
return contains;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if list contains the specified element or element
|
||||
* ends with {@code "*"} and element meeting that requirement is present,
|
||||
* {@code false} otherwise.
|
||||
*
|
||||
* @param list
|
||||
* List to check
|
||||
* @param element
|
||||
* Element to find
|
||||
* @return {@code true} if element was found, {@code false} if not
|
||||
*/
|
||||
protected boolean contains(String[] list, String element) {
|
||||
if (element == null) return false;
|
||||
for (String s : list) {
|
||||
if (s.endsWith("*")) {
|
||||
if (element.toLowerCase().startsWith(s.substring(0, s.length()-1).toLowerCase())) return true;
|
||||
} else {
|
||||
if (element.equalsIgnoreCase(s)) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns name of the feature displayed in /tab cpu.
|
||||
*
|
||||
* @return name of the feature displayed in /tab cpu
|
||||
*/
|
||||
public String getFeatureName() {
|
||||
return featureName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns text to display in /tab cpu of this feature refreshing visuals
|
||||
*
|
||||
* @return Text to display as refreshing of this feature
|
||||
*/
|
||||
public String getRefreshDisplayName() {
|
||||
return refreshDisplayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if method with specified name is overridden
|
||||
* in the implementation, {@code false} if not
|
||||
*
|
||||
* @param method
|
||||
* Method to check
|
||||
* @return {@code true} if overridden, {@code false} if not
|
||||
*/
|
||||
public boolean overridesMethod(String method) {
|
||||
return methodOverrides.contains(method);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if player is currently located in a server
|
||||
* or world, which is marked as disabled, {@code false} if not
|
||||
*
|
||||
* @param p
|
||||
* Player to check
|
||||
* @return {@code true} if player is in disabled server / world,
|
||||
* {@code false} if not
|
||||
*/
|
||||
public boolean isDisabledPlayer(TabPlayer p) {
|
||||
return disabledPlayers.contains(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds specified player into list of players in disabled
|
||||
* servers / worlds.
|
||||
*
|
||||
* @param p
|
||||
* Player to add
|
||||
*/
|
||||
public void addDisabledPlayer(TabPlayer p) {
|
||||
if (disabledPlayers.contains(p)) return;
|
||||
disabledPlayers.add(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes specified player from list of players in disabled
|
||||
* servers / worlds
|
||||
*
|
||||
* @param p
|
||||
* Player to check
|
||||
*/
|
||||
public void removeDisabledPlayer(TabPlayer p) {
|
||||
disabledPlayers.remove(p);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +1,23 @@
|
||||
package me.neznamy.tab.api;
|
||||
|
||||
import java.util.UUID;
|
||||
import lombok.NonNull;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import me.neznamy.tab.api.chat.IChatBaseComponent;
|
||||
import me.neznamy.tab.api.protocol.Skin;
|
||||
import me.neznamy.tab.api.protocol.TabPacket;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* An interface representing a player
|
||||
*/
|
||||
@SuppressWarnings("unused") // API class
|
||||
public interface TabPlayer {
|
||||
|
||||
/**
|
||||
* Refreshes all visuals on the player
|
||||
*/
|
||||
void forceRefresh();
|
||||
|
||||
/**
|
||||
* Returns player's name
|
||||
*
|
||||
* @return Player's name
|
||||
*/
|
||||
@NotNull
|
||||
String getName();
|
||||
|
||||
/**
|
||||
@@ -29,139 +25,17 @@ public interface TabPlayer {
|
||||
*
|
||||
* @return Player's UUID
|
||||
*/
|
||||
@NotNull
|
||||
UUID getUniqueId();
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
UUID getTablistUUID();
|
||||
|
||||
/**
|
||||
* Returns player's protocol version
|
||||
*
|
||||
* @return player's protocol version
|
||||
*/
|
||||
ProtocolVersion getVersion();
|
||||
|
||||
/**
|
||||
* Returns platform-specific entity
|
||||
*
|
||||
* @return an instance of bukkit/bungee player depending on platform
|
||||
* @return platform's player object
|
||||
*/
|
||||
@NotNull
|
||||
Object getPlayer();
|
||||
|
||||
/**
|
||||
* Returns player's current world name (on BungeeCord this requires bridge installed)
|
||||
*
|
||||
* @return name of world where player is currently in, "N/A" on BungeeCord if bridge is not installed
|
||||
*/
|
||||
String getWorld();
|
||||
|
||||
/**
|
||||
* Returns player's current server name on BungeeCord (on bukkit this returns "N/A")
|
||||
*
|
||||
* @return name of server where player is currently in, "N/A" on bukkit
|
||||
*/
|
||||
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 player has permission, false if not
|
||||
*/
|
||||
boolean hasPermission(String permission);
|
||||
|
||||
/**
|
||||
* Sends the player a custom universal packet
|
||||
*
|
||||
* @param packet
|
||||
* packet to send
|
||||
*/
|
||||
void sendCustomPacket(TabPacket packet);
|
||||
|
||||
/**
|
||||
* Sends the player a custom universal packet and adds that packet into counter that
|
||||
* is displayed in /tab cpu
|
||||
*
|
||||
* @param packet
|
||||
* packet to send
|
||||
* @param feature
|
||||
* feature to increment sent packet counter of
|
||||
*/
|
||||
void sendCustomPacket(TabPacket packet, TabFeature feature);
|
||||
|
||||
/**
|
||||
* Sends the player a custom universal packet and adds that packet into counter that
|
||||
* is displayed in /tab cpu
|
||||
*
|
||||
* @param packet
|
||||
* packet to send
|
||||
* @param feature
|
||||
* feature to increment sent packet counter of
|
||||
*/
|
||||
void sendCustomPacket(TabPacket packet, String feature);
|
||||
|
||||
/**
|
||||
* Sends the player a platform-specific packet
|
||||
*
|
||||
* @param packet
|
||||
* an instance of packet depending on platform
|
||||
*/
|
||||
void sendPacket(Object packet);
|
||||
|
||||
/**
|
||||
* Returns player's property by name
|
||||
*
|
||||
* @param name
|
||||
* name of property
|
||||
* @return the property or {@code null} if not found
|
||||
*/
|
||||
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
|
||||
*/
|
||||
void sendMessage(String message, boolean translateColors);
|
||||
|
||||
/**
|
||||
* Sends specified component as a chat message
|
||||
*
|
||||
* @param message
|
||||
* message to send
|
||||
*/
|
||||
void sendMessage(IChatBaseComponent message);
|
||||
|
||||
/**
|
||||
* Returns player's netty channel. On servers running version 1.7 or older returns {@code null}.
|
||||
*
|
||||
* @return player's channel
|
||||
*/
|
||||
Channel getChannel();
|
||||
|
||||
/**
|
||||
* Returns player's ping calculated by server
|
||||
*
|
||||
* @return player's ping
|
||||
*/
|
||||
int getPing();
|
||||
|
||||
/**
|
||||
* Returns player's skin data
|
||||
*
|
||||
* @return player's skin
|
||||
*/
|
||||
Skin getSkin();
|
||||
|
||||
/**
|
||||
* Returns true once the player is successfully loaded (onJoin method ran through all methods)
|
||||
*
|
||||
@@ -169,92 +43,6 @@ public interface TabPlayer {
|
||||
*/
|
||||
boolean isLoaded();
|
||||
|
||||
/**
|
||||
* Sets property with specified name to new value. If property did not exist before, it is
|
||||
* created and {@code true} is returned. If it existed, it is overridden and {@code true} is returned.
|
||||
* {@code false} is returned otherwise.
|
||||
*
|
||||
* @param feature
|
||||
* feature using this property to get placeholders registered
|
||||
* @param identifier
|
||||
* property name
|
||||
* @param rawValue
|
||||
* new raw value
|
||||
* @return {@code true} if value changed / did not exist, {@code false} if value did not change
|
||||
*/
|
||||
boolean setProperty(TabFeature feature, String identifier, String rawValue);
|
||||
|
||||
/**
|
||||
* Loads property from config using standard property loading algorithm
|
||||
*
|
||||
* @param property
|
||||
* property name to load
|
||||
* @return {@code true} if value did not exist or changed, {@code false} otherwise
|
||||
*/
|
||||
boolean loadPropertyFromConfig(TabFeature feature, String property);
|
||||
|
||||
/**
|
||||
* Loads property from config using standard property loading algorithm. If the property is
|
||||
* not set in config, {@code ifNotSet} value is used.
|
||||
*
|
||||
* @param property
|
||||
* property name to load
|
||||
* @param ifNotSet
|
||||
* value to use if property is not defined in config
|
||||
* @return {@code true} if value did not exist or changed, {@code false} otherwise
|
||||
*/
|
||||
boolean loadPropertyFromConfig(TabFeature feature, String property, String ifNotSet);
|
||||
|
||||
/**
|
||||
* Returns name of player's scoreboard team or {@code null} if NameTag feature is disabled
|
||||
*
|
||||
* @return name of player's team
|
||||
*/
|
||||
String getTeamName();
|
||||
|
||||
/**
|
||||
* Returns {@code true} if player is disguised using LibsDisguises, {@code false} if not
|
||||
*
|
||||
* @return {@code true} if player is disguised, {@code false} if not
|
||||
*/
|
||||
boolean isDisguised();
|
||||
|
||||
/**
|
||||
* Returns {@code true} if player has invisibility potion, {@code false} if not.
|
||||
* For bukkit, API is used, for BungeeCord, bridge is used.
|
||||
*
|
||||
* @return {@code true} if player has invisibility potion, {@code false} if not
|
||||
*/
|
||||
boolean hasInvisibilityPotion();
|
||||
|
||||
/**
|
||||
* Checks if player is vanished using any supported vanish plugin and returns the result.
|
||||
*
|
||||
* @return {@code true} if player is vanished, {@code false} if not
|
||||
*/
|
||||
boolean isVanished();
|
||||
|
||||
/**
|
||||
* Calls platform-specific method and returns the result
|
||||
*
|
||||
* @return {@code true} if player is online, {@code false} if not
|
||||
*/
|
||||
boolean isOnline();
|
||||
|
||||
/**
|
||||
* Returns GameMode of the player (0 for survival, 1 creative, 2 adventure, 3 spectator)
|
||||
*
|
||||
* @return GameMode of the player
|
||||
*/
|
||||
int getGamemode();
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this is a bedrock player, {@code false} if not
|
||||
*
|
||||
* @return {@code true} if player is a bedrock player, {@code false} if not
|
||||
*/
|
||||
boolean isBedrockPlayer();
|
||||
|
||||
/**
|
||||
* Returns player's primary permission group. If group has been changed using
|
||||
* {@link #setTemporaryGroup(String)}, returns that value. Otherwise, returns group
|
||||
@@ -262,59 +50,76 @@ public interface TabPlayer {
|
||||
*
|
||||
* @return player's primary permission group
|
||||
*/
|
||||
@NotNull
|
||||
String getGroup();
|
||||
|
||||
/**
|
||||
* Temporarily overrides player's group and applies all changes coming from new group.
|
||||
* This includes all properties and sorting, if used.
|
||||
* Set to {@code null} to reset back.
|
||||
*
|
||||
* @param group
|
||||
* New group to use
|
||||
* @see #hasTemporaryGroup()
|
||||
* @see #resetTemporaryGroup()
|
||||
*/
|
||||
void setTemporaryGroup(String group);
|
||||
void setTemporaryGroup(@Nullable String group);
|
||||
|
||||
/**
|
||||
* Returns temporary group applied to the player using {@link #setTemporaryGroup(String)}.
|
||||
* If no group was set, returns {@code null}
|
||||
* Returns {@code true} if a temporary group was applied to the player using {@link #setTemporaryGroup(String)}.
|
||||
* If no group was set, returns {@code false}
|
||||
*
|
||||
* @return Temporary group assigned to player or {@code null} if not set
|
||||
* @return {@code true} if group is set, {@code false} if not
|
||||
* @see #setTemporaryGroup(String)
|
||||
* @see #resetTemporaryGroup()
|
||||
*/
|
||||
boolean hasTemporaryGroup();
|
||||
|
||||
/**
|
||||
* Resets temporary group assigned using {@link #setTemporaryGroup(String)}.
|
||||
* If no temporary group is set, doesn't do anything.
|
||||
* Changes expected profile name of the player. This adapts all name-bound features
|
||||
* to use this new profile name if another plugin changed profile name of the player. <p>
|
||||
* Automatic profile name change detection is available on Bukkit, BungeeCord and Fabric,
|
||||
* therefore using this is redundant there. This function is only needed on Velocity,
|
||||
* where the detection is not available. <p>
|
||||
* Warning: This function does NOT change player's profile name, it only updates the tracked
|
||||
* name inside the plugin.
|
||||
*
|
||||
* @see #setTemporaryGroup(String)
|
||||
* @see #hasTemporaryGroup()
|
||||
* @param profileName
|
||||
* New expected profile name
|
||||
*/
|
||||
void resetTemporaryGroup();
|
||||
void setExpectedProfileName(@NonNull String profileName);
|
||||
|
||||
/**
|
||||
* Returns player's game profile name as seen by other players. By default,
|
||||
* this returns player's name. If using a nickname / disguise plugin that changes
|
||||
* game profile name for other players and change was successfully detected, returns
|
||||
* that value.
|
||||
* Returns player's expected profile name. This defaults to player's username, but may
|
||||
* get changed by other plugins and then detected by TAB.
|
||||
*
|
||||
* @return player's game profile name as seen by other players
|
||||
* @return Player's expected profile name
|
||||
*/
|
||||
String getNickname();
|
||||
@NotNull
|
||||
String getExpectedProfileName();
|
||||
|
||||
/**
|
||||
* Returns player's chat message signing key. Returned object is a direct
|
||||
* object from the server, which is different per platform.
|
||||
* Returns name of the server the player is connected to.
|
||||
* This requires TAB on proxy.
|
||||
* On backend installation, this method returns {@code "N/A"}.
|
||||
*
|
||||
* @return Player's direct chat message signing key
|
||||
* @return Player's server on proxy or {@code "N/A"} on backend installation
|
||||
*/
|
||||
Object getProfilePublicKey();
|
||||
@NotNull
|
||||
String getServer();
|
||||
|
||||
/**
|
||||
* Return player's chat session ID
|
||||
* @return player's chat session ID
|
||||
* Returns name of the world the player is in.
|
||||
* On proxy installation, TAB-Bridge must be installed to forward this info to the proxy.
|
||||
* Otherwise, it will return {@code "N/A"}.
|
||||
*
|
||||
* @return Player's world or {@code "N/A"} on proxy installation without TAB-Bridge installed
|
||||
*/
|
||||
UUID getChatSessionId();
|
||||
@NotNull
|
||||
String getWorld();
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this player is a bedrock player, {@code false} if not.
|
||||
*
|
||||
* @return {@code true} if this player is a bedrock player, {@code false} if not
|
||||
*/
|
||||
boolean isBedrockPlayer();
|
||||
}
|
||||
@@ -1,168 +0,0 @@
|
||||
package me.neznamy.tab.api;
|
||||
|
||||
/**
|
||||
* An interface allowing to modify tablist display names
|
||||
* of players.
|
||||
* <p>
|
||||
* Instance can be obtained using {@link TabAPI#getTablistFormatManager()}.
|
||||
* This requires the feature to be enabled in config, otherwise the method will
|
||||
* return {@code null}.
|
||||
*/
|
||||
public interface TablistFormatManager {
|
||||
|
||||
/**
|
||||
* Changes player's prefix to provided value. Supports placeholders,
|
||||
* as well as any supported RGB formats.
|
||||
*
|
||||
* @param player
|
||||
* player to change prefix of
|
||||
* @param prefix
|
||||
* new prefix value
|
||||
* @see #resetPrefix(TabPlayer)
|
||||
* @see #getCustomPrefix(TabPlayer)
|
||||
* @see #getOriginalPrefix(TabPlayer)
|
||||
*/
|
||||
void setPrefix(TabPlayer player, String prefix);
|
||||
|
||||
/**
|
||||
* Changes player's name to provided value. Supports placeholders,
|
||||
* as well as any supported RGB formats.
|
||||
*
|
||||
* @param player
|
||||
* player to change prefix of
|
||||
* @param customName
|
||||
* new customName value
|
||||
* @see #resetName(TabPlayer)
|
||||
* @see #getCustomName(TabPlayer)
|
||||
* @see #getOriginalName(TabPlayer)
|
||||
*/
|
||||
void setName(TabPlayer player, String customName);
|
||||
|
||||
/**
|
||||
* Changes player's suffix to provided value. Supports placeholders,
|
||||
* as well as any supported RGB formats.
|
||||
*
|
||||
* @param player
|
||||
* player to change prefix of
|
||||
* @param suffix
|
||||
* new suffix value
|
||||
* @see #resetSuffix(TabPlayer)
|
||||
* @see #getCustomSuffix(TabPlayer)
|
||||
* @see #getOriginalSuffix(TabPlayer)
|
||||
*/
|
||||
void setSuffix(TabPlayer player, String suffix);
|
||||
|
||||
/**
|
||||
* Resets player's prefix previously assigned using {@link #setPrefix(TabPlayer, String)}
|
||||
* method. If nothing was set, this method will not do anything.
|
||||
*
|
||||
* @param player
|
||||
* player to reset prefix of
|
||||
* @see #setPrefix(TabPlayer, String)
|
||||
* @see #getCustomPrefix(TabPlayer)
|
||||
* @see #getOriginalPrefix(TabPlayer)
|
||||
*/
|
||||
void resetPrefix(TabPlayer player);
|
||||
|
||||
/**
|
||||
* Resets player's custom name previously assigned using {@link #setName(TabPlayer, String)}
|
||||
* method. If nothing was set, this method will not do anything.
|
||||
*
|
||||
* @param player
|
||||
* player to reset name of
|
||||
* @see #setName(TabPlayer, String)
|
||||
* @see #getCustomName(TabPlayer)
|
||||
* @see #getOriginalName(TabPlayer)
|
||||
*/
|
||||
void resetName(TabPlayer player);
|
||||
|
||||
/**
|
||||
* Resets player's suffix previously assigned using {@link #setSuffix(TabPlayer, String)}
|
||||
* method. If nothing was set, this method will not do anything.
|
||||
*
|
||||
* @param player
|
||||
* player to reset suffix of
|
||||
* @see #setSuffix(TabPlayer, String)
|
||||
* @see #getCustomSuffix(TabPlayer)
|
||||
* @see #getOriginalSuffix(TabPlayer)
|
||||
*/
|
||||
void resetSuffix(TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns prefix assigned using {@link #setPrefix(TabPlayer, String)} method.
|
||||
* If the method was not used, {@code null} is returned.
|
||||
*
|
||||
* @param player
|
||||
* player to get custom prefix of
|
||||
* @return player's custom prefix or {@code null} if not defined
|
||||
* @see #setPrefix(TabPlayer, String)
|
||||
* @see #resetPrefix(TabPlayer)
|
||||
* @see #getOriginalPrefix(TabPlayer)
|
||||
*/
|
||||
String getCustomPrefix(TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns custom name assigned using {@link #setName(TabPlayer, String)} method.
|
||||
* If the method was not used, {@code null} is returned.
|
||||
*
|
||||
* @param player
|
||||
* player to get custom name of
|
||||
* @return player's custom name or {@code null} if not defined
|
||||
* @see #setName(TabPlayer, String)
|
||||
* @see #resetName(TabPlayer)
|
||||
* @see #getOriginalName(TabPlayer)
|
||||
*/
|
||||
String getCustomName(TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns suffix assigned using {@link #setSuffix(TabPlayer, String)} method.
|
||||
* If the method was not used, {@code null} is returned.
|
||||
*
|
||||
* @param player
|
||||
* player to get custom suffix of
|
||||
* @return player's custom suffix or {@code null} if not defined
|
||||
* @see #setSuffix(TabPlayer, String)
|
||||
* @see #resetSuffix(TabPlayer)
|
||||
* @see #getOriginalSuffix(TabPlayer)
|
||||
*/
|
||||
String getCustomSuffix(TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns player's original prefix applied using plugin's internal logic.
|
||||
* This value is not affected by API calls in any way.
|
||||
*
|
||||
* @param player
|
||||
* player to get original prefix of
|
||||
* @return player's original prefix
|
||||
* @see #setPrefix(TabPlayer, String)
|
||||
* @see #resetPrefix(TabPlayer)
|
||||
* @see #getCustomPrefix(TabPlayer)
|
||||
*/
|
||||
String getOriginalPrefix(TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns player's original name applied using plugin's internal logic.
|
||||
* This value is not affected by API calls in any way.
|
||||
*
|
||||
* @param player
|
||||
* player to get original name of
|
||||
* @return player's original name
|
||||
* @see #setName(TabPlayer, String)
|
||||
* @see #resetName(TabPlayer)
|
||||
* @see #getCustomName(TabPlayer)
|
||||
*/
|
||||
String getOriginalName(TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns player's original suffix applied using plugin's internal logic.
|
||||
* This value is not affected by API calls in any way.
|
||||
*
|
||||
* @param player
|
||||
* player to get original suffix of
|
||||
* @return player's original suffix
|
||||
* @see #setSuffix(TabPlayer, String)
|
||||
* @see #resetSuffix(TabPlayer)
|
||||
* @see #getCustomSuffix(TabPlayer)
|
||||
*/
|
||||
String getOriginalSuffix(TabPlayer player);
|
||||
}
|
||||
@@ -4,13 +4,27 @@ package me.neznamy.tab.api.bossbar;
|
||||
* An enum representing all available BossBar colors.
|
||||
* Calling ordinal() will return color's network ID.
|
||||
*/
|
||||
@SuppressWarnings("unused") // API class
|
||||
public enum BarColor {
|
||||
|
||||
/** Pink color */
|
||||
PINK,
|
||||
|
||||
/** Blue color */
|
||||
BLUE,
|
||||
|
||||
/** Red color */
|
||||
RED,
|
||||
|
||||
/** Green color */
|
||||
GREEN,
|
||||
|
||||
/** Yellow color */
|
||||
YELLOW,
|
||||
|
||||
/** Purple color */
|
||||
PURPLE,
|
||||
|
||||
/** White color */
|
||||
WHITE
|
||||
}
|
||||
@@ -3,34 +3,22 @@ package me.neznamy.tab.api.bossbar;
|
||||
/**
|
||||
* An enum representing all available BossBar styles.
|
||||
* Calling ordinal() will return style's network ID.
|
||||
* Style names are equal to NMS names.
|
||||
*/
|
||||
@SuppressWarnings("unused") // API class
|
||||
public enum BarStyle {
|
||||
|
||||
PROGRESS("SOLID"),
|
||||
NOTCHED_6("SEGMENTED_6"),
|
||||
NOTCHED_10("SEGMENTED_10"),
|
||||
NOTCHED_12("SEGMENTED_12"),
|
||||
NOTCHED_20("SEGMENTED_20");
|
||||
/** Fully solid line */
|
||||
PROGRESS,
|
||||
|
||||
/** Style's name used in Bukkit API */
|
||||
private final String bukkitName;
|
||||
/** Line segmented into 6 parts */
|
||||
NOTCHED_6,
|
||||
|
||||
/**
|
||||
* Initializes enum constant with given bukkit name
|
||||
*
|
||||
* @param bukkitName
|
||||
* Name of color to be returned in {@code getBukkitName()}
|
||||
*/
|
||||
BarStyle(String bukkitName){
|
||||
this.bukkitName = bukkitName;
|
||||
}
|
||||
/** Line segmented into 10 parts */
|
||||
NOTCHED_10,
|
||||
|
||||
/**
|
||||
* Returns name of this style in Bukkit API
|
||||
* @return name of this style in Bukkit API
|
||||
*/
|
||||
public String getBukkitName() {
|
||||
return bukkitName;
|
||||
}
|
||||
/** Line segmented into 12 parts */
|
||||
NOTCHED_12,
|
||||
|
||||
/** Line segmented into 20 parts */
|
||||
NOTCHED_20
|
||||
}
|
||||
@@ -3,16 +3,14 @@ package me.neznamy.tab.api.bossbar;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* An interface representing a BossBar line.
|
||||
* <p>
|
||||
* For clients 1.8 and lower it uses wither, which only allows 1 bar
|
||||
* to be displayed at a time. Entity packets are not available on BungeeCord,
|
||||
* where nothing will be displayed for these players.
|
||||
* <p>
|
||||
* For 1.9+ it uses the new BossBar feature, allowing configurable styles
|
||||
* It uses 1.9+ 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.
|
||||
@@ -26,7 +24,7 @@ public interface BossBar {
|
||||
*
|
||||
* @return name of BossBar
|
||||
*/
|
||||
String getName();
|
||||
@NotNull String getName();
|
||||
|
||||
/**
|
||||
* Returns randomly generated uuid of this BossBar used internally to match
|
||||
@@ -34,7 +32,7 @@ public interface BossBar {
|
||||
*
|
||||
* @return uuid of this BossBar
|
||||
*/
|
||||
UUID getUniqueId();
|
||||
@NotNull UUID getUniqueId();
|
||||
|
||||
/**
|
||||
* Changes BossBar title to specified string, supporting placeholders.
|
||||
@@ -48,7 +46,7 @@ public interface BossBar {
|
||||
* @param title
|
||||
* New title to display in this BossBar
|
||||
*/
|
||||
void setTitle(String title);
|
||||
void setTitle(@NonNull String title);
|
||||
|
||||
/**
|
||||
* Changes BossBar progress to specified string, supporting placeholders.
|
||||
@@ -64,7 +62,7 @@ public interface BossBar {
|
||||
* @param progress
|
||||
* New progress to use in this BossBar
|
||||
*/
|
||||
void setProgress(String progress);
|
||||
void setProgress(@NonNull String progress);
|
||||
|
||||
/**
|
||||
* Changes BossBar progress to specified value ranging from 0 to 100.
|
||||
@@ -90,7 +88,7 @@ public interface BossBar {
|
||||
* @param color
|
||||
* New color to use in this BossBar
|
||||
*/
|
||||
void setColor(String color);
|
||||
void setColor(@NonNull String color);
|
||||
|
||||
/**
|
||||
* Changes BossBar color to specified enum constant.
|
||||
@@ -100,7 +98,7 @@ public interface BossBar {
|
||||
* @param color
|
||||
* New color to use in this BossBar
|
||||
*/
|
||||
void setColor(BarColor color);
|
||||
void setColor(@NonNull BarColor color);
|
||||
|
||||
/**
|
||||
* Changes BossBar style to specified string, supporting placeholders.
|
||||
@@ -116,7 +114,7 @@ public interface BossBar {
|
||||
* @param style
|
||||
* New style to use in this BossBar
|
||||
*/
|
||||
void setStyle(String style);
|
||||
void setStyle(@NonNull String style);
|
||||
|
||||
/**
|
||||
* Changes BossBar style to specified enum constant.
|
||||
@@ -126,7 +124,7 @@ public interface BossBar {
|
||||
* @param style
|
||||
* New style to use in this BossBar
|
||||
*/
|
||||
void setStyle(BarStyle style);
|
||||
void setStyle(@NonNull BarStyle style);
|
||||
|
||||
/**
|
||||
* Returns current title of the BossBar in raw format. If it contains placeholders,
|
||||
@@ -134,7 +132,7 @@ public interface BossBar {
|
||||
*
|
||||
* @return title of the BossBar
|
||||
*/
|
||||
String getTitle();
|
||||
@NotNull String getTitle();
|
||||
|
||||
/**
|
||||
* Returns progress of the BossBar as a string, which is either entered string
|
||||
@@ -142,7 +140,7 @@ public interface BossBar {
|
||||
*
|
||||
* @return entered progress as a string
|
||||
*/
|
||||
String getProgress();
|
||||
@NotNull String getProgress();
|
||||
|
||||
/**
|
||||
* Returns color of the BossBar as a string, which is either entered string
|
||||
@@ -150,7 +148,7 @@ public interface BossBar {
|
||||
*
|
||||
* @return entered color as a string
|
||||
*/
|
||||
String getColor();
|
||||
@NotNull String getColor();
|
||||
|
||||
/**
|
||||
* Returns style of the BossBar as a string, which is either entered string
|
||||
@@ -158,7 +156,7 @@ public interface BossBar {
|
||||
*
|
||||
* @return entered style as a string
|
||||
*/
|
||||
String getStyle();
|
||||
@NotNull String getStyle();
|
||||
|
||||
/**
|
||||
* Registers this BossBar to specified player.
|
||||
@@ -168,7 +166,7 @@ public interface BossBar {
|
||||
* @param player
|
||||
* Player to register this BossBar to
|
||||
*/
|
||||
void addPlayer(TabPlayer player);
|
||||
void addPlayer(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Unregisters this BossBar from specified player.
|
||||
@@ -178,7 +176,7 @@ public interface BossBar {
|
||||
* @param player
|
||||
* Player to unregister this BossBar from
|
||||
*/
|
||||
void removePlayer(TabPlayer player);
|
||||
void removePlayer(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns list of players who can see this BossBar.
|
||||
@@ -189,19 +187,24 @@ public interface BossBar {
|
||||
*
|
||||
* @return List of players seeing this BossBar
|
||||
*/
|
||||
List<TabPlayer> getPlayers();
|
||||
@NotNull List<TabPlayer> getPlayers();
|
||||
|
||||
/**
|
||||
* Returns {@code true} if specified player can see this BossBar, {@code false} if not
|
||||
* Returns {@code true} if this bossbar is visible to specified player based on
|
||||
* display condition or adding via {@link #addPlayer(TabPlayer)}, {@code false} if not.
|
||||
* <p>
|
||||
* This may return {@code true} even if player cannot physically see the bossbar due to
|
||||
* having it disabled via toggle command or {@link BossBarManager#toggleBossBar(TabPlayer, boolean)}
|
||||
* (or {@link BossBarManager#setBossBarVisible(TabPlayer, boolean, boolean)}).
|
||||
*
|
||||
* @param player
|
||||
* Player to check for
|
||||
* @return {@code true} if contains, {@code false} if not
|
||||
* Player to check
|
||||
* @return {@code true} if player is allowed to see this Boss Bar, {@code false} if not.
|
||||
*/
|
||||
boolean containsPlayer(TabPlayer player);
|
||||
boolean containsPlayer(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this bossbar in configured as announcement-only bar,
|
||||
* Returns {@code true} if this boss bar is configured as announcement-only bar,
|
||||
* {@code false} if not.
|
||||
*
|
||||
* @return {@code true} if bar is announcement only, {@code false} if not
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package me.neznamy.tab.api.bossbar;
|
||||
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.tab.api.TabAPI;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import me.neznamy.tab.api.TabAPI;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
|
||||
/**
|
||||
* An interface allowing work with BossBars such as creating, sending
|
||||
@@ -15,6 +17,7 @@ import me.neznamy.tab.api.TabPlayer;
|
||||
* This requires the BossBar feature to be enabled in config, otherwise the method will
|
||||
* return {@code null}.
|
||||
*/
|
||||
@SuppressWarnings("unused") // API class
|
||||
public interface BossBarManager {
|
||||
|
||||
/**
|
||||
@@ -31,7 +34,7 @@ public interface BossBarManager {
|
||||
* Style to use
|
||||
* @return The newly created BossBar
|
||||
*/
|
||||
BossBar createBossBar(String title, float progress, BarColor color, BarStyle style);
|
||||
@NotNull BossBar createBossBar(@NonNull String title, float progress, @NonNull BarColor color, @NonNull BarStyle style);
|
||||
|
||||
/**
|
||||
* Creates BossBar with specified parameters and registers it to BossBar manager,
|
||||
@@ -50,30 +53,19 @@ public interface BossBarManager {
|
||||
* a placeholder that returns one of them
|
||||
* @return The newly created BossBar
|
||||
*/
|
||||
BossBar createBossBar(String title, String progress, String color, String style);
|
||||
@NotNull BossBar createBossBar(@NonNull String title, @NonNull String progress, @NonNull String color, @NonNull String style);
|
||||
|
||||
/**
|
||||
* Returns registered BossBar with given name. For BossBars from config it is the name
|
||||
* they were created with, for API BossBars their randomly generated name, which can be
|
||||
* retrieved using {@link me.neznamy.tab.api.bossbar.BossBar#getName()}.
|
||||
* Returns null if no such BossBar exists.
|
||||
* Returns {@code null} if no such BossBar exists.
|
||||
*
|
||||
* @param name
|
||||
* Name of registered BossBar
|
||||
* @return BossBar with specified 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.
|
||||
*
|
||||
* @param id
|
||||
* UUID to return BossBar by
|
||||
* @return BossBar with specified uuid
|
||||
*/
|
||||
BossBar getBossBar(UUID id);
|
||||
@Nullable BossBar getBossBar(@NonNull String name);
|
||||
|
||||
/**
|
||||
* Returns a map of all registered BossBars. This includes both BossBars from config
|
||||
@@ -84,7 +76,29 @@ public interface BossBarManager {
|
||||
*
|
||||
* @return all registered BossBars
|
||||
*/
|
||||
Map<String, BossBar> getRegisteredBossBars();
|
||||
@NotNull Map<String, BossBar> getRegisteredBossBars();
|
||||
|
||||
/**
|
||||
* Removes BossBar with specified name from the manager, making it no longer available.
|
||||
* If BossBar was displayed to any players, it is removed.
|
||||
*
|
||||
* @param name
|
||||
* Name of registered BossBar to remove
|
||||
* @throws IllegalArgumentException
|
||||
* if no BossBar with specified name exists
|
||||
*/
|
||||
void removeBossBar(@NonNull String name);
|
||||
|
||||
/**
|
||||
* Removes BossBar from the manager, making it no longer available.
|
||||
* If BossBar was displayed to any players, it is removed.
|
||||
*
|
||||
* @param bossBar
|
||||
* BossBar to remove
|
||||
* @throws IllegalArgumentException
|
||||
* if specified BossBar is not registered
|
||||
*/
|
||||
void removeBossBar(@NonNull BossBar bossBar);
|
||||
|
||||
/**
|
||||
* Toggles BossBar for this player and sends toggle message if {@code sendToggleMessage} is true.
|
||||
@@ -96,7 +110,7 @@ public interface BossBarManager {
|
||||
* @see #hasBossBarVisible(TabPlayer)
|
||||
* @see #setBossBarVisible(TabPlayer, boolean, boolean)
|
||||
*/
|
||||
void toggleBossBar(TabPlayer player, boolean sendToggleMessage);
|
||||
void toggleBossBar(@NonNull TabPlayer player, boolean sendToggleMessage);
|
||||
|
||||
/**
|
||||
* Returns true if player can see BossBars, false if toggled via command or API.
|
||||
@@ -107,7 +121,7 @@ public interface BossBarManager {
|
||||
* @see #toggleBossBar(TabPlayer, boolean)
|
||||
* @see #setBossBarVisible(TabPlayer, boolean, boolean)
|
||||
*/
|
||||
boolean hasBossBarVisible(TabPlayer player);
|
||||
boolean hasBossBarVisible(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Sets BossBar visibility of player to set value. If value did not change, nothing happens.
|
||||
@@ -122,37 +136,37 @@ public interface BossBarManager {
|
||||
* @see #toggleBossBar(TabPlayer, boolean)
|
||||
* @see #hasBossBarVisible(TabPlayer)
|
||||
*/
|
||||
void setBossBarVisible(TabPlayer player, boolean visible, boolean sendToggleMessage);
|
||||
void setBossBarVisible(@NonNull 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 seconds.
|
||||
*
|
||||
* @param player
|
||||
* Player to show BossBar to
|
||||
* @param bossBar
|
||||
* Name of registered BossBar to show
|
||||
* @param duration
|
||||
* In milliseconds for how long should BossBar be displayed
|
||||
* In seconds for how long should BossBar be displayed
|
||||
* @throws IllegalArgumentException
|
||||
* if no BossBar with specified name exists
|
||||
* @see #announceBossBar(String, int)
|
||||
* @see #getAnnouncedBossBars()
|
||||
*/
|
||||
void sendBossBarTemporarily(TabPlayer player, String bossBar, int duration);
|
||||
void sendBossBarTemporarily(@NonNull TabPlayer player, @NonNull String bossBar, int duration);
|
||||
|
||||
/**
|
||||
* Temporarily displays registered BossBar to all players for specified amount of time in milliseconds.
|
||||
* Temporarily displays registered BossBar to all players for specified amount of time in seconds.
|
||||
*
|
||||
* @param bossBar
|
||||
* Name of registered BossBar to show
|
||||
* @param duration
|
||||
* In milliseconds for how long should BossBar be displayed
|
||||
* In seconds for how long should BossBar be displayed
|
||||
* @throws IllegalArgumentException
|
||||
* if no BossBar with specified name exists
|
||||
* @see #sendBossBarTemporarily(TabPlayer, String, int)
|
||||
* @see #getAnnouncedBossBars()
|
||||
*/
|
||||
void announceBossBar(String bossBar, int duration);
|
||||
void announceBossBar(@NonNull String bossBar, int duration);
|
||||
|
||||
/**
|
||||
* Returns list of BossBars which are currently being announced.
|
||||
@@ -161,5 +175,5 @@ public interface BossBarManager {
|
||||
* @see #sendBossBarTemporarily(TabPlayer, String, int)
|
||||
* @see #announceBossBar(String, int)
|
||||
*/
|
||||
List<BossBar> getAnnouncedBossBars();
|
||||
@NotNull List<BossBar> getAnnouncedBossBars();
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
package me.neznamy.tab.api.chat;
|
||||
|
||||
import me.neznamy.tab.api.util.Preconditions;
|
||||
|
||||
/**
|
||||
* Class for click event action in chat component
|
||||
*/
|
||||
public class ChatClickable {
|
||||
|
||||
/** 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");
|
||||
Preconditions.checkNotNull(value, "hover value");
|
||||
this.action = action;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns click action defined in constructor
|
||||
*
|
||||
* @return click action
|
||||
*/
|
||||
public EnumClickAction getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns click action defined in constructor
|
||||
*
|
||||
* @return click action
|
||||
*/
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum for all possible click actions
|
||||
*/
|
||||
public enum EnumClickAction {
|
||||
|
||||
OPEN_URL,
|
||||
RUN_COMMAND,
|
||||
CHANGE_PAGE, //since 1.8
|
||||
SUGGEST_COMMAND,
|
||||
COPY_TO_CLIPBOARD //since 1.15
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package me.neznamy.tab.api.chat;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import me.neznamy.tab.api.TabAPI;
|
||||
import me.neznamy.tab.api.util.Preconditions;
|
||||
|
||||
public class ChatComponentEntity extends IChatBaseComponent {
|
||||
|
||||
private final String CONTENTS;
|
||||
private final String VALUE_1_13;
|
||||
private final String VALUE_1_12;
|
||||
private final String VALUE_1_8;
|
||||
|
||||
public ChatComponentEntity(String type, UUID id, String name) {
|
||||
Preconditions.checkNotNull(type, "type");
|
||||
Preconditions.checkNotNull(id, "id");
|
||||
this.CONTENTS = String.format("{\"type\":\"%s\",\"id\":\"%s\",\"name\":{\"text\":\"%s\"}}", type, id, name);
|
||||
this.VALUE_1_13 = String.format("{type:\"%s\",id:\"%s\",name:\"{\\\"text\\\":\\\"%s\\\"}\"}", type, id, name);
|
||||
this.VALUE_1_12 = String.format("{type:\"%s\",id:\"%s\",name:\"%s\"}", type, id, name);
|
||||
this.VALUE_1_8 = String.format("{type:%s,id:%s,name:%s}", type, id, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toRawText() {
|
||||
return toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (TabAPI.getInstance().getServerVersion().getMinorVersion() >= 16) return CONTENTS;
|
||||
if (TabAPI.getInstance().getServerVersion().getMinorVersion() >= 13) return VALUE_1_13;
|
||||
if (TabAPI.getInstance().getServerVersion().getMinorVersion() == 12) return VALUE_1_12;
|
||||
if (TabAPI.getInstance().getServerVersion().getMinorVersion() >= 8) return VALUE_1_8;
|
||||
throw new IllegalStateException("show_entity hover action is not supported on <1.8");
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
package me.neznamy.tab.api.chat;
|
||||
|
||||
import me.neznamy.tab.api.util.Preconditions;
|
||||
|
||||
/**
|
||||
* Class for hover event action in chat component
|
||||
*/
|
||||
public class ChatHoverable {
|
||||
|
||||
/** 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");
|
||||
Preconditions.checkNotNull(value, "hover value");
|
||||
this.action = action;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns hover action defined in constructor
|
||||
*
|
||||
* @return hover action
|
||||
*/
|
||||
public EnumHoverAction getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns hover value defined in constructor
|
||||
*
|
||||
* @return hover value
|
||||
*/
|
||||
public IChatBaseComponent getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum for all possible hover actions
|
||||
*/
|
||||
public enum EnumHoverAction {
|
||||
|
||||
SHOW_TEXT("contents"),
|
||||
SHOW_ITEM("value"),
|
||||
SHOW_ENTITY("contents");
|
||||
|
||||
private final String preferredKey;
|
||||
|
||||
EnumHoverAction(String preferredKey) {
|
||||
this.preferredKey = preferredKey;
|
||||
}
|
||||
|
||||
public String getPreferredKey() {
|
||||
return preferredKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,316 +0,0 @@
|
||||
package me.neznamy.tab.api.chat;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import me.neznamy.tab.api.util.Preconditions;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import me.neznamy.tab.api.ProtocolVersion;
|
||||
import me.neznamy.tab.api.TabAPI;
|
||||
import me.neznamy.tab.api.chat.ChatClickable.EnumClickAction;
|
||||
import me.neznamy.tab.api.chat.ChatHoverable.EnumHoverAction;
|
||||
|
||||
public class ChatModifier {
|
||||
|
||||
private TextColor color;
|
||||
|
||||
private Boolean bold;
|
||||
private Boolean italic;
|
||||
private Boolean underlined;
|
||||
private Boolean strikethrough;
|
||||
private Boolean obfuscated;
|
||||
|
||||
private ChatClickable clickEvent;
|
||||
private ChatHoverable hoverEvent;
|
||||
|
||||
private String font;
|
||||
|
||||
private ProtocolVersion targetVersion;
|
||||
|
||||
public ChatModifier() {
|
||||
}
|
||||
|
||||
public ChatModifier(ChatModifier modifier) {
|
||||
Preconditions.checkNotNull(modifier, "modifier");
|
||||
this.color = modifier.color == null ? null : new TextColor(modifier.color);
|
||||
this.bold = modifier.bold;
|
||||
this.italic = modifier.italic;
|
||||
this.underlined = modifier.underlined;
|
||||
this.strikethrough = modifier.strikethrough;
|
||||
this.obfuscated = modifier.obfuscated;
|
||||
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() {
|
||||
return color;
|
||||
}
|
||||
|
||||
public void setColor(TextColor color) {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public Boolean getBold() {
|
||||
return bold;
|
||||
}
|
||||
|
||||
public void setBold(Boolean bold) {
|
||||
this.bold = bold;
|
||||
}
|
||||
|
||||
public Boolean getItalic() {
|
||||
return italic;
|
||||
}
|
||||
|
||||
public void setItalic(Boolean italic) {
|
||||
this.italic = italic;
|
||||
}
|
||||
|
||||
public Boolean getUnderlined() {
|
||||
return underlined;
|
||||
}
|
||||
|
||||
public void setUnderlined(Boolean underlined) {
|
||||
this.underlined = underlined;
|
||||
}
|
||||
|
||||
public Boolean getStrikethrough() {
|
||||
return strikethrough;
|
||||
}
|
||||
|
||||
public void setStrikethrough(Boolean strikethrough) {
|
||||
this.strikethrough = strikethrough;
|
||||
}
|
||||
|
||||
public Boolean getObfuscated() {
|
||||
return obfuscated;
|
||||
}
|
||||
|
||||
public void setObfuscated(Boolean obfuscated) {
|
||||
this.obfuscated = obfuscated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if bold is defined and set to true, false otherwise
|
||||
*
|
||||
* @return true if bold is defined and set to true, false otherwise
|
||||
*/
|
||||
public boolean isBold(){
|
||||
return Boolean.TRUE.equals(bold);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if italic is defined and set to true, false otherwise
|
||||
*
|
||||
* @return true if italic is defined and set to true, false otherwise
|
||||
*/
|
||||
public boolean isItalic(){
|
||||
return Boolean.TRUE.equals(italic);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if underlined is defined and set to true, false otherwise
|
||||
*
|
||||
* @return true if underlined is defined and set to true, false otherwise
|
||||
*/
|
||||
public boolean isUnderlined(){
|
||||
return Boolean.TRUE.equals(underlined);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if strikethrough is defined and set to true, false otherwise
|
||||
*
|
||||
* @return true if strikethrough is defined and set to true, false otherwise
|
||||
*/
|
||||
public boolean isStrikethrough(){
|
||||
return Boolean.TRUE.equals(strikethrough);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if obfuscation is defined and set to true, false otherwise
|
||||
*
|
||||
* @return true if obfuscation is defined and set to true, false otherwise
|
||||
*/
|
||||
public boolean isObfuscated(){
|
||||
return Boolean.TRUE.equals(obfuscated);
|
||||
}
|
||||
|
||||
public ChatClickable getClickEvent() {
|
||||
return clickEvent;
|
||||
}
|
||||
|
||||
public void setClickEvent(ChatClickable clickEvent) {
|
||||
this.clickEvent = clickEvent;
|
||||
}
|
||||
|
||||
public ChatHoverable getHoverEvent() {
|
||||
return hoverEvent;
|
||||
}
|
||||
|
||||
public void setHoverEvent(ChatHoverable hoverEvent) {
|
||||
this.hoverEvent = hoverEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets click action to OPEN_URL and url to given value
|
||||
*
|
||||
* @param url
|
||||
* url to open
|
||||
*/
|
||||
public void onClickOpenUrl(String url) {
|
||||
Preconditions.checkNotNull(url, "url");
|
||||
clickEvent = new ChatClickable(EnumClickAction.OPEN_URL, url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets click action to RUN_COMMAND and command to given value
|
||||
*
|
||||
* @param command
|
||||
* command to perform, might be without / to send a chat message
|
||||
*/
|
||||
public void onClickRunCommand(String command) {
|
||||
Preconditions.checkNotNull(command, "command");
|
||||
clickEvent = new ChatClickable(EnumClickAction.RUN_COMMAND, command);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets click action to SUGGEST_COMMAND and command to given value
|
||||
*
|
||||
* @param command
|
||||
* command to suggest
|
||||
*/
|
||||
public void onClickSuggestCommand(String command) {
|
||||
Preconditions.checkNotNull(command, "command");
|
||||
clickEvent = new ChatClickable(EnumClickAction.SUGGEST_COMMAND, command);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets click action to CHANGE_PAGE and page id to given value
|
||||
*
|
||||
* @param newPage
|
||||
* id of new page
|
||||
*/
|
||||
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));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
Preconditions.checkNotNull(text, "text");
|
||||
clickEvent = new ChatClickable(EnumClickAction.COPY_TO_CLIPBOARD, text);
|
||||
}
|
||||
|
||||
public void onClick(EnumClickAction action, String value) {
|
||||
Preconditions.checkNotNull(action, "action");
|
||||
Preconditions.checkNotNull(value, "value");
|
||||
clickEvent = new ChatClickable(action, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets hover action to SHOW_TEXT and text to given value
|
||||
*
|
||||
* @param text
|
||||
* text to show
|
||||
*/
|
||||
public void onHoverShowText(IChatBaseComponent text) {
|
||||
Preconditions.checkNotNull(text, "text");
|
||||
hoverEvent = new ChatHoverable(EnumHoverAction.SHOW_TEXT, text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets hover action to SHOW_ITEM and item to given value
|
||||
*
|
||||
* @param serializedItem
|
||||
* item to show
|
||||
*/
|
||||
public void onHoverShowItem(String serializedItem) {
|
||||
Preconditions.checkNotNull(serializedItem, "item");
|
||||
hoverEvent = new ChatHoverable(EnumHoverAction.SHOW_ITEM, new IChatBaseComponent(serializedItem));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets hover action to SHOW_ENTITY and entity data to given values
|
||||
*
|
||||
* @param type
|
||||
* entity type
|
||||
* @param id
|
||||
* entity uuid
|
||||
* @param name
|
||||
* entity custom name
|
||||
*/
|
||||
public void onHoverShowEntity(String type, UUID id, String name) {
|
||||
Preconditions.checkNotNull(type, "type");
|
||||
Preconditions.checkNotNull(id, "id");
|
||||
hoverEvent = new ChatHoverable(EnumHoverAction.SHOW_ENTITY, new ChatComponentEntity(type, id, name));
|
||||
}
|
||||
|
||||
public void onHover(EnumHoverAction action, IChatBaseComponent value) {
|
||||
Preconditions.checkNotNull(action, "action");
|
||||
Preconditions.checkNotNull(value, "value");
|
||||
hoverEvent = new ChatHoverable(action, value);
|
||||
}
|
||||
|
||||
public String getFont() {
|
||||
return font;
|
||||
}
|
||||
|
||||
public void setFont(String font) {
|
||||
this.font = font;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public JSONObject serialize() {
|
||||
JSONObject json = new JSONObject();
|
||||
if (color != null) json.put("color", targetVersion.getMinorVersion() >= 16 ? color.toString() : color.getLegacyColor().toString().toLowerCase());
|
||||
if (bold != null) json.put("bold", bold);
|
||||
if (italic != null) json.put("italic", italic);
|
||||
if (underlined != null) json.put("underlined", underlined);
|
||||
if (strikethrough != null) json.put("strikethrough", strikethrough);
|
||||
if (obfuscated != null) json.put("obfuscated", obfuscated);
|
||||
if (clickEvent != null) {
|
||||
JSONObject click = new JSONObject();
|
||||
click.put("action", clickEvent.getAction().toString().toLowerCase());
|
||||
click.put("value", clickEvent.getValue());
|
||||
json.put("clickEvent", click);
|
||||
}
|
||||
if (hoverEvent != null) {
|
||||
JSONObject hover = new JSONObject();
|
||||
hover.put("action", hoverEvent.getAction().toString().toLowerCase());
|
||||
if (TabAPI.getInstance().getServerVersion().getMinorVersion() >= 16) {
|
||||
hover.put(hoverEvent.getAction().getPreferredKey(), hoverEvent.getValue());
|
||||
} else {
|
||||
hover.put("value", TabAPI.getInstance().getServerVersion().getMinorVersion() >= 9 ?
|
||||
hoverEvent.getValue() : hoverEvent.getValue().toRawText());
|
||||
}
|
||||
json.put("hoverEvent", hover);
|
||||
}
|
||||
if (font != null) json.put("font", font);
|
||||
return json;
|
||||
}
|
||||
|
||||
public String getMagicCodes() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (isBold()) builder.append(EnumChatFormat.BOLD.getFormat());
|
||||
if (isItalic()) builder.append(EnumChatFormat.ITALIC.getFormat());
|
||||
if (isUnderlined()) builder.append(EnumChatFormat.UNDERLINE.getFormat());
|
||||
if (isStrikethrough()) builder.append(EnumChatFormat.STRIKETHROUGH.getFormat());
|
||||
if (isObfuscated()) builder.append(EnumChatFormat.OBFUSCATED.getFormat());
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public void setTargetVersion(ProtocolVersion targetVersion) {
|
||||
this.targetVersion = targetVersion;
|
||||
}
|
||||
|
||||
public ProtocolVersion getTargetVersion() {
|
||||
return targetVersion;
|
||||
}
|
||||
}
|
||||
@@ -1,171 +0,0 @@
|
||||
package me.neznamy.tab.api.chat;
|
||||
|
||||
import me.neznamy.tab.api.ProtocolVersion;
|
||||
import me.neznamy.tab.api.TabAPI;
|
||||
import me.neznamy.tab.api.util.Preconditions;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.json.simple.parser.ParseException;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A class representing a chat component that was serialized before,
|
||||
* but deserialize was requested in PacketPlayOutPlayerInfo packet.
|
||||
* This is used to read and modify the packet and then rewrite it.
|
||||
* However, display name components must be deserialized to properly
|
||||
* forward them in the new packet, but its value is not actually
|
||||
* used anywhere.
|
||||
* <p>
|
||||
* To avoid this heavy and completely unnecessary operation, the original
|
||||
* string is saved and returned during serialization. If any read/write
|
||||
* operation is performed, the string is fully deserialized and this object
|
||||
* will act like a normal chat component.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class DeserializedChatComponent extends IChatBaseComponent {
|
||||
|
||||
/** The original serialized component string */
|
||||
private final String json;
|
||||
|
||||
/**
|
||||
* Flag tracking whether this component was fully deserialized
|
||||
* in case of a read operation to avoid repeating the deserialization
|
||||
* process on every request.
|
||||
*/
|
||||
private boolean deserialized;
|
||||
|
||||
/**
|
||||
* Flag tracking whether this component was modified, which means
|
||||
* a new string has to be created instead of returning the input one.
|
||||
*/
|
||||
private boolean modified;
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameter
|
||||
*
|
||||
* @param json
|
||||
* serialized component as string
|
||||
*/
|
||||
public DeserializedChatComponent(String json) {
|
||||
Preconditions.checkNotNull(json, "json");
|
||||
this.json = json;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (modified) return super.toString();
|
||||
return json;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ProtocolVersion clientVersion) {
|
||||
if (modified) return super.toString(clientVersion);
|
||||
return json;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IChatBaseComponent> getExtra(){
|
||||
if (!deserialized) deserialize();
|
||||
return super.getExtra();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
if (!deserialized) deserialize();
|
||||
return super.getText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChatModifier getModifier() {
|
||||
if (!deserialized) deserialize();
|
||||
return super.getModifier();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IChatBaseComponent setExtra(List<IChatBaseComponent> components){
|
||||
if (!deserialized) deserialize();
|
||||
modified = true;
|
||||
return super.setExtra(components);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addExtra(IChatBaseComponent child) {
|
||||
if (!deserialized) deserialize();
|
||||
modified = true;
|
||||
super.addExtra(child);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModifier(ChatModifier modifier) {
|
||||
if (!deserialized) deserialize();
|
||||
modified = true;
|
||||
super.setModifier(modifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a full deserialization process on this component.
|
||||
*/
|
||||
void deserialize() {
|
||||
deserialized = true;
|
||||
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
|
||||
setText(json.substring(1, json.length()-1));
|
||||
return;
|
||||
}
|
||||
JSONObject jsonObject;
|
||||
try {
|
||||
jsonObject = (JSONObject) new JSONParser().parse(json);
|
||||
} catch (ParseException e) {
|
||||
TabAPI.getInstance().logError("Failed to deserialize json component " + json, e);
|
||||
return;
|
||||
}
|
||||
/* if (jsonObject.containsKey("type")) {
|
||||
return new ChatComponentEntity((String) jsonObject.get("type"), UUID.fromString((String) jsonObject.get("id")), IChatBaseComponent.deserialize(jsonObject.get("name").toString()).toFlatText());
|
||||
}*/
|
||||
setText((String) jsonObject.get("text"));
|
||||
getModifier().setBold(getBoolean(jsonObject, "bold"));
|
||||
getModifier().setItalic(getBoolean(jsonObject, "italic"));
|
||||
getModifier().setUnderlined(getBoolean(jsonObject, "underlined"));
|
||||
getModifier().setStrikethrough(getBoolean(jsonObject, "strikethrough"));
|
||||
getModifier().setObfuscated(getBoolean(jsonObject, "obfuscated"));
|
||||
getModifier().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();
|
||||
getModifier().onClick(ChatClickable.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");
|
||||
getModifier().onHover(ChatHoverable.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 + "\"";
|
||||
addExtra(IChatBaseComponent.deserialize(string));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
Preconditions.checkNotNull(jsonObject, "json object");
|
||||
Preconditions.checkNotNull(key, "key");
|
||||
String value = String.valueOf(jsonObject.getOrDefault(key, null));
|
||||
return "null".equals(value) ? null : Boolean.parseBoolean(value);
|
||||
}
|
||||
}
|
||||
@@ -1,260 +0,0 @@
|
||||
package me.neznamy.tab.api.chat;
|
||||
|
||||
import me.neznamy.tab.api.chat.rgb.RGBUtils;
|
||||
|
||||
/**
|
||||
* An enum containing all possible legacy color codes and magic codes. Also contains handy color-related methods.
|
||||
*/
|
||||
public enum EnumChatFormat {
|
||||
|
||||
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 */
|
||||
public 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);
|
||||
|
||||
/** Character representing the color or magic code */
|
||||
private final char character;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** Color as 6-digit hex code, null for magic codes */
|
||||
private final String hexCode;
|
||||
|
||||
/** Color symbol followed by constant's character */
|
||||
private final String chatFormat;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
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 = (short) ((hexColor >> 16) & 0xFF);
|
||||
green = (short) ((hexColor >> 8) & 0xFF);
|
||||
blue = (short) (hexColor & 0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new magic code instance with given character
|
||||
*
|
||||
* @param character
|
||||
* character representing the magic code
|
||||
*/
|
||||
EnumChatFormat(char character) {
|
||||
this.character = character;
|
||||
this.chatFormat = String.valueOf(COLOR_CHAR) + character;
|
||||
red = 0;
|
||||
green = 0;
|
||||
blue = 0;
|
||||
hexCode = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns red value of this color code
|
||||
*
|
||||
* @return red value
|
||||
*/
|
||||
public short getRed() {
|
||||
return red;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns green value of this color code
|
||||
*
|
||||
* @return green value
|
||||
*/
|
||||
public short getGreen() {
|
||||
return green;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns blue value of this color code
|
||||
*
|
||||
* @return blue value
|
||||
*/
|
||||
public short getBlue() {
|
||||
return blue;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
if (format.character == c) return format;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
String last = getLastColors(legacyText);
|
||||
if (last.length() > 0) {
|
||||
char c = last.toCharArray()[1];
|
||||
for (EnumChatFormat e : VALUES) {
|
||||
if (e.character == c) return e;
|
||||
}
|
||||
}
|
||||
return EnumChatFormat.WHITE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns color char followed by color's character
|
||||
*
|
||||
* @return color char followed by color's character
|
||||
*/
|
||||
public String getFormat() {
|
||||
return chatFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns character representing this color
|
||||
*
|
||||
* @return character representing this color
|
||||
*/
|
||||
public char getCharacter() {
|
||||
return character;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns hex code of this format, null if this is a magic code
|
||||
*
|
||||
* @return hex code of this format
|
||||
*/
|
||||
public String getHexCode() {
|
||||
return hexCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
if (format.red == red && format.green == green && format.blue == blue) return format;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
char[] b = textToTranslate.toCharArray();
|
||||
for (int i = 0; i < b.length - 1; i++) {
|
||||
if ((b[i] == '&') && ("0123456789AaBbCcDdEeFfKkLlMmNnOoRrXx".indexOf(b[(i + 1)]) > -1)){
|
||||
b[i] = COLOR_CHAR;
|
||||
b[(i + 1)] = Character.toLowerCase(b[(i + 1)]);
|
||||
}
|
||||
}
|
||||
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, 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) {
|
||||
if (input == null) return "";
|
||||
StringBuilder result = new StringBuilder();
|
||||
int length = input.length();
|
||||
for (int index = length - 1; index > -1; index--){
|
||||
char section = input.charAt(index);
|
||||
if ((section == COLOR_CHAR || section == '&') && (index < length - 1)){
|
||||
char c = input.charAt(index + 1);
|
||||
if ("0123456789AaBbCcDdEeFfKkLlMmNnOoRr".contains(String.valueOf(c))) {
|
||||
result.insert(0, COLOR_CHAR);
|
||||
result.insert(1, c);
|
||||
if ("0123456789AaBbCcDdEeFfRr".contains(String.valueOf(c))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,438 +0,0 @@
|
||||
package me.neznamy.tab.api.chat;
|
||||
|
||||
import me.neznamy.tab.api.ProtocolVersion;
|
||||
import me.neznamy.tab.api.TabAPI;
|
||||
import me.neznamy.tab.api.chat.rgb.RGBUtils;
|
||||
import me.neznamy.tab.api.util.Preconditions;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A class representing the n.m.s.IChatBaseComponent class to make work with it much easier
|
||||
*/
|
||||
@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<>();
|
||||
|
||||
/** Text of the component */
|
||||
private String text;
|
||||
|
||||
/** Chat modifier containing color, magic codes, hover and click event */
|
||||
private ChatModifier modifier = new ChatModifier();
|
||||
|
||||
/** Extra components used in "extra" field */
|
||||
private List<IChatBaseComponent> extra;
|
||||
|
||||
/**
|
||||
* Constructs a new empty component
|
||||
*/
|
||||
public IChatBaseComponent() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new component which is a clone of provided component
|
||||
*
|
||||
* @param component
|
||||
* component to clone
|
||||
*/
|
||||
public IChatBaseComponent(IChatBaseComponent component) {
|
||||
Preconditions.checkNotNull(component, "component");
|
||||
this.text = component.text;
|
||||
this.modifier = new ChatModifier(component.modifier);
|
||||
for (IChatBaseComponent child : component.getExtra()) {
|
||||
addExtra(new IChatBaseComponent(child));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance with given text
|
||||
*
|
||||
* @param text
|
||||
* text to display
|
||||
*/
|
||||
public IChatBaseComponent(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 Collections.emptyList();
|
||||
return extra;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
this.extra = components;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends provided component as extra component
|
||||
*
|
||||
* @param child
|
||||
* component to append
|
||||
*/
|
||||
public void addExtra(IChatBaseComponent child) {
|
||||
Preconditions.checkNotNull(child, "extra");
|
||||
if (extra == null) extra = new ArrayList<>();
|
||||
extra.add(child);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes text of this component
|
||||
*
|
||||
* @param text
|
||||
* text to show
|
||||
*/
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
return new DeserializedChatComponent(json);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
if (text != null) json.put("text", text);
|
||||
if (modifier.getTargetVersion() == null) modifier.setTargetVersion(TabAPI.getInstance().getServerVersion()); //packet.toString() was called as a part of a debug message
|
||||
json.putAll(modifier.serialize());
|
||||
if (extra != null) json.put("extra", extra);
|
||||
return json.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* 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 "{\"translate\":\"\"}";
|
||||
} else {
|
||||
return "{\"text\":\"\"}";
|
||||
}
|
||||
}
|
||||
}
|
||||
modifier.setTargetVersion(clientVersion);
|
||||
for (IChatBaseComponent child : getExtra()) {
|
||||
child.modifier.setTargetVersion(clientVersion);
|
||||
}
|
||||
String string;
|
||||
if (clientVersion.getMinorVersion() >= 16) {
|
||||
if (serializeCacheModern.containsKey(this)) return serializeCacheModern.get(this);
|
||||
string = toString();
|
||||
if (serializeCacheModern.size() > 10000) serializeCacheModern.clear();
|
||||
serializeCacheModern.put(this, string);
|
||||
} else {
|
||||
if (serializeCacheLegacy.containsKey(this)) return serializeCacheLegacy.get(this);
|
||||
string = toString();
|
||||
if (serializeCacheLegacy.size() > 10000) serializeCacheLegacy.clear();
|
||||
serializeCacheLegacy.put(this, string);
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns organized component from colored text
|
||||
*
|
||||
* @param originalText
|
||||
* text to convert
|
||||
* @return organized component from colored text
|
||||
*/
|
||||
public static IChatBaseComponent fromColoredText(String originalText){
|
||||
Preconditions.checkNotNull(originalText, "text");
|
||||
String text = RGBUtils.getInstance().applyFormats(EnumChatFormat.color(originalText));
|
||||
List<IChatBaseComponent> components = new ArrayList<>();
|
||||
StringBuilder builder = new StringBuilder();
|
||||
IChatBaseComponent component = new IChatBaseComponent();
|
||||
for (int i = 0; i < text.length(); i++){
|
||||
char c = text.charAt(i);
|
||||
if (c == EnumChatFormat.COLOR_CHAR){
|
||||
i++;
|
||||
if (i >= text.length()) {
|
||||
break;
|
||||
}
|
||||
c = text.charAt(i);
|
||||
if ((c >= 'A') && (c <= 'Z')) {
|
||||
c = (char)(c + ' ');
|
||||
}
|
||||
EnumChatFormat format = EnumChatFormat.getByChar(c);
|
||||
if (format != null){
|
||||
if (builder.length() > 0) {
|
||||
component.setText(builder.toString());
|
||||
components.add(component);
|
||||
component = new IChatBaseComponent(component);
|
||||
component.text = null;
|
||||
builder = new StringBuilder();
|
||||
}
|
||||
switch (format){
|
||||
case BOLD:
|
||||
component.modifier.setBold(true);
|
||||
break;
|
||||
case ITALIC:
|
||||
component.modifier.setItalic(true);
|
||||
break;
|
||||
case UNDERLINE:
|
||||
component.modifier.setUnderlined(true);
|
||||
break;
|
||||
case STRIKETHROUGH:
|
||||
component.modifier.setStrikethrough(true);
|
||||
break;
|
||||
case OBFUSCATED:
|
||||
component.modifier.setObfuscated(true);
|
||||
break;
|
||||
case RESET:
|
||||
component = new IChatBaseComponent();
|
||||
component.modifier.setColor(new TextColor(EnumChatFormat.WHITE));
|
||||
break;
|
||||
default:
|
||||
component = new IChatBaseComponent();
|
||||
component.modifier.setColor(new TextColor(format));
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (c == '#' && text.length() > i+6){
|
||||
String hex = text.substring(i+1, i+7);
|
||||
if (RGBUtils.getInstance().isHexCode(hex)) {
|
||||
TextColor color;
|
||||
if (containsLegacyCode(text, i)) {
|
||||
color = new TextColor(hex, EnumChatFormat.getByChar(text.charAt(i+8)));
|
||||
i += 8;
|
||||
} else {
|
||||
color = new TextColor(hex);
|
||||
i += 6;
|
||||
}
|
||||
if (builder.length() > 0){
|
||||
component.setText(builder.toString());
|
||||
components.add(component);
|
||||
builder = new StringBuilder();
|
||||
}
|
||||
component = new IChatBaseComponent();
|
||||
component.modifier.setColor(color);
|
||||
} else {
|
||||
builder.append(c);
|
||||
}
|
||||
} else {
|
||||
builder.append(c);
|
||||
}
|
||||
}
|
||||
component.setText(builder.toString());
|
||||
components.add(component);
|
||||
return new IChatBaseComponent("").setExtra(components);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
private static boolean containsLegacyCode(String text, int i) {
|
||||
if (text.length() - i < 9 || text.charAt(i+7) != '|') return false;
|
||||
return EnumChatFormat.getByChar(text.charAt(i+8)) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
append(builder, "");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 new formatting, might be identical to previous one
|
||||
*/
|
||||
private String append(StringBuilder builder, String previousFormatting) {
|
||||
String formatting = previousFormatting;
|
||||
if (text != null) {
|
||||
formatting = getFormatting();
|
||||
if (!formatting.equals(previousFormatting)) {
|
||||
builder.append(formatting);
|
||||
}
|
||||
builder.append(text);
|
||||
|
||||
}
|
||||
for (IChatBaseComponent component : getExtra()) {
|
||||
formatting = component.append(builder, formatting);
|
||||
}
|
||||
return formatting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns colors and magic codes of this component
|
||||
*
|
||||
* @return used colors and magic codes
|
||||
*/
|
||||
private String getFormatting() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (modifier.getColor() != null) {
|
||||
if (modifier.getColor().getLegacyColor() == EnumChatFormat.WHITE) {
|
||||
//preventing unwanted &r -> &f conversion and stopping the <1.13 client bug fix from working
|
||||
builder.append(EnumChatFormat.RESET.getFormat());
|
||||
} else {
|
||||
builder.append(modifier.getColor().getLegacyColor().getFormat());
|
||||
}
|
||||
}
|
||||
builder.append(modifier.getMagicCodes());
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns raw text without colors, only works correctly when component is organized
|
||||
*
|
||||
* @return raw text in this component and all child components
|
||||
*/
|
||||
public String toRawText() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (text != null) builder.append(text);
|
||||
for (IChatBaseComponent child : getExtra()) {
|
||||
if (child.text != null) builder.append(child.text);
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the component into flat text with used colors (including rgb) and magic codes
|
||||
*
|
||||
* @return converted text
|
||||
*/
|
||||
public String toFlatText() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (modifier.getColor() != null) builder.append("#").append(modifier.getColor().getHexCode());
|
||||
builder.append(modifier.getMagicCodes());
|
||||
if (text != null) builder.append(text);
|
||||
for (IChatBaseComponent child : getExtra()) {
|
||||
builder.append(child.toFlatText());
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
public static IChatBaseComponent optimizedComponent(String text){
|
||||
if (text == null) return null;
|
||||
if (componentCache.containsKey(text)) return componentCache.get(text);
|
||||
IChatBaseComponent component;
|
||||
if (text.contains("#") || text.contains("&x") || text.contains(EnumChatFormat.COLOR_CHAR + "x") || text.contains("<")){
|
||||
//contains RGB colors
|
||||
component = IChatBaseComponent.fromColoredText(text);
|
||||
} else {
|
||||
//no RGB
|
||||
component = new IChatBaseComponent(text);
|
||||
}
|
||||
if (componentCache.size() > 10000) componentCache.clear();
|
||||
componentCache.put(text, component);
|
||||
return component;
|
||||
}
|
||||
}
|
||||
@@ -1,222 +0,0 @@
|
||||
package me.neznamy.tab.api.chat;
|
||||
|
||||
import me.neznamy.tab.api.util.Preconditions;
|
||||
|
||||
/**
|
||||
* A class representing a component color, which can be either RGB or legacy code.
|
||||
*/
|
||||
public class TextColor {
|
||||
|
||||
/**
|
||||
* 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 to this color object. */
|
||||
private EnumChatFormat legacyColor;
|
||||
|
||||
/** HEX code of this color as a 6-digit hexadecimal string without "#" prefix. */
|
||||
private String hexCode;
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
Preconditions.checkNotNull(color, "color");
|
||||
rgb = color.rgb;
|
||||
legacyColor = color.legacyColor;
|
||||
hexCode = color.hexCode;
|
||||
legacyColorForced = color.legacyColorForced;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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");
|
||||
this.hexCode = hexCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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");
|
||||
Preconditions.checkNotNull(legacyColor, "legacy color");
|
||||
this.hexCode = hexCode;
|
||||
this.legacyColorForced = true;
|
||||
this.legacyColor = legacyColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
Preconditions.checkNotNull(legacyColor, "legacy color");
|
||||
this.rgb = (legacyColor.getRed() << 16) + (legacyColor.getGreen() << 8) + legacyColor.getBlue();
|
||||
this.hexCode = legacyColor.getHexCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
Preconditions.checkRange(red, 0, 255, "red");
|
||||
Preconditions.checkRange(green, 0, 255, "green");
|
||||
Preconditions.checkRange(blue, 0, 255, "blue");
|
||||
this.rgb = (red << 16) + (green << 8) + blue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the closest legacy color based currently provided values
|
||||
*/
|
||||
private EnumChatFormat loadClosestColor() {
|
||||
double minMaxDist = 9999;
|
||||
double maxDist;
|
||||
EnumChatFormat closestColor = EnumChatFormat.WHITE;
|
||||
for (EnumChatFormat color : EnumChatFormat.VALUES) {
|
||||
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;
|
||||
if (maxDist < minMaxDist) {
|
||||
minMaxDist = maxDist;
|
||||
closestColor = color;
|
||||
}
|
||||
}
|
||||
return closestColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code red} value
|
||||
*
|
||||
* @return red value
|
||||
*/
|
||||
public int getRed() {
|
||||
if (rgb == -1) rgb = Integer.parseInt(hexCode, 16);
|
||||
return (rgb >> 16) & 0xFF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code green} value
|
||||
*
|
||||
* @return green value
|
||||
*/
|
||||
public int getGreen() {
|
||||
if (rgb == -1) rgb = Integer.parseInt(hexCode, 16);
|
||||
return (rgb >> 8) & 0xFF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code blue} value
|
||||
*
|
||||
* @return blue value
|
||||
*/
|
||||
public int getBlue() {
|
||||
if (rgb == -1) rgb = Integer.parseInt(hexCode, 16);
|
||||
return rgb & 0xFF;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 = loadClosestColor();
|
||||
return legacyColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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", rgb);
|
||||
return hexCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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());
|
||||
if (legacyEquivalent != null) {
|
||||
//not sending old colors as RGB to 1.16 clients if not needed as <1.16 servers will fail to apply color
|
||||
return legacyEquivalent.toString().toLowerCase();
|
||||
}
|
||||
return "#" + getHexCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 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;
|
||||
if (string.startsWith("#")) return new TextColor(string.substring(1));
|
||||
return new TextColor(EnumChatFormat.valueOf(string.toUpperCase()));
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
package me.neznamy.tab.api.chat;
|
||||
|
||||
import me.neznamy.tab.api.ProtocolVersion;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A class extending IChatBaseComponent that holds the original value
|
||||
* to avoid deserializing it, which is an unnecessary operation that
|
||||
* slows down the performance, as well as makes code more complicated
|
||||
* and open to problems.
|
||||
*/
|
||||
public class WrappedChatComponent extends IChatBaseComponent {
|
||||
|
||||
/** Original NMS component */
|
||||
private final Object originalComponent;
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameter
|
||||
*
|
||||
* @param originalComponent
|
||||
* Original NMS component
|
||||
*/
|
||||
public WrappedChatComponent(Object originalComponent) {
|
||||
this.originalComponent = originalComponent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the original NMS component
|
||||
* @return the original NMS component
|
||||
*/
|
||||
public Object get() {
|
||||
return originalComponent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
throw new UnsupportedOperationException("Not supported for " + getClass().getSimpleName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ProtocolVersion clientVersion) {
|
||||
throw new UnsupportedOperationException("Not supported for " + getClass().getSimpleName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IChatBaseComponent> getExtra(){
|
||||
throw new UnsupportedOperationException("Not supported for " + getClass().getSimpleName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
throw new UnsupportedOperationException("Not supported for " + getClass().getSimpleName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChatModifier getModifier() {
|
||||
throw new UnsupportedOperationException("Not supported for " + getClass().getSimpleName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public IChatBaseComponent setExtra(List<IChatBaseComponent> components){
|
||||
throw new UnsupportedOperationException("Not supported for " + getClass().getSimpleName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addExtra(IChatBaseComponent child) {
|
||||
throw new UnsupportedOperationException("Not supported for " + getClass().getSimpleName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModifier(ChatModifier modifier) {
|
||||
throw new UnsupportedOperationException("Not supported for " + getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
@@ -1,209 +0,0 @@
|
||||
package me.neznamy.tab.api.chat.rgb;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import me.neznamy.tab.api.chat.EnumChatFormat;
|
||||
import me.neznamy.tab.api.chat.TextColor;
|
||||
import me.neznamy.tab.api.chat.rgb.format.*;
|
||||
import me.neznamy.tab.api.chat.rgb.gradient.CMIGradient;
|
||||
import me.neznamy.tab.api.chat.rgb.gradient.CommonGradient;
|
||||
import me.neznamy.tab.api.chat.rgb.gradient.GradientPattern;
|
||||
import me.neznamy.tab.api.chat.rgb.gradient.KyoriGradient;
|
||||
import me.neznamy.tab.api.util.Preconditions;
|
||||
|
||||
/**
|
||||
* A helper class to reformat all RGB formats into the default #RRGGBB and apply gradients
|
||||
*/
|
||||
public class RGBUtils {
|
||||
|
||||
/** Instance of the class */
|
||||
private static final RGBUtils instance = new RGBUtils();
|
||||
|
||||
/** Registered RGB formatters */
|
||||
private final RGBFormatter[] formats;
|
||||
|
||||
/** Registered gradient patterns */
|
||||
private final GradientPattern[] gradients;
|
||||
|
||||
/** 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() {
|
||||
List<RGBFormatter> list = new ArrayList<>();
|
||||
try {
|
||||
Class.forName("net.kyori.adventure.text.minimessage.MiniMessage");
|
||||
list.add(new MiniMessageFormat());
|
||||
} catch (ClassNotFoundException ignored) {}
|
||||
list.add(new BukkitFormat());
|
||||
list.add(new CMIFormat());
|
||||
list.add(new UnnamedFormat1());
|
||||
list.add(new HtmlFormat());
|
||||
list.add(new KyoriFormat());
|
||||
formats = list.toArray(new RGBFormatter[0]);
|
||||
|
||||
gradients = new GradientPattern[] {
|
||||
//{#RRGGBB>}text{#RRGGBB<}
|
||||
new CMIGradient(),
|
||||
//<#RRGGBB>Text</#RRGGBB>
|
||||
new CommonGradient(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, 9, 7),
|
||||
//<$#RRGGBB>Text<$#RRGGBB>
|
||||
new CommonGradient(Pattern.compile("<\\$#[0-9a-fA-F]{6}>[^<]*<\\$#[0-9a-fA-F]{6}>"),
|
||||
Pattern.compile("<\\$#[0-9a-fA-F]{6}\\|.>[^<]*<\\$#[0-9a-fA-F]{6}>"),
|
||||
"<$", 10, 3, 10, 7),
|
||||
new KyoriGradient()
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns instance of this class
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
public String applyFormats(String text) {
|
||||
Preconditions.checkNotNull(text, "text");
|
||||
String replaced = text;
|
||||
for (GradientPattern pattern : gradients) {
|
||||
replaced = pattern.applyPattern(replaced, false);
|
||||
}
|
||||
for (RGBFormatter formatter : formats) {
|
||||
replaced = formatter.reformat(replaced);
|
||||
}
|
||||
return replaced;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies all gradient formats to text and returns it. This only affects
|
||||
* usage where no placeholder is used inside.
|
||||
*
|
||||
* @param text
|
||||
* original text
|
||||
* @return text where all gradients with static text are converted to #RRGGBB
|
||||
*/
|
||||
public String applyCleanGradients(String text) {
|
||||
Preconditions.checkNotNull(text, "text");
|
||||
String replaced = text;
|
||||
for (GradientPattern pattern : gradients) {
|
||||
replaced = pattern.applyPattern(replaced, true);
|
||||
}
|
||||
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
|
||||
String replaced = applyFormats(text);
|
||||
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));
|
||||
}
|
||||
}
|
||||
return replaced;
|
||||
} else {
|
||||
return convertRGBtoLegacy(text);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts all hex codes in given string to legacy codes
|
||||
*
|
||||
* @param text
|
||||
* text to convert
|
||||
* @return translated text
|
||||
*/
|
||||
public String convertRGBtoLegacy(String text) {
|
||||
if (text == null) return null;
|
||||
if (!text.contains("#")) return EnumChatFormat.color(text);
|
||||
String applied = applyFormats(text);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < applied.length(); i++){
|
||||
char c = applied.charAt(i);
|
||||
if (c == '#' && applied.length() > i+6) {
|
||||
String hexCode = applied.substring(i+1, i+7);
|
||||
if (isHexCode(hexCode)) {
|
||||
if (containsLegacyCode(applied, i)) {
|
||||
sb.append(new TextColor(hexCode, EnumChatFormat.getByChar(applied.charAt(i+8))).getLegacyColor().getFormat());
|
||||
i += 8;
|
||||
} else {
|
||||
sb.append(new TextColor(hexCode).getLegacyColor().getFormat());
|
||||
i += 6;
|
||||
}
|
||||
} else {
|
||||
sb.append(c);
|
||||
}
|
||||
} else {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
Preconditions.checkNotNull(string, "string");
|
||||
if (string.length() != 6) return false;
|
||||
for (int i=0; i<6; i++) {
|
||||
char c = string.charAt(i);
|
||||
if (c < 48 || (c > 57 && c < 65) || (c > 70 && c < 97) || c > 102) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if text contains legacy color request at defined RGB index start
|
||||
*
|
||||
* @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;
|
||||
return EnumChatFormat.getByChar(text.charAt(i+8)) != null;
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package me.neznamy.tab.api.chat.rgb.format;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import me.neznamy.tab.api.chat.EnumChatFormat;
|
||||
|
||||
/**
|
||||
* Formatter for &x&R&R&G&G&B&B
|
||||
*/
|
||||
public class BukkitFormat implements RGBFormatter {
|
||||
|
||||
private final Pattern pattern = Pattern.compile("[" + EnumChatFormat.COLOR_CHAR + "&]x[" + EnumChatFormat.COLOR_CHAR + "&\\p{XDigit}]{12}");
|
||||
|
||||
@Override
|
||||
public String reformat(String text) {
|
||||
if (!text.contains("&x") && !text.contains(EnumChatFormat.COLOR_CHAR + "x")) return text;
|
||||
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);
|
||||
}
|
||||
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 CMIFormat implements RGBFormatter {
|
||||
|
||||
private final Pattern pattern = Pattern.compile("\\{#[0-9a-fA-F]{6}}");
|
||||
|
||||
@Override
|
||||
public String reformat(String text) {
|
||||
if (!text.contains("{#")) return text;
|
||||
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);
|
||||
}
|
||||
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 HtmlFormat 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;
|
||||
}
|
||||
}
|
||||
@@ -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 KyoriFormat implements RGBFormatter {
|
||||
|
||||
private final Pattern pattern = Pattern.compile("<#[0-9a-fA-F]{6}>");
|
||||
|
||||
@Override
|
||||
public String reformat(String text) {
|
||||
if (!text.contains("<#")) return text;
|
||||
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);
|
||||
}
|
||||
return replaced;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package me.neznamy.tab.api.chat.rgb.format;
|
||||
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
|
||||
/**
|
||||
* Call to MiniMessage API to reformat text to &x&R&R&G&G&B&B
|
||||
*/
|
||||
public class MiniMessageFormat implements RGBFormatter {
|
||||
|
||||
@Override
|
||||
public String reformat(String text) {
|
||||
if (!text.contains("<")) return text;
|
||||
try {
|
||||
return LegacyComponentSerializer.legacySection().serialize(MiniMessage.miniMessage().deserialize(text));
|
||||
} catch (Throwable ignored) {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package me.neznamy.tab.api.chat.rgb.format;
|
||||
|
||||
/**
|
||||
* Abstract class for different RGB patterns
|
||||
*/
|
||||
public interface RGBFormatter {
|
||||
|
||||
/**
|
||||
* Reformats RGB codes in provided text into #RRGGBB format
|
||||
*
|
||||
* @param text
|
||||
* text to format
|
||||
* @return reformatted text
|
||||
*/
|
||||
String reformat(String text);
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package me.neznamy.tab.api.chat.rgb.format;
|
||||
|
||||
/**
|
||||
* Formatter for &#RRGGBB
|
||||
*/
|
||||
public class UnnamedFormat1 implements RGBFormatter {
|
||||
|
||||
@Override
|
||||
public String reformat(String text) {
|
||||
return text.contains("&#") ? text.replace("&#", "#") : text;
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
package me.neznamy.tab.api.chat.rgb.gradient;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import me.neznamy.tab.api.chat.EnumChatFormat;
|
||||
import me.neznamy.tab.api.chat.TextColor;
|
||||
|
||||
public class CommonGradient implements GradientPattern {
|
||||
|
||||
private final Pattern pattern;
|
||||
private final Pattern legacyPattern;
|
||||
private final String containCheck;
|
||||
private final int legacyCharPosition;
|
||||
private final int startColorStart;
|
||||
private final int messageStart;
|
||||
private final int endColorStartSub;
|
||||
|
||||
public CommonGradient(Pattern pattern, Pattern legacyPattern, String containCheck, int legacyCharPosition,
|
||||
int startColorStart, int messageStart, int endColorStartSub) {
|
||||
this.pattern = pattern;
|
||||
this.legacyPattern = legacyPattern;
|
||||
this.containCheck = containCheck;
|
||||
this.legacyCharPosition = legacyCharPosition;
|
||||
this.startColorStart = startColorStart;
|
||||
this.messageStart = messageStart;
|
||||
this.endColorStartSub = endColorStartSub;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String applyPattern(String text, boolean ignorePlaceholders) {
|
||||
if (!text.contains(containCheck)) return text;
|
||||
String replaced = text;
|
||||
Matcher m = legacyPattern.matcher(replaced);
|
||||
while (m.find()) {
|
||||
String format = m.group();
|
||||
EnumChatFormat legacyColor = EnumChatFormat.getByChar(format.charAt(legacyCharPosition));
|
||||
if ((ignorePlaceholders && format.contains("%")) || legacyColor == null) continue;
|
||||
TextColor start = new TextColor(format.substring(startColorStart, startColorStart+6), legacyColor);
|
||||
String message = format.substring(messageStart+2, format.length()-10);
|
||||
TextColor end = new TextColor(format.substring(format.length()-endColorStartSub, format.length()-endColorStartSub+6));
|
||||
String applied = asGradient(start, message, end);
|
||||
replaced = replaced.replace(format, applied);
|
||||
}
|
||||
m = pattern.matcher(replaced);
|
||||
while (m.find()) {
|
||||
String format = m.group();
|
||||
if (ignorePlaceholders && format.contains("%")) continue;
|
||||
TextColor start = new TextColor(format.substring(startColorStart, startColorStart+6));
|
||||
String message = format.substring(messageStart, format.length()-10);
|
||||
TextColor end = new TextColor(format.substring(format.length()-endColorStartSub, format.length()-endColorStartSub+6));
|
||||
String applied = asGradient(start, message, end);
|
||||
replaced = replaced.replace(format, applied);
|
||||
}
|
||||
return replaced;
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
package me.neznamy.tab.api.chat.rgb.gradient;
|
||||
|
||||
import me.neznamy.tab.api.chat.EnumChatFormat;
|
||||
import me.neznamy.tab.api.chat.TextColor;
|
||||
|
||||
/**
|
||||
* Abstract class for applying different gradient patterns
|
||||
*/
|
||||
public interface GradientPattern {
|
||||
|
||||
/**
|
||||
* Applies gradients in provided text and returns text using only #RRGGBB
|
||||
*
|
||||
* @param text
|
||||
* text to be reformatted
|
||||
* @return reformatted text
|
||||
*/
|
||||
String applyPattern(String text, boolean ignorePlaceholders);
|
||||
|
||||
/**
|
||||
* Returns gradient text based on start color, text and end color
|
||||
*
|
||||
* @param start
|
||||
* start color
|
||||
* @param text
|
||||
* text to be reformatted
|
||||
* @param end
|
||||
* end color
|
||||
* @return reformatted text
|
||||
*/
|
||||
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());
|
||||
StringBuilder sb = new StringBuilder();
|
||||
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("|").append(start.getLegacyColor().getCharacter());
|
||||
sb.append(magicCodes);
|
||||
sb.append(deColorized);
|
||||
return sb.toString();
|
||||
}
|
||||
for (int i=0; i<length; i++) {
|
||||
int red = (int) (start.getRed() + (float)(end.getRed() - start.getRed())/(length-1)*i);
|
||||
int green = (int) (start.getGreen() + (float)(end.getGreen() - start.getGreen())/(length-1)*i);
|
||||
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("|").append(start.getLegacyColor().getCharacter());
|
||||
sb.append(magicCodes);
|
||||
sb.append(deColorized.charAt(i));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package me.neznamy.tab.api.chat.rgb.gradient;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import me.neznamy.tab.api.chat.EnumChatFormat;
|
||||
import me.neznamy.tab.api.chat.TextColor;
|
||||
|
||||
/**
|
||||
* Gradient applier for <gradient:#RRGGBB:#RRGGBB>Text</gradient>
|
||||
* and <gradient:#RRGGBB|L:#RRGGBB>Text</gradient>
|
||||
*/
|
||||
public class KyoriGradient implements GradientPattern {
|
||||
|
||||
private final Pattern pattern = Pattern.compile("<gradient:#[0-9a-fA-F]{6}:#[0-9a-fA-F]{6}>[^<]*</gradient>");
|
||||
|
||||
private final Pattern patternLegacy = Pattern.compile("<gradient:#[0-9a-fA-F]{6}\\|.:#[0-9a-fA-F]{6}>[^<]*</gradient>");
|
||||
|
||||
@Override
|
||||
public String applyPattern(String text, boolean ignorePlaceholders) {
|
||||
if (!text.contains("<grad")) return text;
|
||||
String replaced = text;
|
||||
Matcher m = patternLegacy.matcher(replaced);
|
||||
while (m.find()) {
|
||||
String format = m.group();
|
||||
EnumChatFormat legacyColor = EnumChatFormat.getByChar(format.charAt(18));
|
||||
if ((ignorePlaceholders && format.contains("%")) || legacyColor == null) continue;
|
||||
TextColor start = new TextColor(format.substring(11, 17), legacyColor);
|
||||
String message = format.substring(28, format.length()-11);
|
||||
TextColor end = new TextColor(format.substring(21, 27));
|
||||
String applied = asGradient(start, message, end);
|
||||
replaced = replaced.replace(format, applied);
|
||||
}
|
||||
m = pattern.matcher(replaced);
|
||||
while (m.find()) {
|
||||
String format = m.group();
|
||||
if (ignorePlaceholders && format.contains("%")) continue;
|
||||
TextColor start = new TextColor(format.substring(11, 17));
|
||||
String message = format.substring(26, format.length()-11);
|
||||
TextColor end = new TextColor(format.substring(19, 25));
|
||||
String applied = asGradient(start, message, end);
|
||||
replaced = replaced.replace(format, applied);
|
||||
}
|
||||
return replaced;
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,19 @@
|
||||
package me.neznamy.tab.api.event;
|
||||
|
||||
import lombok.NonNull;
|
||||
|
||||
/**
|
||||
* The event bus. This is used to register event listeners/handlers for
|
||||
* handling events that may be fired by TAB.
|
||||
*/
|
||||
@SuppressWarnings("unused") // API class
|
||||
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}
|
||||
* <p>All methods in this class that are annotated with {@link Subscribe}
|
||||
* must meet the following criteria:
|
||||
* <ul>
|
||||
* <li>It must be <strong>public</strong>.</li>
|
||||
@@ -24,7 +27,7 @@ public interface EventBus {
|
||||
* @param listener the listener to register
|
||||
* @throws RuntimeException if a method does not meet the criteria
|
||||
*/
|
||||
void register(Object listener);
|
||||
void register(@NonNull Object listener);
|
||||
|
||||
/**
|
||||
* Registers the given handler to this event bus.
|
||||
@@ -33,7 +36,7 @@ public interface EventBus {
|
||||
* @param handler the handler to register
|
||||
* @param <E> the type of the event
|
||||
*/
|
||||
<E extends TabEvent> void register(Class<E> type, EventHandler<E> handler);
|
||||
<E extends TabEvent> void register(@NonNull Class<E> type, @NonNull EventHandler<E> handler);
|
||||
|
||||
/**
|
||||
* Scans the given listener for any method that is annotated with
|
||||
@@ -41,7 +44,7 @@ public interface EventBus {
|
||||
*
|
||||
* @param listener the listener to unregister
|
||||
*/
|
||||
void unregister(Object listener);
|
||||
void unregister(@NonNull Object listener);
|
||||
|
||||
/**
|
||||
* Unregisters the given handler from this event bus.
|
||||
@@ -49,5 +52,5 @@ public interface EventBus {
|
||||
* @param handler the handler to unregister
|
||||
* @param <E> the type of the event
|
||||
*/
|
||||
<E extends TabEvent> void unregister(EventHandler<E> handler);
|
||||
<E extends TabEvent> void unregister(@NonNull EventHandler<E> handler);
|
||||
}
|
||||
@@ -3,7 +3,7 @@ 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
|
||||
* <p>This is a marker interface. All events <strong>must</strong> implement this
|
||||
* interface.
|
||||
*/
|
||||
public interface TabEvent {
|
||||
|
||||
@@ -2,6 +2,7 @@ package me.neznamy.tab.api.event.player;
|
||||
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import me.neznamy.tab.api.event.TabEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Called when the player has been fully loaded by TAB.
|
||||
@@ -13,13 +14,13 @@ public interface PlayerLoadEvent extends TabEvent {
|
||||
*
|
||||
* @return the player that was loaded
|
||||
*/
|
||||
TabPlayer getPlayer();
|
||||
@NotNull TabPlayer getPlayer();
|
||||
|
||||
/**
|
||||
* Returns true if player was loaded because they joined,
|
||||
* false if the player was loaded because tab reload command was executed
|
||||
* Returns {@code true} if player was loaded because they joined,
|
||||
* {@code false} if the player was loaded because tab reload command was executed
|
||||
*
|
||||
* @return true if player joined, false if plugin was reloaded
|
||||
* @return {@code true} if player joined, {@code false} if plugin was reloaded
|
||||
*/
|
||||
boolean isJoin();
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
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,85 @@
|
||||
package me.neznamy.tab.api.integration;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public abstract class VanishIntegration {
|
||||
|
||||
/** List of all registered VanishIntegration handlers */
|
||||
private static final List<VanishIntegration> HANDLERS = new ArrayList<>();
|
||||
|
||||
/** Name of the plugin this integration is associated with */
|
||||
@NotNull
|
||||
private final String plugin;
|
||||
|
||||
/**
|
||||
* Determines if a viewer can see a target player.
|
||||
*
|
||||
* @param viewer
|
||||
* The player attempting to view another player
|
||||
* @param target
|
||||
* The player being viewed
|
||||
* @return {@code true} if the viewer can see the target, {@code false} otherwise
|
||||
*/
|
||||
public abstract boolean canSee(@NotNull TabPlayer viewer, @NotNull TabPlayer target);
|
||||
|
||||
/**
|
||||
* Checks if the specified player is in a vanished state.
|
||||
*
|
||||
* @param player
|
||||
* The player to check
|
||||
* @return {@code true} if the player is vanished, {@code false} otherwise
|
||||
*/
|
||||
public abstract boolean isVanished(@NotNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Registers this integration handler to the global list of handlers.
|
||||
*/
|
||||
public void register() {
|
||||
registerHandler(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters this integration handler from the global list of handlers.
|
||||
*/
|
||||
public void unregister() {
|
||||
unregisterHandler(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a VanishIntegration handler to the global list of handlers.
|
||||
*
|
||||
* @param handler
|
||||
* The handler to register
|
||||
*/
|
||||
public static void registerHandler(@NotNull VanishIntegration handler) {
|
||||
HANDLERS.add(handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a VanishIntegration handler from the global list of handlers.
|
||||
*
|
||||
* @param handler
|
||||
* The handler to unregister
|
||||
*/
|
||||
public static void unregisterHandler(@NotNull VanishIntegration handler) {
|
||||
HANDLERS.remove(handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of all registered VanishIntegration handlers.
|
||||
*
|
||||
* @return A list of registered VanishIntegration handlers
|
||||
*/
|
||||
@NotNull
|
||||
public static List<VanishIntegration> getHandlers() {
|
||||
return HANDLERS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,289 @@
|
||||
package me.neznamy.tab.api.nametag;
|
||||
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.tab.api.TabAPI;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Interface for manipulating player name tags.
|
||||
* <p>
|
||||
* Instance can be obtained using {@link TabAPI#getNameTagManager()}.
|
||||
* This requires the Team feature to be enabled in config, otherwise the method will
|
||||
* return {@code null}.
|
||||
*/
|
||||
@SuppressWarnings("unused") // API class
|
||||
public interface NameTagManager {
|
||||
|
||||
/**
|
||||
* Makes player's NameTag globally invisible
|
||||
*
|
||||
* @param player
|
||||
* player to hide name tag of
|
||||
* @see #showNameTag(TabPlayer)
|
||||
* @see #hasHiddenNameTag(TabPlayer)
|
||||
*/
|
||||
void hideNameTag(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Hides player's NameTag for specified player until it's shown again
|
||||
*
|
||||
* @param player
|
||||
* player to hide name tag of
|
||||
* @param viewer
|
||||
* player to hide name tag for
|
||||
*/
|
||||
void hideNameTag(@NonNull TabPlayer player, @NonNull TabPlayer viewer);
|
||||
|
||||
/**
|
||||
* Makes player's NameTag visible again
|
||||
*
|
||||
* @param player
|
||||
* player to show name tag of
|
||||
* @see #hideNameTag(TabPlayer)
|
||||
* @see #hasHiddenNameTag(TabPlayer)
|
||||
*/
|
||||
void showNameTag(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Shows player's NameTag for specified viewer if it was hidden before
|
||||
*
|
||||
* @param player
|
||||
* player to show name tag of
|
||||
* @param viewer
|
||||
* player to show NameTag back for
|
||||
*/
|
||||
void showNameTag(@NonNull TabPlayer player, @NonNull TabPlayer viewer);
|
||||
|
||||
/**
|
||||
* Return whether player has hidden NameTag or not
|
||||
*
|
||||
* @param player
|
||||
* player to check name tag visibility status of
|
||||
* @return Whether player has hidden NameTag or not
|
||||
* @see #hideNameTag(TabPlayer)
|
||||
* @see #showNameTag(TabPlayer)
|
||||
*/
|
||||
boolean hasHiddenNameTag(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns true if NameTag is hidden for specified viewer, false if not
|
||||
*
|
||||
* @param player
|
||||
* player to check visibility status of
|
||||
* @param viewer
|
||||
* player to check visibility status for
|
||||
* @return true if hidden, false if not
|
||||
*/
|
||||
boolean hasHiddenNameTag(@NonNull TabPlayer player, @NonNull TabPlayer viewer);
|
||||
|
||||
/**
|
||||
* Unregisters player's team and no longer handles it, as well as disables anti-override for teams.
|
||||
* This can be resumed using resumeTeamHandling(). If team handling was paused already, nothing happens.
|
||||
*
|
||||
* @param player
|
||||
* player to pause team handling of
|
||||
*/
|
||||
void pauseTeamHandling(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Resumes team handling if it was before paused using pauseTeamHandling(), if not, nothing happens
|
||||
*
|
||||
* @param player
|
||||
* player to resume team handling of
|
||||
*/
|
||||
void resumeTeamHandling(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns true if team handling is paused for this player using pauseTeamHandling(), false if not, or
|
||||
* it was resumed already using resumeTeamHandling
|
||||
*
|
||||
* @param player
|
||||
* player to check handling status of
|
||||
* @return true if paused, false if not
|
||||
*/
|
||||
boolean hasTeamHandlingPaused(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Forces collision rule for the player. Setting it to null will remove forced value
|
||||
*
|
||||
* @param player
|
||||
* player to set collision rule of
|
||||
* @param collision
|
||||
* forced collision rule
|
||||
*/
|
||||
void setCollisionRule(@NonNull TabPlayer player, @Nullable Boolean collision);
|
||||
|
||||
/**
|
||||
* Returns forced collision rule or null if collision is not forced using setCollisionRule
|
||||
*
|
||||
* @param player
|
||||
* player to get forced collision of
|
||||
* @return forced value or null if not forced
|
||||
*/
|
||||
@Nullable Boolean getCollisionRule(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Changes player's prefix to provided value. Supports placeholders,
|
||||
* as well as any supported RGB formats. Use {@code null} to reset
|
||||
* value back to original.
|
||||
*
|
||||
* @param player
|
||||
* player to change prefix of
|
||||
* @param prefix
|
||||
* new prefix value
|
||||
* @see #getCustomPrefix(TabPlayer)
|
||||
* @see #getOriginalRawPrefix(TabPlayer)
|
||||
*/
|
||||
void setPrefix(@NonNull TabPlayer player, @Nullable String prefix);
|
||||
|
||||
/**
|
||||
* Changes player's suffix to provided value. Supports placeholders,
|
||||
* as well as any supported RGB formats. Use {@code null} to reset
|
||||
* value back to original.
|
||||
*
|
||||
* @param player
|
||||
* player to change prefix of
|
||||
* @param suffix
|
||||
* new suffix value
|
||||
* @see #getCustomSuffix(TabPlayer)
|
||||
* @see #getOriginalRawSuffix(TabPlayer)
|
||||
*/
|
||||
void setSuffix(@NonNull TabPlayer player, @Nullable String suffix);
|
||||
|
||||
/**
|
||||
* Returns custom prefix assigned using {@link #setPrefix(TabPlayer, String)}.
|
||||
* If no custom prefix is set, returns {@code null}.
|
||||
*
|
||||
* @param player
|
||||
* Player to get custom prefix of
|
||||
* @return Custom prefix assigned using the API.
|
||||
* @see #setPrefix(TabPlayer, String)
|
||||
* @see #getOriginalRawPrefix(TabPlayer)
|
||||
*/
|
||||
@Nullable
|
||||
String getCustomPrefix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns custom suffix assigned using {@link #setSuffix(TabPlayer, String)}.
|
||||
* If no custom suffix is set, returns {@code null}.
|
||||
*
|
||||
* @param player
|
||||
* Player to get custom suffix of
|
||||
* @return Custom suffix assigned using the API.
|
||||
* @see #setSuffix(TabPlayer, String)
|
||||
* @see #getOriginalRawSuffix(TabPlayer)
|
||||
*/
|
||||
@Nullable
|
||||
String getCustomSuffix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns original prefix assigned by the plugin using internal logic.
|
||||
* @param player
|
||||
* Player to get original prefix of
|
||||
* @return Original prefix assigned by the plugin's internal logic.
|
||||
* @see #getCustomPrefix(TabPlayer)
|
||||
*/
|
||||
@NotNull
|
||||
String getOriginalRawPrefix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns original suffix assigned by the plugin using internal logic.
|
||||
* @param player
|
||||
* Player to get original suffix of
|
||||
* @return Original suffix assigned by the plugin's internal logic.
|
||||
* @see #getCustomSuffix(TabPlayer)
|
||||
*/
|
||||
@NotNull
|
||||
String getOriginalRawSuffix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns original prefix assigned by the plugin using internal logic with all placeholders replaced.
|
||||
* @param player
|
||||
* Player to get replaced original prefix of
|
||||
* @return Original prefix assigned by the plugin's internal logic.
|
||||
* @see #getCustomPrefix(TabPlayer)
|
||||
*/
|
||||
@NotNull
|
||||
String getOriginalReplacedPrefix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns original suffix assigned by the plugin using internal logic with all placeholders replaced.
|
||||
* @param player
|
||||
* Player to get replaced original suffix of
|
||||
* @return Original suffix assigned by the plugin's internal logic.
|
||||
* @see #getCustomSuffix(TabPlayer)
|
||||
*/
|
||||
@NotNull
|
||||
String getOriginalReplacedSuffix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns original suffix assigned by the plugin using internal logic.
|
||||
* @param player
|
||||
* Player to get replaced original prefix of
|
||||
* @return Original prefix assigned by the plugin's internal logic.
|
||||
* @see #getCustomPrefix(TabPlayer)
|
||||
* @deprecated Use {@link #getOriginalRawPrefix(TabPlayer)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@NotNull
|
||||
String getOriginalPrefix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns original suffix assigned by the plugin using internal logic.
|
||||
* @param player
|
||||
* Player to get replaced original suffix of
|
||||
* @return Original suffix assigned by the plugin's internal logic.
|
||||
* @see #getCustomSuffix(TabPlayer)
|
||||
* @deprecated Use {@link #getOriginalRawSuffix(TabPlayer)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@NotNull
|
||||
String getOriginalSuffix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Toggles name tag visibility view on all players for specified player.
|
||||
* On first call, name tags of all players will become invisible for specified
|
||||
* player. On the second call, they will become visible again.
|
||||
*
|
||||
* @param player
|
||||
* player to toggle name tag visibility view for
|
||||
* @param sendToggleMessage
|
||||
* {@code true} if the configured toggle message should be sent, {@code false} if not
|
||||
*/
|
||||
void toggleNameTagVisibilityView(@NonNull TabPlayer player, boolean sendToggleMessage);
|
||||
|
||||
/**
|
||||
* Shows back name tag visibility view on all players for specified player.
|
||||
* If the view is not hidden, nothing happens.
|
||||
*
|
||||
* @param player
|
||||
* player to show name tag visibility view for
|
||||
* @param sendToggleMessage
|
||||
* {@code true} if the configured toggle message should be sent, {@code false} if not
|
||||
*/
|
||||
void showNameTagVisibilityView(@NonNull TabPlayer player, boolean sendToggleMessage);
|
||||
|
||||
/**
|
||||
* Hides name tag visibility view on all players for specified player.
|
||||
* If the view is already hidden, nothing happens.
|
||||
*
|
||||
* @param player
|
||||
* player to show name tag visibility view for
|
||||
* @param sendToggleMessage
|
||||
* {@code true} if the configured toggle message should be sent, {@code false} if not
|
||||
*/
|
||||
void hideNameTagVisibilityView(@NonNull TabPlayer player, boolean sendToggleMessage);
|
||||
|
||||
/**
|
||||
* Returns {@code true} if player has hidden name tags by either calling
|
||||
* {@link #toggleNameTagVisibilityView(TabPlayer, boolean)} or using a command,
|
||||
* {@code false} if not.
|
||||
*
|
||||
* @param player
|
||||
* player to check
|
||||
* @return {@code true} if hidden, {@code false} if not
|
||||
*/
|
||||
boolean hasHiddenNameTagVisibilityView(@NonNull TabPlayer player);
|
||||
}
|
||||
@@ -1,14 +1,23 @@
|
||||
package me.neznamy.tab.api.placeholder;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* An interface representing some kind of placeholder
|
||||
*/
|
||||
public interface Placeholder {
|
||||
|
||||
/**
|
||||
* Returns refresh interval of this placeholder
|
||||
*
|
||||
* @return refresh interval of this placeholder
|
||||
*/
|
||||
int getRefresh();
|
||||
|
||||
String getIdentifier();
|
||||
|
||||
void enableTriggerMode(Runnable onActivation, Runnable onDisable);
|
||||
|
||||
void unload();
|
||||
|
||||
boolean isUsed();
|
||||
/**
|
||||
* Returns placeholder's identifier
|
||||
*
|
||||
* @return placeholder's identifier
|
||||
*/
|
||||
@NotNull String getIdentifier();
|
||||
}
|
||||
@@ -1,53 +1,103 @@
|
||||
package me.neznamy.tab.api.placeholder;
|
||||
|
||||
import java.util.List;
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.tab.api.TabAPI;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import me.neznamy.tab.api.TabFeature;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
|
||||
/**
|
||||
* An interface allowing placeholder registration. Instance can be
|
||||
* obtained using {@link TabAPI#getPlaceholderManager()}
|
||||
*/
|
||||
@SuppressWarnings("unused") // API class
|
||||
public interface PlaceholderManager {
|
||||
|
||||
/**
|
||||
* Registers a server placeholder (placeholder with same output for all players)
|
||||
*/
|
||||
ServerPlaceholder registerServerPlaceholder(String identifier, int refresh, Supplier<Object> supplier);
|
||||
|
||||
/**
|
||||
* Registers a player placeholder (placeholder with player-specific output)
|
||||
*/
|
||||
PlayerPlaceholder registerPlayerPlaceholder(String identifier, int refresh, Function<TabPlayer, Object> function);
|
||||
|
||||
/**
|
||||
* Registers a relational placeholder (different output for each player pair)
|
||||
*/
|
||||
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
|
||||
*/
|
||||
List<String> detectPlaceholders(String text);
|
||||
|
||||
/**
|
||||
* Adds placeholder to list of used placeholders and assigns this feature as using it,
|
||||
* which will then receive refresh() if values changes
|
||||
*
|
||||
* @param identifier
|
||||
* placeholder identifier
|
||||
* @param feature
|
||||
* feature using the placeholder
|
||||
* Placeholder identifier
|
||||
* @param refresh
|
||||
* Refresh interval
|
||||
* @param supplier
|
||||
* Supplier for placeholder output
|
||||
* @return Registered placeholder for further use
|
||||
* @throws IllegalArgumentException
|
||||
* If {@code identifier} does not start and end with {@code %} or
|
||||
* {@code refresh} is not divisible by 50
|
||||
*/
|
||||
void addUsedPlaceholder(String identifier, TabFeature feature);
|
||||
@NotNull ServerPlaceholder registerServerPlaceholder(@NonNull String identifier, int refresh, @NonNull Supplier<String> supplier);
|
||||
|
||||
String findReplacement(String placeholder, String output);
|
||||
/**
|
||||
* Registers a player placeholder (placeholder different output per player)
|
||||
*
|
||||
* @param identifier
|
||||
* Placeholder identifier
|
||||
* @param refresh
|
||||
* Refresh interval
|
||||
* @param function
|
||||
* Function for placeholder output
|
||||
* @return Registered placeholder for further use
|
||||
* @throws IllegalArgumentException
|
||||
* If {@code identifier} does not start and end with {@code %} or
|
||||
* {@code refresh} is not divisible by 50
|
||||
*/
|
||||
@NotNull PlayerPlaceholder registerPlayerPlaceholder(@NonNull String identifier, int refresh, @NonNull Function<TabPlayer, String> function);
|
||||
|
||||
List<String> getUsedPlaceholders();
|
||||
/**
|
||||
* Registers a relational placeholder (placeholder with output different for each player duo)
|
||||
*
|
||||
* @param identifier
|
||||
* Placeholder identifier
|
||||
* @param refresh
|
||||
* Refresh interval
|
||||
* @param function
|
||||
* Function for placeholder output
|
||||
* @return Registered placeholder for further use
|
||||
* @throws IllegalArgumentException
|
||||
* If {@code identifier} does not start and end with {@code %},
|
||||
* does not start with {@code %rel_} or
|
||||
* {@code refresh} is not divisible by 50
|
||||
*/
|
||||
@NotNull RelationalPlaceholder registerRelationalPlaceholder(@NonNull String identifier, int refresh, @NonNull BiFunction<TabPlayer, TabPlayer, String> function);
|
||||
|
||||
Placeholder getPlaceholder(String identifier);
|
||||
void registerServerPlaceholder(@NonNull Pattern identifier, int refresh, @NonNull Function<Matcher, Supplier<String>> function);
|
||||
|
||||
void registerPlayerPlaceholder(@NonNull Pattern identifier, int refresh,
|
||||
@NonNull Function<Matcher, Function<me.neznamy.tab.api.TabPlayer, String>> function);
|
||||
|
||||
void registerRelationalPlaceholder(@NonNull Pattern identifier, int refresh,
|
||||
@NonNull Function<Matcher, BiFunction<me.neznamy.tab.api.TabPlayer, me.neznamy.tab.api.TabPlayer, String>> function);
|
||||
|
||||
/**
|
||||
* Returns placeholder from specified identifier. If it does not exist, it is registered
|
||||
* as a PlaceholderAPI placeholder and returned.
|
||||
*
|
||||
* @param identifier
|
||||
* Placeholder identifier
|
||||
* @return Placeholder with specified identifier
|
||||
*/
|
||||
@NotNull Placeholder getPlaceholder(@NonNull String identifier);
|
||||
|
||||
/**
|
||||
* Unregisters placeholder and makes plugin no longer refresh it.
|
||||
*
|
||||
* @param placeholder
|
||||
* Placeholder to unregister
|
||||
*/
|
||||
void unregisterPlaceholder(@NonNull Placeholder placeholder);
|
||||
|
||||
/**
|
||||
* Unregisters placeholder and makes plugin no longer refresh it.
|
||||
*
|
||||
* @param identifier
|
||||
* identifier of placeholder to unregister
|
||||
*/
|
||||
void unregisterPlaceholder(@NonNull String identifier);
|
||||
}
|
||||
@@ -1,28 +1,31 @@
|
||||
package me.neznamy.tab.api.placeholder;
|
||||
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Interface for player placeholders (placeholders returning different value for each player)
|
||||
*/
|
||||
public interface PlayerPlaceholder extends Placeholder {
|
||||
|
||||
void updateValue(TabPlayer player, Object value);
|
||||
|
||||
/**
|
||||
* Calls the placeholder request function and returns the output.
|
||||
* If the placeholder threw an exception, it is logged in {@code placeholder-errors.log}
|
||||
* file and "ERROR" is returned.
|
||||
*
|
||||
* @param p
|
||||
* player to get placeholder value for
|
||||
* @return value placeholder returned or "ERROR" if it threw an error
|
||||
*/
|
||||
Object request(TabPlayer p);
|
||||
|
||||
/**
|
||||
* Returns last known value for given player.
|
||||
* Force-updates placeholder value. It will still be overridden by periodic refresh later,
|
||||
* so this is (only) useful for force an update when value is supposed to change, and you have
|
||||
* a high refresh interval set.
|
||||
*
|
||||
* @param player
|
||||
* player to get last value for
|
||||
* @return last known value for entered player
|
||||
* Player to update value for
|
||||
* @param value
|
||||
* New value
|
||||
*/
|
||||
String getLastValue(TabPlayer player);
|
||||
void updateValue(@NonNull TabPlayer player, @Nullable String value);
|
||||
|
||||
/**
|
||||
* Force-updates placeholder value using previously provided update function.
|
||||
*
|
||||
* @param player
|
||||
* Player to update value for
|
||||
*/
|
||||
void update(@NonNull TabPlayer player);
|
||||
}
|
||||
@@ -1,33 +1,36 @@
|
||||
package me.neznamy.tab.api.placeholder;
|
||||
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* An interface for relational placeholders (returning different value for each player duo)
|
||||
*/
|
||||
@SuppressWarnings("unused") // API class
|
||||
public interface RelationalPlaceholder extends Placeholder {
|
||||
|
||||
void updateValue(TabPlayer viewer, TabPlayer target, Object value);
|
||||
|
||||
/**
|
||||
* Calls the placeholder request function and returns the output.
|
||||
* If the placeholder threw an exception, it is logged in {@code placeholder-errors.log}
|
||||
* file and "ERROR" is returned.
|
||||
* Force-updates placeholder value. It will still be overridden by periodic refresh later,
|
||||
* so this is (only) useful for force an update when value is supposed to change, and you have
|
||||
* a high refresh interval set.
|
||||
*
|
||||
* @param viewer
|
||||
* player looking at output of the placeholder
|
||||
* Placeholder viewer
|
||||
* @param target
|
||||
* player the placeholder is displayed on
|
||||
* @return value placeholder returned or "ERROR" if it threw an error
|
||||
* Placeholder target
|
||||
* @param value
|
||||
* New value
|
||||
*/
|
||||
Object request(TabPlayer viewer, TabPlayer target);
|
||||
void updateValue(@NonNull TabPlayer viewer, @NonNull TabPlayer target, @Nullable String value);
|
||||
|
||||
/**
|
||||
* Returns last known value for given players. First player is viewer,
|
||||
* second player is target.
|
||||
* Force-updates placeholder value using previously provided update function.
|
||||
*
|
||||
* @param viewer
|
||||
* viewer of the placeholder
|
||||
* Placeholder viewer
|
||||
* @param target
|
||||
* target who is the text displayed on
|
||||
* @return last known value for entered player duo
|
||||
* Placeholder target
|
||||
*/
|
||||
String getLastValue(TabPlayer viewer, TabPlayer target);
|
||||
void update(@NonNull TabPlayer viewer, @NonNull TabPlayer target);
|
||||
}
|
||||
@@ -1,22 +1,24 @@
|
||||
package me.neznamy.tab.api.placeholder;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* An interface for server placeholders (returning same value for all players)
|
||||
*/
|
||||
public interface ServerPlaceholder extends Placeholder {
|
||||
|
||||
void updateValue(Object value);
|
||||
/**
|
||||
* Force-updates placeholder value. It will still be overridden by periodic refresh later,
|
||||
* so this is (only) useful for force an update when value is supposed to change, and you have
|
||||
* a high refresh interval set.
|
||||
*
|
||||
* @param value
|
||||
* New value
|
||||
*/
|
||||
void updateValue(@Nullable String value);
|
||||
|
||||
/**
|
||||
* Calls the placeholder request function and returns the output.
|
||||
* If the placeholder threw an exception, it is logged in {@code placeholder-errors.log}
|
||||
* file and "ERROR" is returned.
|
||||
*
|
||||
* @return value placeholder returned or "ERROR" if it threw an error
|
||||
* Force-updates placeholder value using previously provided update function.
|
||||
*/
|
||||
Object request();
|
||||
|
||||
/**
|
||||
* Returns last known value of the placeholder.
|
||||
*
|
||||
* @return last known value
|
||||
*/
|
||||
String getLastValue();
|
||||
void update();
|
||||
}
|
||||
@@ -1,269 +0,0 @@
|
||||
package me.neznamy.tab.api.protocol;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import me.neznamy.tab.api.ProtocolVersion;
|
||||
import me.neznamy.tab.api.chat.EnumChatFormat;
|
||||
import me.neznamy.tab.api.chat.IChatBaseComponent;
|
||||
import me.neznamy.tab.api.chat.rgb.RGBUtils;
|
||||
import me.neznamy.tab.api.util.BiFunctionWithException;
|
||||
import me.neznamy.tab.api.util.Preconditions;
|
||||
|
||||
/**
|
||||
* A class for packet building, methods are overridden in
|
||||
* platform-specific builders which extend this class to build actual packets.
|
||||
* Packets which don't have a method override are forwarded into
|
||||
* sendPacket method, where they are handled using platform's API instead.
|
||||
*/
|
||||
public class PacketBuilder {
|
||||
|
||||
/** Function map turning custom packet class into platform-specific packets */
|
||||
protected final Map<Class<? extends TabPacket>, BiFunctionWithException<TabPacket, ProtocolVersion, Object>> buildMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Constructs new instance and fills {@link #buildMap} with abstract build methods
|
||||
* of packets present on all platforms.
|
||||
*/
|
||||
public PacketBuilder() {
|
||||
buildMap.put(PacketPlayOutBoss.class, (packet, version) -> build((PacketPlayOutBoss)packet, version));
|
||||
buildMap.put(PacketPlayOutChat.class, (packet, version) -> build((PacketPlayOutChat)packet, version));
|
||||
buildMap.put(PacketPlayOutPlayerInfo.class, (packet, version) -> build((PacketPlayOutPlayerInfo)packet, version));
|
||||
buildMap.put(PacketPlayOutPlayerListHeaderFooter.class, (packet, version) -> build((PacketPlayOutPlayerListHeaderFooter)packet, version));
|
||||
buildMap.put(PacketPlayOutScoreboardDisplayObjective.class, (packet, version) -> build((PacketPlayOutScoreboardDisplayObjective)packet, version));
|
||||
buildMap.put(PacketPlayOutScoreboardObjective.class, (packet, version) -> build((PacketPlayOutScoreboardObjective)packet, version));
|
||||
buildMap.put(PacketPlayOutScoreboardScore.class, (packet, version) -> build((PacketPlayOutScoreboardScore)packet, version));
|
||||
buildMap.put(PacketPlayOutScoreboardTeam.class, (packet, version) -> build((PacketPlayOutScoreboardTeam)packet, version));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts custom packet into platform-specific packet by calling a function from
|
||||
* {@link #buildMap}.
|
||||
*
|
||||
* @param packet
|
||||
* Packet to build
|
||||
* @param clientVersion
|
||||
* Protocol version of player to build the packet for
|
||||
* @return Platform-specific packet
|
||||
* @throws ReflectiveOperationException
|
||||
* if reflection fails
|
||||
*/
|
||||
public Object build(TabPacket packet, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
Preconditions.checkNotNull(packet, "packet");
|
||||
Preconditions.checkNotNull(clientVersion, "clientVersion");
|
||||
return buildMap.get(packet.getClass()).apply(packet, clientVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs platform-specific PacketPlayOutBoss class based on custom packet class
|
||||
*
|
||||
* @param packet
|
||||
* Custom packet to be built
|
||||
* @param clientVersion
|
||||
* Protocol version of player to build the packet for
|
||||
* @return Platform-specific packet
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public Object build(PacketPlayOutBoss packet, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
return packet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs platform-specific PacketPlayOutChat class based on custom packet class
|
||||
*
|
||||
* @param packet
|
||||
* Custom packet to be built
|
||||
* @param clientVersion
|
||||
* Protocol version of player to build the packet for
|
||||
* @return Platform-specific packet
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public Object build(PacketPlayOutChat packet, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
return packet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs platform-specific PacketPlayOutPlayerInfo class based on custom packet class
|
||||
*
|
||||
* @param packet
|
||||
* Custom packet to be built
|
||||
* @param clientVersion
|
||||
* Protocol version of player to build the packet for
|
||||
* @return Platform-specific packet
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public Object build(PacketPlayOutPlayerInfo packet, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
return packet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs platform-specific PacketPlayOutPlayerListHeaderFooter class based on custom packet class
|
||||
*
|
||||
* @param packet
|
||||
* Custom packet to be built
|
||||
* @param clientVersion
|
||||
* Protocol version of player to build the packet for
|
||||
* @return Platform-specific packet
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public Object build(PacketPlayOutPlayerListHeaderFooter packet, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
return packet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs platform-specific PacketPlayOutScoreboardDisplayObjective class based on custom packet class
|
||||
*
|
||||
* @param packet
|
||||
* Custom packet to be built
|
||||
* @param clientVersion
|
||||
* Protocol version of player to build the packet for
|
||||
* @return Platform-specific packet
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public Object build(PacketPlayOutScoreboardDisplayObjective packet, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
return packet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs platform-specific PacketPlayOutScoreboardObjective class based on custom packet class
|
||||
*
|
||||
* @param packet
|
||||
* Custom packet to be built
|
||||
* @param clientVersion
|
||||
* Protocol version of player to build the packet for
|
||||
* @return Platform-specific packet
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public Object build(PacketPlayOutScoreboardObjective packet, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
return packet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs platform-specific PacketPlayOutScoreboardScore class based on custom packet class
|
||||
*
|
||||
* @param packet
|
||||
* Custom packet to be built
|
||||
* @param clientVersion
|
||||
* Protocol version of player to build the packet for
|
||||
* @return Platform-specific packet
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public Object build(PacketPlayOutScoreboardScore packet, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
return packet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs platform-specific PacketPlayOutScoreboardTeam class based on custom packet class
|
||||
*
|
||||
* @param packet
|
||||
* Custom packet to be built
|
||||
* @param clientVersion
|
||||
* Protocol version of player to build the packet for
|
||||
* @return Platform-specific packet
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public Object build(PacketPlayOutScoreboardTeam packet, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
return packet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cuts given string to specified character length (or length-1 if last character is a color character)
|
||||
* and translates RGB to legacy colors. If string is not that long, the original string is returned.
|
||||
* RGB codes are converted into legacy, since cutting is only needed for <1.13.
|
||||
* If {@code string} is {@code null}, empty string is returned.
|
||||
*
|
||||
* @param string
|
||||
* String to cut
|
||||
* @param length
|
||||
* Length to cut to
|
||||
* @return string cut to {@code length} characters
|
||||
*/
|
||||
public String cutTo(String string, int length) {
|
||||
if (string == null) return "";
|
||||
String legacyText = string;
|
||||
if (string.contains("#")) {
|
||||
//converting RGB to legacy colors
|
||||
legacyText = RGBUtils.getInstance().convertRGBtoLegacy(string);
|
||||
}
|
||||
if (legacyText.length() <= length) return legacyText;
|
||||
if (legacyText.charAt(length-1) == EnumChatFormat.COLOR_CHAR) {
|
||||
return legacyText.substring(0, length-1); //cutting one extra character to prevent prefix ending with "&"
|
||||
} else {
|
||||
return legacyText.substring(0, length);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If {@code clientVersion} is >= 1.13, creates a component from given text and returns
|
||||
* 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.
|
||||
*
|
||||
* @param text
|
||||
* Text to convert
|
||||
* @param clientVersion
|
||||
* Version of player to convert text for
|
||||
* @return serialized component for 1.13+ clients, cut string for 1.12-
|
||||
*/
|
||||
public String jsonOrCut(String text, ProtocolVersion clientVersion, int length) {
|
||||
if (text == null) return null;
|
||||
if (clientVersion.getMinorVersion() >= 13) {
|
||||
return IChatBaseComponent.optimizedComponent(text).toString(clientVersion);
|
||||
} else {
|
||||
return cutTo(text, length);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts platform-specific instance of player info packet into
|
||||
* {@link PacketPlayOutPlayerInfo} object.
|
||||
*
|
||||
* @param packet
|
||||
* platform-specific info packet
|
||||
* @param clientVersion
|
||||
* Version of client receiving the packet
|
||||
* @return The packet converted into {@link PacketPlayOutPlayerInfo}
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public PacketPlayOutPlayerInfo readPlayerInfo(Object packet, ProtocolVersion clientVersion) throws ReflectiveOperationException {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts platform-specific instance of objective packet into
|
||||
* {@link PacketPlayOutScoreboardObjective} object.
|
||||
*
|
||||
* @param packet
|
||||
* platform-specific objective packet
|
||||
* @return The packet converted into {@link PacketPlayOutScoreboardObjective}
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public PacketPlayOutScoreboardObjective readObjective(Object packet) throws ReflectiveOperationException {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts platform-specific instance of display objective packet into
|
||||
* {@link PacketPlayOutScoreboardDisplayObjective} object.
|
||||
*
|
||||
* @param packet
|
||||
* platform-specific display objective packet
|
||||
* @return The packet converted into {@link PacketPlayOutScoreboardDisplayObjective}
|
||||
* @throws ReflectiveOperationException
|
||||
* if thrown by reflective operation
|
||||
*/
|
||||
public PacketPlayOutScoreboardDisplayObjective readDisplayObjective(Object packet) throws ReflectiveOperationException {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,302 +0,0 @@
|
||||
package me.neznamy.tab.api.protocol;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import me.neznamy.tab.api.bossbar.BarColor;
|
||||
import me.neznamy.tab.api.bossbar.BarStyle;
|
||||
import me.neznamy.tab.api.util.Preconditions;
|
||||
|
||||
/**
|
||||
* A class representing platform specific packet class
|
||||
*/
|
||||
public class PacketPlayOutBoss implements TabPacket {
|
||||
|
||||
/** UUID of the BossBar */
|
||||
private final UUID id;
|
||||
|
||||
/** Action of this packet */
|
||||
private final Action action;
|
||||
|
||||
/** BossBar title */
|
||||
private String name;
|
||||
|
||||
/** BossBar progress (0-1)*/
|
||||
private float pct;
|
||||
|
||||
/** BossBar color */
|
||||
private BarColor color;
|
||||
|
||||
/** BossBar style */
|
||||
private BarStyle overlay;
|
||||
|
||||
/** Darken screen flag */
|
||||
private boolean darkenScreen;
|
||||
|
||||
/** Play music flag */
|
||||
private boolean playMusic;
|
||||
|
||||
/** Create fog flag */
|
||||
private boolean createWorldFog;
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters and
|
||||
* {@link me.neznamy.tab.api.protocol.PacketPlayOutBoss.Action}.ADD action
|
||||
*
|
||||
* @param id
|
||||
* BossBar uuid
|
||||
* @param name
|
||||
* BossBar title
|
||||
* @param pct
|
||||
* BossBar progress
|
||||
* @param color
|
||||
* BossBar color
|
||||
* @param overlay
|
||||
* BossBar style
|
||||
*/
|
||||
public PacketPlayOutBoss(UUID id, String name, float pct, BarColor color, BarStyle overlay) {
|
||||
Preconditions.checkNotNull(id, "uuid");
|
||||
Preconditions.checkNotNull(name, "title");
|
||||
Preconditions.checkNotNull(color, "color");
|
||||
Preconditions.checkNotNull(overlay, "style");
|
||||
this.action = Action.ADD;
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.pct = pct;
|
||||
this.color = color;
|
||||
this.overlay = overlay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters and
|
||||
* {@link me.neznamy.tab.api.protocol.PacketPlayOutBoss.Action}.REMOVE action
|
||||
*
|
||||
* @param id
|
||||
* BossBar uuid
|
||||
*/
|
||||
public PacketPlayOutBoss(UUID id) {
|
||||
Preconditions.checkNotNull(id, "uuid");
|
||||
this.action = Action.REMOVE;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters and
|
||||
* {@link me.neznamy.tab.api.protocol.PacketPlayOutBoss.Action}.UPDATE_PCT action
|
||||
*
|
||||
* @param id
|
||||
* BossBar uuid
|
||||
* @param pct
|
||||
* BossBar progress
|
||||
*/
|
||||
public PacketPlayOutBoss(UUID id, float pct) {
|
||||
Preconditions.checkNotNull(id, "uuid");
|
||||
this.action = Action.UPDATE_PCT;
|
||||
this.id = id;
|
||||
this.pct = pct;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters and
|
||||
* {@link me.neznamy.tab.api.protocol.PacketPlayOutBoss.Action}.UPDATE_NAME action
|
||||
*
|
||||
* @param id
|
||||
* BossBar uuid
|
||||
* @param name
|
||||
* BossBar title
|
||||
*/
|
||||
public PacketPlayOutBoss(UUID id, String name) {
|
||||
Preconditions.checkNotNull(id, "uuid");
|
||||
Preconditions.checkNotNull(name, "title");
|
||||
this.action = Action.UPDATE_NAME;
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters and
|
||||
* {@link me.neznamy.tab.api.protocol.PacketPlayOutBoss.Action}.UPDATE_STYLE action
|
||||
*
|
||||
* @param id
|
||||
* BossBar uuid
|
||||
* @param color
|
||||
* BossBar color
|
||||
* @param overlay
|
||||
* BossBar style
|
||||
*/
|
||||
public PacketPlayOutBoss(UUID id, BarColor color, BarStyle overlay) {
|
||||
Preconditions.checkNotNull(id, "uuid");
|
||||
Preconditions.checkNotNull(color, "color");
|
||||
Preconditions.checkNotNull(overlay, "style");
|
||||
this.action = Action.UPDATE_STYLE;
|
||||
this.id = id;
|
||||
this.color = color;
|
||||
this.overlay = overlay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters and
|
||||
* {@link me.neznamy.tab.api.protocol.PacketPlayOutBoss.Action}.UPDATE_PROPERTIES action
|
||||
*
|
||||
* @param darkenScreen
|
||||
* Darken screen flag
|
||||
* @param playMusic
|
||||
* Play music flag
|
||||
* @param createWorldFog
|
||||
* Create fog flag
|
||||
*/
|
||||
public PacketPlayOutBoss(UUID id, boolean darkenScreen, boolean playMusic, boolean createWorldFog) {
|
||||
Preconditions.checkNotNull(id, "uuid");
|
||||
this.action = Action.UPDATE_PROPERTIES;
|
||||
this.id = id;
|
||||
this.darkenScreen = darkenScreen;
|
||||
this.playMusic = playMusic;
|
||||
this.createWorldFog = createWorldFog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns bitmask based on {@link #darkenScreen}, {@link #playMusic} and {@link #darkenScreen} values.
|
||||
* <p>
|
||||
* {@link #darkenScreen} adds {@code 1}, {@link #playMusic} {@code 2} and {@link #darkenScreen} {@code 4}
|
||||
* to the final value.
|
||||
*
|
||||
* @return the bitmask
|
||||
*/
|
||||
public byte getFlags(){
|
||||
byte value = 0;
|
||||
if (darkenScreen) value += 1;
|
||||
if (playMusic) value += 2;
|
||||
if (createWorldFog) value += 4;
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("PacketPlayOutBoss{id=%s,operation=%s,name=%s,pct=%s,color=%s,overlay=%s,darkenScreen=%s,playMusic=%s,createWorldFog=%s}",
|
||||
id, action, name, pct, color, overlay, darkenScreen, playMusic, createWorldFog);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #color}
|
||||
*
|
||||
* @return color
|
||||
*/
|
||||
public BarColor getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #overlay}
|
||||
*
|
||||
* @return style
|
||||
*/
|
||||
public BarStyle getOverlay() {
|
||||
return overlay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #name}
|
||||
*
|
||||
* @return name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #id}
|
||||
*
|
||||
* @return id
|
||||
*/
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #pct}
|
||||
*
|
||||
* @return progress
|
||||
*/
|
||||
public float getPct() {
|
||||
return pct;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #action}
|
||||
*
|
||||
* @return packet action
|
||||
*/
|
||||
public Action getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #darkenScreen}
|
||||
*
|
||||
* @return darkenScreen
|
||||
*/
|
||||
public boolean isDarkenScreen() {
|
||||
return darkenScreen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #createWorldFog}
|
||||
*
|
||||
* @return createWorldFog
|
||||
*/
|
||||
public boolean isCreateWorldFog() {
|
||||
return createWorldFog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #playMusic}
|
||||
*
|
||||
* @return playMusic
|
||||
*/
|
||||
public boolean isPlayMusic() {
|
||||
return playMusic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets {@link #darkenScreen} to specified value
|
||||
*
|
||||
* @param darkenScreen
|
||||
* Darken screen flag
|
||||
*/
|
||||
public void setDarkenScreen(boolean darkenScreen) {
|
||||
this.darkenScreen = darkenScreen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets {@link #createWorldFog} to specified value
|
||||
*
|
||||
* @param createWorldFog
|
||||
* Create fog flag
|
||||
*/
|
||||
public void setCreateWorldFog(boolean createWorldFog) {
|
||||
this.createWorldFog = createWorldFog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets {@link #playMusic} to specified value
|
||||
*
|
||||
* @param playMusic
|
||||
* Play music flag
|
||||
*/
|
||||
public void setPlayMusic(boolean playMusic) {
|
||||
this.playMusic = playMusic;
|
||||
}
|
||||
|
||||
/**
|
||||
* An enum representing all valid boss packet actions.
|
||||
* Calling ordinal() will return action's network ID.
|
||||
*/
|
||||
public enum Action {
|
||||
|
||||
ADD,
|
||||
REMOVE,
|
||||
UPDATE_PCT,
|
||||
UPDATE_NAME,
|
||||
UPDATE_STYLE,
|
||||
UPDATE_PROPERTIES
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
package me.neznamy.tab.api.protocol;
|
||||
|
||||
import me.neznamy.tab.api.chat.IChatBaseComponent;
|
||||
import me.neznamy.tab.api.util.Preconditions;
|
||||
|
||||
/**
|
||||
* A class representing platform specific packet class
|
||||
*/
|
||||
public class PacketPlayOutChat implements TabPacket {
|
||||
|
||||
/** Message to be sent */
|
||||
private final IChatBaseComponent message;
|
||||
|
||||
/** Message position */
|
||||
private final ChatMessageType type;
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters
|
||||
*
|
||||
* @param message
|
||||
* Chat message to be sent
|
||||
* @param type
|
||||
* Message position
|
||||
*/
|
||||
public PacketPlayOutChat(IChatBaseComponent message, ChatMessageType type) {
|
||||
Preconditions.checkNotNull(message, "message");
|
||||
Preconditions.checkNotNull(type, "message type");
|
||||
this.message = message;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("PacketPlayOutChat{message=%s,type=%s}", message, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #message}
|
||||
*
|
||||
* @return message
|
||||
*/
|
||||
public IChatBaseComponent getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #type}
|
||||
*
|
||||
* @return type
|
||||
*/
|
||||
public ChatMessageType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* An enum representing positions of a chat message
|
||||
* Calling ordinal() will return type's network ID.
|
||||
*/
|
||||
public enum ChatMessageType {
|
||||
|
||||
CHAT,
|
||||
SYSTEM,
|
||||
GAME_INFO
|
||||
}
|
||||
}
|
||||
@@ -1,440 +0,0 @@
|
||||
package me.neznamy.tab.api.protocol;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import me.neznamy.tab.api.chat.IChatBaseComponent;
|
||||
import me.neznamy.tab.api.util.Preconditions;
|
||||
|
||||
/**
|
||||
* A class representing platform specific packet class
|
||||
*/
|
||||
public class PacketPlayOutPlayerInfo implements TabPacket {
|
||||
|
||||
/** Packet actions */
|
||||
private final EnumSet<EnumPlayerInfoAction> actions;
|
||||
|
||||
/** List of affected entries */
|
||||
private final List<PlayerInfoData> entries;
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters.
|
||||
*
|
||||
* @param action
|
||||
* Packet action
|
||||
* @param entries
|
||||
* Affected entries
|
||||
*/
|
||||
public PacketPlayOutPlayerInfo(EnumPlayerInfoAction action, PlayerInfoData... entries) {
|
||||
this(action, Arrays.asList(entries));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters.
|
||||
*
|
||||
* @param action
|
||||
* Packet action
|
||||
* @param entries
|
||||
* Affected entries
|
||||
*/
|
||||
public PacketPlayOutPlayerInfo(EnumPlayerInfoAction action, List<PlayerInfoData> entries) {
|
||||
Preconditions.checkNotNull(action, "action");
|
||||
Preconditions.checkNotNull(entries, "entries");
|
||||
if (action == EnumPlayerInfoAction.ADD_PLAYER) {
|
||||
actions = EnumSet.of(EnumPlayerInfoAction.ADD_PLAYER,
|
||||
EnumPlayerInfoAction.INITIALIZE_CHAT,
|
||||
EnumPlayerInfoAction.UPDATE_GAME_MODE,
|
||||
EnumPlayerInfoAction.UPDATE_LISTED,
|
||||
EnumPlayerInfoAction.UPDATE_LATENCY,
|
||||
EnumPlayerInfoAction.UPDATE_DISPLAY_NAME);
|
||||
} else {
|
||||
this.actions = EnumSet.of(action);
|
||||
}
|
||||
this.entries = entries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters.
|
||||
*
|
||||
* @param actions
|
||||
* Packet actions
|
||||
* @param entries
|
||||
* Affected entries
|
||||
*/
|
||||
public PacketPlayOutPlayerInfo(EnumSet<EnumPlayerInfoAction> actions, PlayerInfoData... entries) {
|
||||
Preconditions.checkNotNull(actions, "action");
|
||||
Preconditions.checkNotNull(entries, "entries");
|
||||
this.actions = actions;
|
||||
this.entries = Arrays.asList(entries);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters.
|
||||
*
|
||||
* @param actions
|
||||
* Packet actions
|
||||
* @param entries
|
||||
* Affected entries
|
||||
*/
|
||||
public PacketPlayOutPlayerInfo(EnumSet<EnumPlayerInfoAction> actions, List<PlayerInfoData> entries) {
|
||||
Preconditions.checkNotNull(actions, "action");
|
||||
Preconditions.checkNotNull(entries, "entries");
|
||||
this.actions = actions;
|
||||
this.entries = entries;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("PacketPlayOutPlayerInfo{actions=%s,entries=%s}", actions, entries);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #actions}
|
||||
*
|
||||
* @return packet action
|
||||
*/
|
||||
public EnumSet<EnumPlayerInfoAction> getActions() {
|
||||
return actions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #entries}
|
||||
*
|
||||
* @return affected entries
|
||||
*/
|
||||
public List<PlayerInfoData> getEntries() {
|
||||
return entries;
|
||||
}
|
||||
|
||||
/**
|
||||
* A subclass representing player list entry
|
||||
*/
|
||||
public static class PlayerInfoData {
|
||||
|
||||
/** Latency */
|
||||
private int latency;
|
||||
|
||||
/** I have no idea what this is */
|
||||
private boolean listed;
|
||||
|
||||
/** 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.
|
||||
*/
|
||||
private IChatBaseComponent displayName;
|
||||
|
||||
/** Real name of affected player */
|
||||
private String name;
|
||||
|
||||
/** Player UUID */
|
||||
private UUID uniqueId;
|
||||
|
||||
/** Player's skin, null for empty skin */
|
||||
private Skin skin;
|
||||
|
||||
/** Chat session ID */
|
||||
private UUID chatSessionId;
|
||||
|
||||
/** Player's chat signing key */
|
||||
private Object profilePublicKey;
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters. Suitable for
|
||||
* {@link EnumPlayerInfoAction#ADD_PLAYER} action
|
||||
*
|
||||
* @param name
|
||||
* Player's name
|
||||
* @param uniqueId
|
||||
* Player's uuid
|
||||
* @param skin
|
||||
* Player's platform-specific skin object
|
||||
* @param latency
|
||||
* Player's ping
|
||||
* @param gameMode
|
||||
* Player's GameMode
|
||||
* @param displayName
|
||||
* Player's display name
|
||||
* @param profilePublicKey
|
||||
* Player's chat signing key
|
||||
*/
|
||||
public PlayerInfoData(String name, UUID uniqueId, Skin skin, boolean listed, int latency, EnumGamemode gameMode, IChatBaseComponent displayName, UUID chatSessionId, Object profilePublicKey) {
|
||||
Preconditions.checkNotNull(uniqueId, "uuid");
|
||||
this.name = name;
|
||||
this.uniqueId = uniqueId;
|
||||
this.skin = skin;
|
||||
this.listed = listed;
|
||||
this.latency = latency;
|
||||
this.gameMode = gameMode;
|
||||
this.displayName = displayName;
|
||||
this.chatSessionId = chatSessionId;
|
||||
this.profilePublicKey = profilePublicKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters. Suitable for
|
||||
* {@link EnumPlayerInfoAction#UPDATE_GAME_MODE} action
|
||||
*
|
||||
* @param uniqueId
|
||||
* Player's uuid
|
||||
* @param gameMode
|
||||
* Player's GameMode
|
||||
*/
|
||||
public PlayerInfoData(UUID uniqueId, EnumGamemode gameMode) {
|
||||
Preconditions.checkNotNull(uniqueId, "uuid");
|
||||
this.uniqueId = uniqueId;
|
||||
this.gameMode = gameMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters. Suitable for
|
||||
* {@link EnumPlayerInfoAction#UPDATE_LATENCY} action
|
||||
*
|
||||
* @param uniqueId
|
||||
* Player's uuid
|
||||
* @param latency
|
||||
* Player's ping
|
||||
*/
|
||||
public PlayerInfoData(UUID uniqueId, int latency) {
|
||||
Preconditions.checkNotNull(uniqueId, "uuid");
|
||||
this.uniqueId = uniqueId;
|
||||
this.latency = latency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters. Suitable for
|
||||
* {@link EnumPlayerInfoAction#UPDATE_DISPLAY_NAME} action
|
||||
*
|
||||
* @param uniqueId
|
||||
* Player's uuid
|
||||
* @param displayName
|
||||
* Player's display name
|
||||
*/
|
||||
public PlayerInfoData(UUID uniqueId, IChatBaseComponent displayName) {
|
||||
Preconditions.checkNotNull(uniqueId, "uuid");
|
||||
this.uniqueId = uniqueId;
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameter. Suitable for
|
||||
* {@link EnumPlayerInfoAction#REMOVE_PLAYER} action
|
||||
*
|
||||
* @param uniqueId
|
||||
* Player's uuid
|
||||
*/
|
||||
public PlayerInfoData(UUID uniqueId) {
|
||||
this.uniqueId = uniqueId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("PlayerInfoData{latency=%s,gameMode=%s,displayName=%s,name=%s,uniqueId=%s,skin=%s,profilePublicKey=%s}",
|
||||
latency, gameMode, displayName, name, uniqueId, skin, profilePublicKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #latency}
|
||||
*
|
||||
* @return latency
|
||||
*/
|
||||
public int getLatency() {
|
||||
return latency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets {@link #latency} to specified value
|
||||
*
|
||||
* @param latency
|
||||
* Latency to use
|
||||
*/
|
||||
public void setLatency(int latency) {
|
||||
this.latency = latency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #listed}
|
||||
*
|
||||
* @return listed
|
||||
*/
|
||||
public boolean isListed() {
|
||||
return listed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets {@link #listed} to specified value
|
||||
*
|
||||
* @param listed
|
||||
* Listed flag
|
||||
*/
|
||||
public void setListed(boolean listed) {
|
||||
this.listed = listed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #displayName}
|
||||
*
|
||||
* @return displayName
|
||||
*/
|
||||
public IChatBaseComponent getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets {@link #displayName} to specified value
|
||||
*
|
||||
* @param displayName
|
||||
* Display name to use
|
||||
*/
|
||||
public void setDisplayName(IChatBaseComponent displayName) {
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #uniqueId}
|
||||
*
|
||||
* @return uniqueId
|
||||
*/
|
||||
public UUID getUniqueId() {
|
||||
return uniqueId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets {@link #uniqueId} to specified value
|
||||
*
|
||||
* @param uniqueId
|
||||
* UUID to use
|
||||
*/
|
||||
public void setUniqueId(UUID uniqueId) {
|
||||
this.uniqueId = uniqueId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #name}
|
||||
*
|
||||
* @return name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets {@link #name} to specified value
|
||||
*
|
||||
* @param name
|
||||
* name to use
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #gameMode}
|
||||
*
|
||||
* @return gameMode
|
||||
*/
|
||||
public EnumGamemode getGameMode() {
|
||||
return gameMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets {@link #gameMode} to specified value
|
||||
*
|
||||
* @param gameMode
|
||||
* GameMode to use
|
||||
*/
|
||||
public void setGameMode(EnumGamemode gameMode) {
|
||||
this.gameMode = gameMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #skin}
|
||||
*
|
||||
* @return skin
|
||||
*/
|
||||
public Skin getSkin() {
|
||||
return skin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets {@link #skin} to specified value
|
||||
*
|
||||
* @param skin
|
||||
* Skin to use
|
||||
*/
|
||||
public void setSkin(Skin skin) {
|
||||
this.skin = skin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #chatSessionId}
|
||||
*
|
||||
* @return chatSessionId
|
||||
*/
|
||||
public UUID getChatSessionId() {
|
||||
return chatSessionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets {@link #chatSessionId} to specified value
|
||||
*
|
||||
* @param chatSessionId
|
||||
* chatSessionId to use
|
||||
*/
|
||||
public void setChatSessionId(UUID chatSessionId) {
|
||||
this.chatSessionId = chatSessionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #profilePublicKey}
|
||||
*
|
||||
* @return profilePublicKey
|
||||
*/
|
||||
public Object getProfilePublicKey() {
|
||||
return profilePublicKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets {@link #profilePublicKey} to specified value
|
||||
*
|
||||
* @param profilePublicKey
|
||||
* profilePublicKey to use
|
||||
*/
|
||||
public void setProfilePublicKey(Object profilePublicKey) {
|
||||
this.profilePublicKey = profilePublicKey;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* En enum representing packet action
|
||||
*/
|
||||
public enum EnumPlayerInfoAction {
|
||||
|
||||
ADD_PLAYER,
|
||||
INITIALIZE_CHAT,
|
||||
UPDATE_GAME_MODE,
|
||||
UPDATE_LISTED,
|
||||
UPDATE_LATENCY,
|
||||
UPDATE_DISPLAY_NAME,
|
||||
REMOVE_PLAYER
|
||||
}
|
||||
|
||||
/**
|
||||
* An enum representing GameMode
|
||||
*/
|
||||
public enum EnumGamemode {
|
||||
|
||||
NOT_SET,
|
||||
SURVIVAL,
|
||||
CREATIVE,
|
||||
ADVENTURE,
|
||||
SPECTATOR;
|
||||
|
||||
/** Value array to iterate over to avoid array creations on each call */
|
||||
public static final EnumGamemode[] VALUES = values();
|
||||
}
|
||||
}
|
||||
-70
@@ -1,70 +0,0 @@
|
||||
package me.neznamy.tab.api.protocol;
|
||||
|
||||
import me.neznamy.tab.api.chat.IChatBaseComponent;
|
||||
import me.neznamy.tab.api.util.Preconditions;
|
||||
|
||||
/**
|
||||
* A class representing platform specific packet class
|
||||
*/
|
||||
public class PacketPlayOutPlayerListHeaderFooter implements TabPacket {
|
||||
|
||||
/** TabList header */
|
||||
private final IChatBaseComponent header;
|
||||
|
||||
/** TabList footer */
|
||||
private final IChatBaseComponent footer;
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters. They are converted to {@link IChatBaseComponent}
|
||||
* using {@link IChatBaseComponent#optimizedComponent(String)} method.
|
||||
*
|
||||
* @param header
|
||||
* TabList header
|
||||
* @param footer
|
||||
* TabList footer
|
||||
*/
|
||||
public PacketPlayOutPlayerListHeaderFooter(String header, String footer) {
|
||||
Preconditions.checkNotNull(header, "header");
|
||||
Preconditions.checkNotNull(footer, "footer");
|
||||
this.header = IChatBaseComponent.optimizedComponent(header);
|
||||
this.footer = IChatBaseComponent.optimizedComponent(footer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters.
|
||||
*
|
||||
* @param header
|
||||
* TabList header
|
||||
* @param footer
|
||||
* TabList footer
|
||||
*/
|
||||
public PacketPlayOutPlayerListHeaderFooter(IChatBaseComponent header, IChatBaseComponent footer) {
|
||||
Preconditions.checkNotNull(header, "header");
|
||||
Preconditions.checkNotNull(footer, "footer");
|
||||
this.header = header;
|
||||
this.footer = footer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("PacketPlayOutPlayerListHeaderFooter{header=%s,footer=%s}", header, footer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #header}
|
||||
*
|
||||
* @return header
|
||||
*/
|
||||
public IChatBaseComponent getHeader() {
|
||||
return header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #footer}
|
||||
*
|
||||
* @return footer
|
||||
*/
|
||||
public IChatBaseComponent getFooter() {
|
||||
return footer;
|
||||
}
|
||||
}
|
||||
-60
@@ -1,60 +0,0 @@
|
||||
package me.neznamy.tab.api.protocol;
|
||||
|
||||
import me.neznamy.tab.api.util.Preconditions;
|
||||
|
||||
/**
|
||||
* A class representing platform specific packet class
|
||||
*/
|
||||
public class PacketPlayOutScoreboardDisplayObjective implements TabPacket {
|
||||
|
||||
/**
|
||||
* Display slot.
|
||||
* 0 = PlayerList,
|
||||
* 1 = SideBar,
|
||||
* 2 = BelowName.
|
||||
*/
|
||||
private final int slot;
|
||||
|
||||
/** Up to 16 characters long objective name */
|
||||
private final String objectiveName;
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters
|
||||
*
|
||||
* @param slot
|
||||
* Display slot
|
||||
* @param objectiveName
|
||||
* Internal name of the objective
|
||||
* @throws IllegalArgumentException
|
||||
* if {@code objectiveName} is null or longer than 16 characters
|
||||
*/
|
||||
public PacketPlayOutScoreboardDisplayObjective(int slot, String objectiveName) {
|
||||
Preconditions.checkNotNull(objectiveName, "objective name");
|
||||
Preconditions.checkMaxLength(objectiveName, 16, "objective name");
|
||||
this.slot = slot;
|
||||
this.objectiveName = objectiveName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("PacketPlayOutScoreboardDisplayObjective{slot=%s,objectiveName=%s}", slot, objectiveName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #slot}
|
||||
*
|
||||
* @return slot
|
||||
*/
|
||||
public int getSlot() {
|
||||
return slot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #objectiveName}
|
||||
*
|
||||
* @return objectiveName
|
||||
*/
|
||||
public String getObjectiveName() {
|
||||
return objectiveName;
|
||||
}
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
package me.neznamy.tab.api.protocol;
|
||||
|
||||
import me.neznamy.tab.api.util.Preconditions;
|
||||
|
||||
/**
|
||||
* A class representing platform specific packet class
|
||||
*/
|
||||
public class PacketPlayOutScoreboardObjective implements TabPacket {
|
||||
|
||||
/** Up to 16 characters long objective name */
|
||||
private final String objectiveName;
|
||||
|
||||
/** Display name */
|
||||
private final String displayName;
|
||||
|
||||
/** Display type, only takes effect in PlayerList */
|
||||
private final EnumScoreboardHealthDisplay renderType;
|
||||
|
||||
/**
|
||||
* Packet action.
|
||||
* 0 = register,
|
||||
* 1 = unregister,
|
||||
* 2 = update title
|
||||
*/
|
||||
private final int action;
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters.
|
||||
*
|
||||
* @param action
|
||||
* Packet action (0 = add, 1 = remove, 2 = update title)
|
||||
* @param objectiveName
|
||||
* objective name, up to 16 characters long
|
||||
* @param displayName
|
||||
* title
|
||||
* @param renderType
|
||||
* display type
|
||||
* @throws IllegalArgumentException
|
||||
* if {@code objectiveName} is null or longer than 16 characters
|
||||
*/
|
||||
public PacketPlayOutScoreboardObjective(int action, String objectiveName, String displayName, EnumScoreboardHealthDisplay renderType) {
|
||||
Preconditions.checkRange(action, 0, 2, "action");
|
||||
Preconditions.checkNotNull(objectiveName, "objective name");
|
||||
Preconditions.checkMaxLength(objectiveName, 16, "objective name");
|
||||
Preconditions.checkNotNull(renderType, "render type");
|
||||
this.objectiveName = objectiveName;
|
||||
this.displayName = displayName;
|
||||
this.renderType = renderType;
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new packet with given objective name and 1 (unregister) action.
|
||||
*
|
||||
* @param objectiveName
|
||||
* objective name, up to 16 characters long
|
||||
* @throws IllegalArgumentException
|
||||
* if {@code objectiveName} is null or longer than 16 characters
|
||||
*/
|
||||
public PacketPlayOutScoreboardObjective(String objectiveName) {
|
||||
Preconditions.checkNotNull(objectiveName, "objective name");
|
||||
Preconditions.checkMaxLength(objectiveName, 16, "objective name");
|
||||
this.objectiveName = objectiveName;
|
||||
this.displayName = ""; //avoiding NPE on <1.7
|
||||
this.action = 1;
|
||||
this.renderType = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("PacketPlayOutScoreboardObjective{objectiveName=%s,displayName=%s,renderType=%s,method=%s}",
|
||||
objectiveName, displayName, renderType, action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #displayName}
|
||||
*
|
||||
* @return displayName
|
||||
*/
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #objectiveName}
|
||||
*
|
||||
* @return objectiveName
|
||||
*/
|
||||
public String getObjectiveName() {
|
||||
return objectiveName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #renderType}
|
||||
*
|
||||
* @return renderType
|
||||
*/
|
||||
public EnumScoreboardHealthDisplay getRenderType() {
|
||||
return renderType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #action}
|
||||
*
|
||||
* @return packet action
|
||||
*/
|
||||
public int getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
/**
|
||||
* An enum representing available display types.
|
||||
* They only take effect in PlayerList position.
|
||||
*/
|
||||
public enum EnumScoreboardHealthDisplay {
|
||||
|
||||
INTEGER, HEARTS
|
||||
}
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
package me.neznamy.tab.api.protocol;
|
||||
|
||||
import me.neznamy.tab.api.util.Preconditions;
|
||||
|
||||
/**
|
||||
* A class representing platform specific packet class
|
||||
*/
|
||||
public class PacketPlayOutScoreboardScore implements TabPacket {
|
||||
|
||||
/** Packet action */
|
||||
private final Action action;
|
||||
|
||||
/** Objective name */
|
||||
private final String objectiveName;
|
||||
|
||||
/** Affected player */
|
||||
private final String player;
|
||||
|
||||
/** Player's score */
|
||||
private final int score;
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters
|
||||
*
|
||||
* @param action
|
||||
* Packet action
|
||||
* @param objectiveName
|
||||
* Objective name
|
||||
* @param player
|
||||
* Affected player
|
||||
* @param score
|
||||
* Player's score
|
||||
* @throws IllegalArgumentException
|
||||
* if {@code objectiveName} is null or longer than 16 characters
|
||||
*/
|
||||
public PacketPlayOutScoreboardScore(Action action, String objectiveName, String player, int score) {
|
||||
Preconditions.checkNotNull(action, "action");
|
||||
Preconditions.checkNotNull(objectiveName, "objective name");
|
||||
Preconditions.checkMaxLength(objectiveName, 16, "objective name");
|
||||
Preconditions.checkNotNull(player, "player");
|
||||
this.action = action;
|
||||
this.objectiveName = objectiveName;
|
||||
this.player = player;
|
||||
this.score = score;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("PacketPlayOutScoreboardScore{action=%s,objectiveName=%s,player=%s,score=%s}",
|
||||
action, objectiveName, player, score);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #action}
|
||||
*
|
||||
* @return packet action
|
||||
*/
|
||||
public Action getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #objectiveName}
|
||||
*
|
||||
* @return objective name
|
||||
*/
|
||||
public String getObjectiveName() {
|
||||
return objectiveName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #player}
|
||||
*
|
||||
* @return player
|
||||
*/
|
||||
public String getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #score}
|
||||
*
|
||||
* @return score
|
||||
*/
|
||||
public int getScore() {
|
||||
return score;
|
||||
}
|
||||
|
||||
/**
|
||||
* An enum representing action types
|
||||
*/
|
||||
public enum Action {
|
||||
|
||||
CHANGE,
|
||||
REMOVE
|
||||
}
|
||||
}
|
||||
@@ -1,285 +0,0 @@
|
||||
package me.neznamy.tab.api.protocol;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import me.neznamy.tab.api.chat.EnumChatFormat;
|
||||
import me.neznamy.tab.api.util.Preconditions;
|
||||
|
||||
/**
|
||||
* A class representing platform specific packet class
|
||||
*/
|
||||
public class PacketPlayOutScoreboardTeam implements TabPacket {
|
||||
|
||||
/**
|
||||
* Up to 16 characters long team name.
|
||||
* 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 final String name;
|
||||
|
||||
/** Team prefix, limited to 16 characters, on <1.13 */
|
||||
private String playerPrefix;
|
||||
|
||||
/** Team suffix, limited to 16 characters, on <1.13 */
|
||||
private String playerSuffix;
|
||||
|
||||
/**
|
||||
* NameTag visibility rule since 1.8. Possible options are:
|
||||
* {@code always}, {@code hideForOtherTeams}, {@code hideForOwnTeam}, {@code never}
|
||||
*/
|
||||
private String nameTagVisibility;
|
||||
|
||||
/**
|
||||
* Collision rule added in 1.9. Possible options are:
|
||||
* {@code always}, {@code pushOtherTeams}, {@code pushOwnTeam}, {@code never}
|
||||
*/
|
||||
private String collisionRule;
|
||||
|
||||
/**
|
||||
* Team color field added in 1.13. It determines name color,
|
||||
* prefix and suffix color start.
|
||||
*/
|
||||
private EnumChatFormat color;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
private Collection<String> players = Collections.emptyList();
|
||||
|
||||
/**
|
||||
* Packet action.
|
||||
* 0 = create team,
|
||||
* 1 = remove team,
|
||||
* 2 = update team info,
|
||||
* 3 = add entries,
|
||||
* 4 = remove entries
|
||||
*/
|
||||
private final int action;
|
||||
|
||||
/**
|
||||
* Bit mask.
|
||||
* 0x01: Allow friendly fire,
|
||||
* 0x02: Can see invisible players on the same team.
|
||||
*/
|
||||
private int options;
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters. Private constructor used
|
||||
* internally to validate team name and set action.
|
||||
*
|
||||
* @param action
|
||||
* Packet action (0 = create team, 1 = remove team, 2 = update team info,
|
||||
* 3 = add entries, 4 = remove entries)
|
||||
* @param name
|
||||
* Team name, up to 16 characters long
|
||||
* @throws IllegalArgumentException
|
||||
* if {@code name} is null, empty or longer than 16 characters
|
||||
*/
|
||||
private PacketPlayOutScoreboardTeam(int action, String name) {
|
||||
Preconditions.checkNotNull(name, "team name");
|
||||
Preconditions.checkMaxLength(name, 16, "team name");
|
||||
this.action = action;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters and 0 (CREATE) action
|
||||
*
|
||||
* @param team
|
||||
* Team name, up to 16 characters long
|
||||
* @param prefix
|
||||
* Prefix of players in team
|
||||
* @param suffix
|
||||
* Suffix of players in team
|
||||
* @param visibility
|
||||
* NameTag visibility rule
|
||||
* @param collision
|
||||
* Collision rule
|
||||
* @param players
|
||||
* Affected entities
|
||||
* @param options
|
||||
* bitmask of team options
|
||||
* @throws IllegalArgumentException
|
||||
* if {@code name} is null, empty or longer than 16 characters
|
||||
*/
|
||||
public PacketPlayOutScoreboardTeam(String team, String prefix, String suffix, String visibility, String collision, Collection<String> players, int options) {
|
||||
this(0, team);
|
||||
Preconditions.checkNotNull(prefix, "prefix");
|
||||
Preconditions.checkNotNull(suffix, "suffix");
|
||||
Preconditions.checkNotNull(visibility, "visibility");
|
||||
Preconditions.checkNotNull(collision, "collision");
|
||||
Preconditions.checkNotNull(players, "players");
|
||||
this.playerPrefix = prefix;
|
||||
this.playerSuffix = suffix;
|
||||
this.nameTagVisibility = visibility;
|
||||
this.collisionRule = collision;
|
||||
this.players = players;
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters and 1 (REMOVE) action
|
||||
*
|
||||
* @param team
|
||||
* Team name, up to 16 characters long
|
||||
* @throws IllegalArgumentException
|
||||
* if {@code name} is null, empty or longer than 16 characters
|
||||
*/
|
||||
public PacketPlayOutScoreboardTeam(String team) {
|
||||
this(1, team);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters and 2 (UPDATE_TEAM_INFO) action
|
||||
*
|
||||
* @param team
|
||||
* Team name, up to 16 characters long
|
||||
* @param prefix
|
||||
* Prefix of players in team
|
||||
* @param suffix
|
||||
* Suffix of players in team
|
||||
* @param visibility
|
||||
* NameTag visibility rule
|
||||
* @param collision
|
||||
* Collision rule
|
||||
* @param options
|
||||
* bitmask of team options
|
||||
* @throws IllegalArgumentException
|
||||
* if {@code name} is null, empty or longer than 16 characters
|
||||
*/
|
||||
public PacketPlayOutScoreboardTeam(String team, String prefix, String suffix, String visibility, String collision, int options) {
|
||||
this(2, team);
|
||||
Preconditions.checkNotNull(prefix, "prefix");
|
||||
Preconditions.checkNotNull(suffix, "suffix");
|
||||
Preconditions.checkNotNull(visibility, "visibility");
|
||||
Preconditions.checkNotNull(collision, "collision");
|
||||
Preconditions.checkNotNull(players, "players");
|
||||
this.playerPrefix = prefix;
|
||||
this.playerSuffix = suffix;
|
||||
this.nameTagVisibility = visibility;
|
||||
this.collisionRule = collision;
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters and 3 (ADD_PLAYERS) if {@code add} is {@code true},
|
||||
* 4 (REMOVE_PLAYERS) if {@code add} is {@code false} action.
|
||||
*
|
||||
* @param team
|
||||
* Team name, up to 16 characters long
|
||||
* @param players
|
||||
* Affected entities
|
||||
* @param add
|
||||
* {@code true} if players should be added, {@code false} if removed from team
|
||||
* @throws IllegalArgumentException
|
||||
* if {@code name} is null, empty or longer than 16 characters
|
||||
*/
|
||||
public PacketPlayOutScoreboardTeam(String team, Collection<String> players, boolean add) {
|
||||
this(add ? 3 : 4, team);
|
||||
Preconditions.checkNotNull(players, "players");
|
||||
this.players = players;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
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, action, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #name}
|
||||
*
|
||||
* @return team name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #playerPrefix}
|
||||
*
|
||||
* @return playerPrefix
|
||||
*/
|
||||
public String getPlayerPrefix() {
|
||||
return playerPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #playerSuffix}
|
||||
*
|
||||
* @return playerSuffix
|
||||
*/
|
||||
public String getPlayerSuffix() {
|
||||
return playerSuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #nameTagVisibility}
|
||||
*
|
||||
* @return nameTagVisibility
|
||||
*/
|
||||
public String getNameTagVisibility() {
|
||||
return nameTagVisibility;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #collisionRule}
|
||||
*
|
||||
* @return collisionRule
|
||||
*/
|
||||
public String getCollisionRule() {
|
||||
return collisionRule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets {@link #color} to specified color
|
||||
*
|
||||
* @param color
|
||||
* color to use
|
||||
*/
|
||||
public void setColor(EnumChatFormat color) {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #color}
|
||||
*
|
||||
* @return color
|
||||
*/
|
||||
public EnumChatFormat getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #players}
|
||||
*
|
||||
* @return players
|
||||
*/
|
||||
public Collection<String> getPlayers() {
|
||||
return players;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #options}
|
||||
*
|
||||
* @return team options
|
||||
*/
|
||||
public int getOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #action}
|
||||
*
|
||||
* @return packet action
|
||||
*/
|
||||
public int getAction() {
|
||||
return action;
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
package me.neznamy.tab.api.protocol;
|
||||
|
||||
import me.neznamy.tab.api.util.Preconditions;
|
||||
|
||||
/**
|
||||
* Class representing a minecraft skin as a value - signature pair.
|
||||
*/
|
||||
public class Skin {
|
||||
|
||||
/** Skin value */
|
||||
private final String value;
|
||||
|
||||
/** Skin signature, can be null */
|
||||
private final String signature;
|
||||
|
||||
/**
|
||||
* Constructs new instance with given parameters
|
||||
*
|
||||
* @param value
|
||||
* skin value
|
||||
* @param signature
|
||||
* skin signature
|
||||
* @throws IllegalArgumentException
|
||||
* if {@code value} is {@code null}
|
||||
*/
|
||||
public Skin(String value, String signature) {
|
||||
Preconditions.checkNotNull(value, "value");
|
||||
this.value = value;
|
||||
this.signature = signature;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns skin value
|
||||
*
|
||||
* @return skin value
|
||||
*/
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns skin signature
|
||||
*
|
||||
* @return skin signature
|
||||
*/
|
||||
public String getSignature() {
|
||||
return signature;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns user-friendly representation of this object
|
||||
*
|
||||
* @return user-friendly representation of this object
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("Skin{value=%s,signature=%s}", value, signature);
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package me.neznamy.tab.api.protocol;
|
||||
|
||||
/**
|
||||
* Interface representing a packet that can be sent to client independently of platform.
|
||||
* It is technically empty, existence is only present to restrict type access
|
||||
* when sending packets to player, so {@link me.neznamy.tab.api.TabPlayer#sendCustomPacket(TabPacket)} cannot
|
||||
* be called with an actual packet.
|
||||
*/
|
||||
public interface TabPacket {
|
||||
|
||||
/**
|
||||
* Returns user-friendly string representation of the packet
|
||||
*
|
||||
* @return user-friendly string representation of the packet
|
||||
*/
|
||||
String toString();
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
package me.neznamy.tab.api.scoreboard;
|
||||
|
||||
import lombok.NonNull;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* An interface allowing to work with a line of
|
||||
* text in scoreboard.
|
||||
@@ -13,7 +16,7 @@ public interface Line {
|
||||
*
|
||||
* @return raw text of this line
|
||||
*/
|
||||
String getText();
|
||||
@NotNull String getText();
|
||||
|
||||
/**
|
||||
* Changes text to new value. Supports placeholders, which are
|
||||
@@ -25,5 +28,5 @@ public interface Line {
|
||||
* @param text
|
||||
* Raw text to display in the line
|
||||
*/
|
||||
void setText(String text);
|
||||
void setText(@NonNull String text);
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
package me.neznamy.tab.api.scoreboard;
|
||||
|
||||
import lombok.NonNull;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -8,16 +11,17 @@ import java.util.List;
|
||||
* {@link ScoreboardManager#createScoreboard(String, String, List)},
|
||||
* for scoreboards from config {@link ScoreboardManager#getRegisteredScoreboards()}.
|
||||
*/
|
||||
@SuppressWarnings("unused") // API class
|
||||
public interface Scoreboard {
|
||||
|
||||
/**
|
||||
* Returns internal name of this scoreboard. Name is defined in registration,
|
||||
* scoreboards from config use name they were defined with. This value is
|
||||
* used internally and in /tab announce scoreboard command.
|
||||
* used internally and in /tab scoreboard announce command.
|
||||
*
|
||||
* @return custom name of this scoreboard
|
||||
*/
|
||||
String getName();
|
||||
@NotNull String getName();
|
||||
|
||||
/**
|
||||
* Returns raw title of this scoreboard. Placeholders stay in their
|
||||
@@ -26,7 +30,7 @@ public interface Scoreboard {
|
||||
* @return scoreboard title
|
||||
* @see #setTitle(String)
|
||||
*/
|
||||
String getTitle();
|
||||
@NotNull String getTitle();
|
||||
|
||||
/**
|
||||
* Sets title to specified value. Placeholders are refreshed automatically
|
||||
@@ -43,7 +47,7 @@ public interface Scoreboard {
|
||||
* New title to use with placeholder support
|
||||
* @see #getTitle()
|
||||
*/
|
||||
void setTitle(String title);
|
||||
void setTitle(@NonNull String title);
|
||||
|
||||
/**
|
||||
* Returns list of lines in this scoreboard in the order they appear
|
||||
@@ -54,7 +58,7 @@ public interface Scoreboard {
|
||||
* @see #addLine(String)
|
||||
* @see #removeLine(int)
|
||||
*/
|
||||
List<Line> getLines();
|
||||
@NotNull List<Line> getLines();
|
||||
|
||||
/**
|
||||
* Adds line with specified text on the bottom of scoreboard. Supports
|
||||
@@ -65,7 +69,7 @@ public interface Scoreboard {
|
||||
* @see #getLines()
|
||||
* @see #removeLine(int)
|
||||
*/
|
||||
void addLine(String text);
|
||||
void addLine(@NonNull String text);
|
||||
|
||||
/**
|
||||
* Removes line with specified index. Index starts at {@code 0} and ends at
|
||||
@@ -80,8 +84,24 @@ public interface Scoreboard {
|
||||
*/
|
||||
void removeLine(int index);
|
||||
|
||||
/**
|
||||
* Replaces all current lines with the provided list.
|
||||
* Supports placeholders, which will automatically be refreshed.
|
||||
* Client can only see up to 15 lines at a time.
|
||||
* If the new list is identical to the current one, nothing happens.
|
||||
*
|
||||
* @param lines
|
||||
* New list of lines to display
|
||||
* @throws NullPointerException
|
||||
* if {@code lines} is {@code null}
|
||||
* @see #getLines()
|
||||
* @see #addLine(String)
|
||||
* @see #removeLine(int)
|
||||
*/
|
||||
void setLines(@NonNull List<String> lines);
|
||||
|
||||
/**
|
||||
* Unregisters this scoreboard from all players who can see it.
|
||||
*/
|
||||
void unregister();
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,22 @@
|
||||
package me.neznamy.tab.api.scoreboard;
|
||||
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
|
||||
/**
|
||||
* Interface allowing work with scoreboards, such as creating,
|
||||
* sending, toggling and modifying.
|
||||
* <p>
|
||||
* Instance can be obtained using {@link me.neznamy.tab.api.TabAPI#getScoreboardManager()}.
|
||||
* This requires the scoreboard feature to be enabled in config,
|
||||
* the method will return null otherwise.
|
||||
* the method will return {@code null} otherwise.
|
||||
*/
|
||||
@SuppressWarnings("unused") // API class
|
||||
public interface ScoreboardManager {
|
||||
|
||||
/**
|
||||
@@ -39,7 +43,7 @@ public interface ScoreboardManager {
|
||||
* @throws NullPointerException
|
||||
* if {@code name} or {@code lines} is {@code null}
|
||||
*/
|
||||
Scoreboard createScoreboard(String name, String title, List<String> lines);
|
||||
@NotNull Scoreboard createScoreboard(@NonNull String name, @NonNull String title, @NonNull List<String> lines);
|
||||
|
||||
/**
|
||||
* Returns map of registered scoreboards via config and API.
|
||||
@@ -49,7 +53,30 @@ public interface ScoreboardManager {
|
||||
*
|
||||
* @return map of registered scoreboards
|
||||
*/
|
||||
Map<String, Scoreboard> getRegisteredScoreboards();
|
||||
@NotNull Map<String, Scoreboard> getRegisteredScoreboards();
|
||||
|
||||
/**
|
||||
* Removes scoreboard with specified name from list of scoreboards. If it was displayed to anyone,
|
||||
* it will be removed from their display as well. Then, those players will receive a new scoreboard based
|
||||
* on configuration.
|
||||
*
|
||||
* @param name Name of scoreboard to remove
|
||||
* @throws IllegalArgumentException
|
||||
* if scoreboard with such name does not exist
|
||||
*/
|
||||
void removeScoreboard(@NonNull String name);
|
||||
|
||||
/**
|
||||
* Removes scoreboard from list of scoreboards. If it was displayed to anyone,
|
||||
* it will be removed from their display as well. Then, those players will receive a new scoreboard based
|
||||
* on configuration.
|
||||
*
|
||||
* @param scoreboard
|
||||
* Scoreboard to remove
|
||||
* @throws IllegalArgumentException
|
||||
* if specified scoreboard is not registered
|
||||
*/
|
||||
void removeScoreboard(@NonNull Scoreboard scoreboard);
|
||||
|
||||
/**
|
||||
* Displays scoreboard to defined player. This will disable all display
|
||||
@@ -66,7 +93,7 @@ public interface ScoreboardManager {
|
||||
* @see #hasCustomScoreboard(TabPlayer)
|
||||
* @see #resetScoreboard(TabPlayer)
|
||||
*/
|
||||
void showScoreboard(TabPlayer player, Scoreboard scoreboard);
|
||||
void showScoreboard(@NonNull TabPlayer player, @NonNull Scoreboard scoreboard);
|
||||
|
||||
/**
|
||||
* Returns {@code true} if player has custom scoreboard set using
|
||||
@@ -79,7 +106,7 @@ public interface ScoreboardManager {
|
||||
* @see #showScoreboard(TabPlayer, Scoreboard)
|
||||
* @see #resetScoreboard(TabPlayer)
|
||||
*/
|
||||
boolean hasCustomScoreboard(TabPlayer player);
|
||||
boolean hasCustomScoreboard(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Hides custom scoreboard sent using {@link #showScoreboard(TabPlayer, Scoreboard)}
|
||||
@@ -91,7 +118,7 @@ public interface ScoreboardManager {
|
||||
* @see #showScoreboard(TabPlayer, Scoreboard)
|
||||
* @see #hasCustomScoreboard(TabPlayer)
|
||||
*/
|
||||
void resetScoreboard(TabPlayer player);
|
||||
void resetScoreboard(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns {@code true} if player has scoreboard enabled, {@code false}
|
||||
@@ -105,7 +132,7 @@ public interface ScoreboardManager {
|
||||
* @see #setScoreboardVisible(TabPlayer, boolean, boolean)
|
||||
* @see #toggleScoreboard(TabPlayer, boolean)
|
||||
*/
|
||||
boolean hasScoreboardVisible(TabPlayer player);
|
||||
boolean hasScoreboardVisible(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Sets scoreboard visibility of player to defined value. If visibility status
|
||||
@@ -122,7 +149,7 @@ public interface ScoreboardManager {
|
||||
* @see #toggleScoreboard(TabPlayer, boolean)
|
||||
* @see #hasScoreboardVisible(TabPlayer)
|
||||
*/
|
||||
void setScoreboardVisible(TabPlayer player, boolean visible, boolean sendToggleMessage);
|
||||
void setScoreboardVisible(@NonNull TabPlayer player, boolean visible, boolean sendToggleMessage);
|
||||
|
||||
/**
|
||||
* Toggles scoreboard for specified player. If player had scoreboard visible,
|
||||
@@ -136,7 +163,7 @@ public interface ScoreboardManager {
|
||||
* @see #hasScoreboardVisible(TabPlayer)
|
||||
* @see #setScoreboardVisible(TabPlayer, boolean, boolean)
|
||||
*/
|
||||
void toggleScoreboard(TabPlayer player, boolean sendToggleMessage);
|
||||
void toggleScoreboard(@NonNull TabPlayer player, boolean sendToggleMessage);
|
||||
|
||||
/**
|
||||
* Temporarily displays scoreboard to all players for specified amount of
|
||||
@@ -151,7 +178,7 @@ public interface ScoreboardManager {
|
||||
* if no scoreboard was found with such name or {@code duration}
|
||||
* is < 0.
|
||||
*/
|
||||
void announceScoreboard(String scoreboard, int duration);
|
||||
void announceScoreboard(@NonNull String scoreboard, int duration);
|
||||
|
||||
/**
|
||||
* Returns player's currently displayed scoreboard. This can be either with
|
||||
@@ -162,5 +189,5 @@ public interface ScoreboardManager {
|
||||
* player to get active scoreboard of
|
||||
* @return player's active scoreboard or {@code null} if player has no scoreboard
|
||||
*/
|
||||
Scoreboard getActiveScoreboard(TabPlayer player);
|
||||
@Nullable Scoreboard getActiveScoreboard(@NonNull TabPlayer player);
|
||||
}
|
||||
+13
-37
@@ -1,4 +1,9 @@
|
||||
package me.neznamy.tab.api;
|
||||
package me.neznamy.tab.api.tablist;
|
||||
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.tab.api.TabAPI;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Interface allowing to send header/footer to players.
|
||||
@@ -7,39 +12,40 @@ package me.neznamy.tab.api;
|
||||
* This requires the Header/footer feature to be enabled in config, otherwise
|
||||
* the method will return {@code null}.
|
||||
*/
|
||||
@SuppressWarnings("unused") // API class
|
||||
public interface HeaderFooterManager {
|
||||
|
||||
/**
|
||||
* Sets raw value of header to specified value. This overrides plugin
|
||||
* configuration until reset is called. Has full placeholder support
|
||||
* and will send update packet whenever a placeholder used inside
|
||||
* changes its value.
|
||||
* changes its value. Use {@code null} to reset value back to original.
|
||||
*
|
||||
* @param player
|
||||
* Player to set header for
|
||||
* @param header
|
||||
* Raw header value
|
||||
*/
|
||||
void setHeader(TabPlayer player, String header);
|
||||
void setHeader(@NonNull TabPlayer player, @Nullable String header);
|
||||
|
||||
/**
|
||||
* Sets raw value of footer to specified value. This overrides plugin
|
||||
* configuration until reset is called. Has full placeholder support
|
||||
* and will send update packet whenever a placeholder used inside
|
||||
* changes its value.
|
||||
* changes its value. Use {@code null} to reset value back to original.
|
||||
*
|
||||
* @param player
|
||||
* Player to set header for
|
||||
* @param footer
|
||||
* Raw footer value
|
||||
*/
|
||||
void setFooter(TabPlayer player, String footer);
|
||||
void setFooter(@NonNull TabPlayer player, @Nullable String footer);
|
||||
|
||||
/**
|
||||
* Sets raw value of header and footer to specified values. This overrides plugin
|
||||
* configuration until reset is called. Has full placeholder support
|
||||
* and will send update packet whenever a placeholder used inside
|
||||
* changes its value.
|
||||
* changes its value. Use {@code null} to reset value back to original.
|
||||
*
|
||||
* @param player
|
||||
* Player to set header for
|
||||
@@ -48,35 +54,5 @@ public interface HeaderFooterManager {
|
||||
* @param footer
|
||||
* Raw footer value
|
||||
*/
|
||||
void setHeaderAndFooter(TabPlayer player, String header, String footer);
|
||||
|
||||
/**
|
||||
* Resets header value previously set using {@link #setHeader(TabPlayer, String)}
|
||||
* or {@link #setHeaderAndFooter(TabPlayer, String, String)} and restores internal
|
||||
* logic using configuration files.
|
||||
*
|
||||
* @param player
|
||||
* Player to reset header for
|
||||
*/
|
||||
void resetHeader(TabPlayer player);
|
||||
|
||||
/**
|
||||
* Resets footer value previously set using {@link #setFooter(TabPlayer, String)}
|
||||
* or {@link #setHeaderAndFooter(TabPlayer, String, String)} and restores internal
|
||||
* logic using configuration files.
|
||||
*
|
||||
* @param player
|
||||
* Player to reset header for
|
||||
*/
|
||||
void resetFooter(TabPlayer player);
|
||||
|
||||
/**
|
||||
* Resets values previously set using {@link #setHeader(TabPlayer, String)},
|
||||
* {@link #setFooter(TabPlayer, String)} or {@link #setHeaderAndFooter(TabPlayer, String, String)}
|
||||
* and restores internal logic using configuration files.
|
||||
*
|
||||
* @param player
|
||||
* Player to reset header and footer for
|
||||
*/
|
||||
void resetHeaderAndFooter(TabPlayer player);
|
||||
void setHeaderAndFooter(@NonNull TabPlayer player, @Nullable String header, @Nullable String footer);
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package me.neznamy.tab.api.tablist;
|
||||
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.tab.api.TabAPI;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Interface for managing player sorting by directly configuring
|
||||
* team names of players. Instance can be obtained using
|
||||
* {@link TabAPI#getSortingManager()}. If the feature is disabled,
|
||||
* it will return {@code null}.
|
||||
*/
|
||||
@SuppressWarnings("unused") // API class
|
||||
public interface SortingManager {
|
||||
|
||||
/**
|
||||
* Forces new team name for the player until this method is called again with null argument and
|
||||
* performs all actions to change player's team name
|
||||
*
|
||||
* @param player
|
||||
* player to set team name of
|
||||
* @param teamName
|
||||
* forced team name
|
||||
*/
|
||||
void forceTeamName(@NonNull TabPlayer player, @Nullable String teamName);
|
||||
|
||||
/**
|
||||
* Returns forced team name of player or null if not forced
|
||||
*
|
||||
* @param player
|
||||
* player to check forced team name of
|
||||
* @return forced team name of player or null if not forced
|
||||
*/
|
||||
@Nullable String getForcedTeamName(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns original team name of the player set by the plugin.
|
||||
*
|
||||
* @param player
|
||||
* Player to get team name of
|
||||
* @return Player's team name based on configuration.
|
||||
*/
|
||||
@NotNull String getOriginalTeamName(@NonNull TabPlayer player);
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
package me.neznamy.tab.api.tablist;
|
||||
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.tab.api.TabAPI;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* An interface allowing to modify TabList display names
|
||||
* of players.
|
||||
* <p>
|
||||
* Instance can be obtained using {@link TabAPI#getTabListFormatManager()}.
|
||||
* This requires the feature to be enabled in config, otherwise the method will
|
||||
* return {@code null}.
|
||||
*/
|
||||
@SuppressWarnings("unused") // API class
|
||||
public interface TabListFormatManager {
|
||||
|
||||
/**
|
||||
* Changes player's prefix to provided value. Supports placeholders,
|
||||
* as well as any supported RGB formats. Use {@code null} to reset
|
||||
* value back to original.
|
||||
*
|
||||
* @param player
|
||||
* player to change prefix of
|
||||
* @param prefix
|
||||
* new prefix value
|
||||
* @see #getCustomPrefix(TabPlayer)
|
||||
* @see #getOriginalRawPrefix(TabPlayer)
|
||||
*/
|
||||
void setPrefix(@NonNull TabPlayer player, @Nullable String prefix);
|
||||
|
||||
/**
|
||||
* Changes player's name to provided value. Supports placeholders,
|
||||
* as well as any supported RGB formats. Use {@code null} to reset
|
||||
* value back to original.
|
||||
*
|
||||
* @param player
|
||||
* player to change prefix of
|
||||
* @param customName
|
||||
* new customName value
|
||||
* @see #getCustomName(TabPlayer)
|
||||
* @see #getOriginalRawName(TabPlayer)
|
||||
*/
|
||||
void setName(@NonNull TabPlayer player, @Nullable String customName);
|
||||
|
||||
/**
|
||||
* Changes player's suffix to provided value. Supports placeholders,
|
||||
* as well as any supported RGB formats. Use {@code null} to reset
|
||||
* value back to original.
|
||||
*
|
||||
* @param player
|
||||
* player to change prefix of
|
||||
* @param suffix
|
||||
* new suffix value
|
||||
* @see #getCustomSuffix(TabPlayer)
|
||||
* @see #getOriginalRawSuffix(TabPlayer)
|
||||
*/
|
||||
void setSuffix(@NonNull TabPlayer player, @Nullable String suffix);
|
||||
|
||||
/**
|
||||
* Returns prefix assigned using {@link #setPrefix(TabPlayer, String)} method.
|
||||
* If the method was not used, {@code null} is returned.
|
||||
*
|
||||
* @param player
|
||||
* player to get custom prefix of
|
||||
* @return player's custom prefix or {@code null} if not defined
|
||||
* @see #setPrefix(TabPlayer, String)
|
||||
* @see #getOriginalRawPrefix(TabPlayer)
|
||||
*/
|
||||
@Nullable String getCustomPrefix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns custom name assigned using {@link #setName(TabPlayer, String)} method.
|
||||
* If the method was not used, {@code null} is returned.
|
||||
*
|
||||
* @param player
|
||||
* player to get custom name of
|
||||
* @return player's custom name or {@code null} if not defined
|
||||
* @see #setName(TabPlayer, String)
|
||||
* @see #getOriginalName(TabPlayer)
|
||||
*/
|
||||
@Nullable String getCustomName(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns suffix assigned using {@link #setSuffix(TabPlayer, String)} method.
|
||||
* If the method was not used, {@code null} is returned.
|
||||
*
|
||||
* @param player
|
||||
* player to get custom suffix of
|
||||
* @return player's custom suffix or {@code null} if not defined
|
||||
* @see #setSuffix(TabPlayer, String)
|
||||
* @see #getOriginalSuffix(TabPlayer)
|
||||
*/
|
||||
@Nullable String getCustomSuffix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns player's original prefix applied using plugin's internal logic.
|
||||
* This value is not affected by API calls in any way.
|
||||
*
|
||||
* @param player
|
||||
* player to get original prefix of
|
||||
* @return player's original prefix
|
||||
* @see #setPrefix(TabPlayer, String)
|
||||
* @see #getCustomPrefix(TabPlayer)
|
||||
* @deprecated Use {@link #getOriginalRawPrefix(TabPlayer)} instead.
|
||||
*/
|
||||
@NotNull
|
||||
@Deprecated
|
||||
String getOriginalPrefix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns player's original name applied using plugin's internal logic.
|
||||
* This value is not affected by API calls in any way.
|
||||
*
|
||||
* @param player
|
||||
* player to get original name of
|
||||
* @return player's original name
|
||||
* @see #setName(TabPlayer, String)
|
||||
* @see #getCustomName(TabPlayer)
|
||||
* @deprecated Use {@link #getOriginalRawName(TabPlayer)} instead.
|
||||
*/
|
||||
@NotNull
|
||||
@Deprecated
|
||||
String getOriginalName(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns player's original suffix applied using plugin's internal logic.
|
||||
* This value is not affected by API calls in any way.
|
||||
*
|
||||
* @param player
|
||||
* player to get original suffix of
|
||||
* @return player's original suffix
|
||||
* @see #setSuffix(TabPlayer, String)
|
||||
* @see #getCustomSuffix(TabPlayer)
|
||||
* @deprecated Use {@link #getOriginalRawSuffix(TabPlayer)} instead.
|
||||
*/
|
||||
@NotNull
|
||||
@Deprecated
|
||||
String getOriginalSuffix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns original prefix assigned by the plugin using internal logic.
|
||||
* @param player
|
||||
* Player to get original prefix of
|
||||
* @return Original prefix assigned by the plugin's internal logic.
|
||||
* @see #getCustomPrefix(TabPlayer)
|
||||
*/
|
||||
@NotNull
|
||||
String getOriginalRawPrefix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns original name assigned by the plugin using internal logic.
|
||||
* @param player
|
||||
* Player to get original name of
|
||||
* @return Original name assigned by the plugin's internal logic.
|
||||
* @see #getCustomName(TabPlayer)
|
||||
*/
|
||||
@NotNull
|
||||
String getOriginalRawName(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns original suffix assigned by the plugin using internal logic.
|
||||
* @param player
|
||||
* Player to get original suffix of
|
||||
* @return Original suffix assigned by the plugin's internal logic.
|
||||
* @see #getCustomSuffix(TabPlayer)
|
||||
*/
|
||||
@NotNull
|
||||
String getOriginalRawSuffix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns original prefix assigned by the plugin using internal logic with all placeholders replaced.
|
||||
* @param player
|
||||
* Player to get replaced original prefix of
|
||||
* @return Original prefix assigned by the plugin's internal logic.
|
||||
* @see #getCustomPrefix(TabPlayer)
|
||||
*/
|
||||
@NotNull
|
||||
String getOriginalReplacedPrefix(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns original name assigned by the plugin using internal logic with all placeholders replaced.
|
||||
* @param player
|
||||
* Player to get replaced original name of
|
||||
* @return Original name assigned by the plugin's internal logic.
|
||||
* @see #getCustomName(TabPlayer)
|
||||
*/
|
||||
@NotNull
|
||||
String getOriginalReplacedName(@NonNull TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns original suffix assigned by the plugin using internal logic with all placeholders replaced.
|
||||
* @param player
|
||||
* Player to get replaced original suffix of
|
||||
* @return Original suffix assigned by the plugin's internal logic.
|
||||
* @see #getCustomSuffix(TabPlayer)
|
||||
*/
|
||||
@NotNull
|
||||
String getOriginalReplacedSuffix(@NonNull TabPlayer player);
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package me.neznamy.tab.api.tablist.layout;
|
||||
|
||||
import lombok.NonNull;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Interface representing a layout.
|
||||
*/
|
||||
@SuppressWarnings("unused") // API class
|
||||
public interface Layout {
|
||||
|
||||
/**
|
||||
* Returns name of the layout.
|
||||
*
|
||||
* @return name of the layout
|
||||
*/
|
||||
@NotNull String getName();
|
||||
|
||||
/**
|
||||
* Adds fixed slot with specified parameters
|
||||
*
|
||||
* @param slot
|
||||
* Slot (1-80)
|
||||
* @param text
|
||||
* Text to display
|
||||
*/
|
||||
void addFixedSlot(int slot, @NonNull String text);
|
||||
|
||||
/**
|
||||
* Adds fixed slot with specified parameters
|
||||
*
|
||||
* @param slot
|
||||
* Slot (1-80)
|
||||
* @param text
|
||||
* Text to display
|
||||
* @param skin
|
||||
* Skin definition like in config
|
||||
*/
|
||||
void addFixedSlot(int slot, @NonNull String text, @NonNull String skin);
|
||||
|
||||
/**
|
||||
* Adds fixed slot with specified parameters
|
||||
*
|
||||
* @param slot
|
||||
* Slot (1-80)
|
||||
* @param text
|
||||
* Text to display
|
||||
* @param ping
|
||||
* Slot's ping
|
||||
*/
|
||||
void addFixedSlot(int slot, @NonNull String text, int ping);
|
||||
|
||||
/**
|
||||
* Adds fixed slot with specified parameters
|
||||
*
|
||||
* @param slot
|
||||
* Slot (1-80)
|
||||
* @param text
|
||||
* Text to display
|
||||
* @param skin
|
||||
* Skin definition like in config
|
||||
* @param ping
|
||||
* Slot's ping
|
||||
*/
|
||||
void addFixedSlot(int slot, @NonNull String text, @NonNull String skin, int ping);
|
||||
|
||||
/**
|
||||
* Adds fixed slot with specified parameters
|
||||
*
|
||||
* @param slot
|
||||
* Slot (1-80)
|
||||
* @param text
|
||||
* Text to display
|
||||
* @param skin
|
||||
* Skin definition like in config
|
||||
* @param ping
|
||||
* Slot's ping, accepts placeholders that evaluate to a number
|
||||
*/
|
||||
void addFixedSlot(int slot, @NonNull String text, @NonNull String skin, @NonNull String ping);
|
||||
|
||||
/**
|
||||
* Adds a player group.
|
||||
*
|
||||
* @param condition
|
||||
* Condition that must be met for player to appear in the group.
|
||||
* May be null for no requirement. Syntax is like in config -
|
||||
* either condition name or short format.
|
||||
* @param slots
|
||||
* Slots for this player group
|
||||
*/
|
||||
void addGroup(@Nullable String condition, int[] slots);
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package me.neznamy.tab.api.tablist.layout;
|
||||
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.tab.api.TabAPI;
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Interface for working with layouts. Instance can be obtained using
|
||||
* {@link TabAPI#getLayoutManager()}. If the feature is disabled in
|
||||
* config, it will return {@code null}.
|
||||
*/
|
||||
@SuppressWarnings("unused") // API class
|
||||
public interface LayoutManager {
|
||||
|
||||
/**
|
||||
* Creates new layout
|
||||
*
|
||||
* @param name
|
||||
* Unique layout name
|
||||
* @return Created layout
|
||||
*/
|
||||
@NotNull
|
||||
Layout createNewLayout(@NonNull String name);
|
||||
|
||||
/**
|
||||
* Creates new layout with given name and slot count (1.19.3+ only).
|
||||
*
|
||||
* @param name
|
||||
* Unique layout name
|
||||
* @param slotCount
|
||||
* Amount of slots to use for 1.19.3+ players
|
||||
* @return Created layout
|
||||
*/
|
||||
@NotNull
|
||||
Layout createNewLayout(@NonNull String name, int slotCount);
|
||||
|
||||
/**
|
||||
* Returns defined layout from config by name. If no such layout is defined in config,
|
||||
* {@code null} is returned.
|
||||
*
|
||||
* @param name
|
||||
* Name of layout defined in config
|
||||
* @return Layout defined in config by name or {@code null} if no such layout is defined
|
||||
*/
|
||||
@Nullable
|
||||
Layout getLayout(@NonNull String name);
|
||||
|
||||
/**
|
||||
* Sends layout to player. Set to {@code null} to make player not see
|
||||
* any layout, but default TabList instead.
|
||||
*
|
||||
* @param player
|
||||
* Player to send layout to
|
||||
* @param layout
|
||||
* Layout to send
|
||||
* @see #resetLayout(TabPlayer)
|
||||
*/
|
||||
void sendLayout(@NonNull TabPlayer player, @Nullable Layout layout);
|
||||
|
||||
/**
|
||||
* Reset layout back to original one based on configuration.
|
||||
*
|
||||
* @param player
|
||||
* Player to reset layout for
|
||||
* @see #sendLayout(TabPlayer, Layout)
|
||||
*/
|
||||
void resetLayout(@NonNull TabPlayer player);
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
package me.neznamy.tab.api.task;
|
||||
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import me.neznamy.tab.api.TabFeature;
|
||||
|
||||
/**
|
||||
* Manager for scheduling and executing tasks in TAB's
|
||||
* main thread to avoid concurrency issues.
|
||||
*/
|
||||
public interface ThreadManager {
|
||||
|
||||
/**
|
||||
* Starts a task in new thread and measures how long it took to process
|
||||
*
|
||||
* @param feature
|
||||
* feature to add cpu usage to
|
||||
* @param type
|
||||
* usage type to add cpu usage to
|
||||
* @param task
|
||||
* the task
|
||||
*/
|
||||
Future<Void> runMeasuredTask(TabFeature feature, String type, Runnable task);
|
||||
|
||||
/**
|
||||
* Starts a task in new thread and measures how long it took to process
|
||||
*
|
||||
* @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 feature, String type, Runnable task);
|
||||
|
||||
/**
|
||||
* Runs task in a new thread
|
||||
*
|
||||
* @param task
|
||||
* the task
|
||||
*/
|
||||
Future<Void> runTask(Runnable task);
|
||||
|
||||
/**
|
||||
* Starts a new task with defined repeat interval that measures cpu usage
|
||||
*
|
||||
* @param intervalMilliseconds
|
||||
* task interval
|
||||
* @param feature
|
||||
* feature to add cpu usage to
|
||||
* @param type
|
||||
* usage type to add cpu usage to
|
||||
* @param task
|
||||
* the task
|
||||
* @return Future representing the submitted task
|
||||
*/
|
||||
Future<?> startRepeatingMeasuredTask(int intervalMilliseconds, TabFeature feature, String type, Runnable task);
|
||||
|
||||
/**
|
||||
* Starts a new task with defined repeat interval
|
||||
*
|
||||
* @param intervalMilliseconds
|
||||
* task interval
|
||||
* @param task
|
||||
* the task
|
||||
* @return Future representing the submitted task
|
||||
*/
|
||||
Future<?> startRepeatingTask(int intervalMilliseconds, Runnable task);
|
||||
|
||||
/**
|
||||
* Runs task with a delay and measures how long it took to process
|
||||
*
|
||||
* @param delayMilliseconds
|
||||
* how long to run the task after
|
||||
* @param feature
|
||||
* feature to add cpu usage to
|
||||
* @param type
|
||||
* usage type to add cpu usage to
|
||||
* @param task
|
||||
* the task
|
||||
* @return Future representing the submitted task
|
||||
*/
|
||||
Future<?> runTaskLater(int delayMilliseconds, TabFeature feature, String type, Runnable task);
|
||||
|
||||
/**
|
||||
* Runs task with a delay
|
||||
*
|
||||
* @param delayMilliseconds
|
||||
* how long to run the task after
|
||||
* @param task
|
||||
* the task
|
||||
* @return Future representing the submitted task
|
||||
*/
|
||||
Future<?> runTaskLater(int delayMilliseconds, Runnable task);
|
||||
}
|
||||
@@ -1,182 +0,0 @@
|
||||
package me.neznamy.tab.api.team;
|
||||
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
|
||||
public interface TeamManager {
|
||||
|
||||
/**
|
||||
* Makes player's NameTag globally invisible
|
||||
*
|
||||
* @param player
|
||||
* player to hide nametag of
|
||||
* @see #showNametag(TabPlayer)
|
||||
* @see #hasHiddenNametag(TabPlayer)
|
||||
*/
|
||||
void hideNametag(TabPlayer player);
|
||||
|
||||
/**
|
||||
* Hides player's NameTag for specified player until it's shown again
|
||||
*
|
||||
* @param player
|
||||
* player to hide nametag of
|
||||
* @param viewer
|
||||
* player to hide NameTag for
|
||||
*/
|
||||
void hideNametag(TabPlayer player, TabPlayer viewer);
|
||||
|
||||
/**
|
||||
* Makes player's NameTag visible again
|
||||
*
|
||||
* @param player
|
||||
* player to show nametag of
|
||||
* @see #hideNametag(TabPlayer)
|
||||
* @see #hasHiddenNametag(TabPlayer)
|
||||
*/
|
||||
void showNametag(TabPlayer player);
|
||||
|
||||
/**
|
||||
* Shows player's NameTag for specified viewer if it was hidden before
|
||||
*
|
||||
* @param player
|
||||
* player to show nametag of
|
||||
* @param viewer
|
||||
* player to show NameTag back for
|
||||
*/
|
||||
void showNametag(TabPlayer player, TabPlayer viewer);
|
||||
|
||||
/**
|
||||
* Return whether player has hidden NameTag or not
|
||||
*
|
||||
* @param player
|
||||
* player to check nametag visibility status of
|
||||
* @return Whether player has hidden NameTag or not
|
||||
* @see #hideNametag(TabPlayer)
|
||||
* @see #showNametag(TabPlayer)
|
||||
*/
|
||||
boolean hasHiddenNametag(TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns true if NameTag is hidden for specified viewer, false if not
|
||||
*
|
||||
* @param player
|
||||
* player to check visibility status of
|
||||
* @param viewer
|
||||
* player to check visibility status for
|
||||
* @return true if hidden, false if not
|
||||
*/
|
||||
boolean hasHiddenNametag(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.
|
||||
*
|
||||
* @param player
|
||||
* player to pause team handling of
|
||||
*/
|
||||
void pauseTeamHandling(TabPlayer player);
|
||||
|
||||
/**
|
||||
* Resumes team handling if it was before paused using pauseTeamHandling(), if not, nothing happens
|
||||
*
|
||||
* @param player
|
||||
* player to resume team handling of
|
||||
*/
|
||||
void resumeTeamHandling(TabPlayer player);
|
||||
|
||||
/**
|
||||
* Returns true if team handling is paused for this player using pauseTeamHandling(), false if not, or
|
||||
* it was resumed already using resumeTeamHandling
|
||||
*
|
||||
* @param player
|
||||
* player to check handling status of
|
||||
* @return true if paused, false if not
|
||||
*/
|
||||
boolean hasTeamHandlingPaused(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 player
|
||||
* player to set team name of
|
||||
* @param teamName
|
||||
* forced team name
|
||||
*/
|
||||
void forceTeamName(TabPlayer player, String teamName);
|
||||
|
||||
/**
|
||||
* Returns forced team name of player or null if not forced
|
||||
*
|
||||
* @param player
|
||||
* player to check forced team name of
|
||||
* @return forced team name of player or null if not forced
|
||||
*/
|
||||
String getForcedTeamName(TabPlayer player);
|
||||
|
||||
|
||||
/**
|
||||
* Forces collision rule for the player. Setting it to null will remove forced value
|
||||
*
|
||||
* @param player
|
||||
* player to set collision rule of
|
||||
* @param collision
|
||||
* forced collision rule
|
||||
*/
|
||||
void setCollisionRule(TabPlayer player, Boolean collision);
|
||||
|
||||
/**
|
||||
* Returns forced collision rule or null if collision is not forced using setCollisionRule
|
||||
*
|
||||
* @param player
|
||||
* player to get forced collision of
|
||||
* @return forced value or null if not forced
|
||||
*/
|
||||
Boolean getCollisionRule(TabPlayer player);
|
||||
|
||||
/**
|
||||
* Sends update team's properties packet of player's team to everyone
|
||||
*
|
||||
* @param player
|
||||
* player to update team data of
|
||||
*/
|
||||
void updateTeamData(TabPlayer player);
|
||||
|
||||
void setPrefix(TabPlayer player, String prefix);
|
||||
|
||||
void setSuffix(TabPlayer player, String suffix);
|
||||
|
||||
void resetPrefix(TabPlayer player);
|
||||
|
||||
void resetSuffix(TabPlayer player);
|
||||
|
||||
String getCustomPrefix(TabPlayer player);
|
||||
|
||||
String getCustomSuffix(TabPlayer player);
|
||||
|
||||
String getOriginalPrefix(TabPlayer player);
|
||||
|
||||
String getOriginalSuffix(TabPlayer player);
|
||||
|
||||
/**
|
||||
* Toggles nametag visibility view on all players for specified player.
|
||||
* On first call, nametags of all players will become invisible for specified
|
||||
* player. On second call, they will become visible again.
|
||||
*
|
||||
* @param player
|
||||
* player to toggle nametag visibility view for
|
||||
* @param sendToggleMessage
|
||||
* {@code true} if configured toggle message should be sent, {@code false} if not
|
||||
*/
|
||||
void toggleNameTagVisibilityView(TabPlayer player, boolean sendToggleMessage);
|
||||
|
||||
/**
|
||||
* Returns {@code true} if player has hidden nametags by either calling
|
||||
* {@link #toggleNameTagVisibilityView(TabPlayer, boolean)} or using a command,
|
||||
* {@code false} if not.
|
||||
*
|
||||
* @param player
|
||||
* player to check
|
||||
* @return {@code true} if hidden, {@code false} if not
|
||||
*/
|
||||
boolean hasHiddenNameTagVisibilityView(TabPlayer player);
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package me.neznamy.tab.api.team;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
|
||||
public interface UnlimitedNametagManager extends TeamManager {
|
||||
|
||||
void disableArmorStands(TabPlayer player);
|
||||
|
||||
void enableArmorStands(TabPlayer player);
|
||||
|
||||
boolean hasDisabledArmorStands(TabPlayer player);
|
||||
|
||||
void setName(TabPlayer player, String customName);
|
||||
|
||||
void setLine(TabPlayer player, String line, String value);
|
||||
|
||||
void resetName(TabPlayer player);
|
||||
|
||||
void resetLine(TabPlayer player, String line);
|
||||
|
||||
String getCustomName(TabPlayer player);
|
||||
|
||||
String getCustomLineValue(TabPlayer player, String line);
|
||||
|
||||
String getOriginalName(TabPlayer player);
|
||||
|
||||
String getOriginalLineValue(TabPlayer player, String line);
|
||||
|
||||
List<String> getDefinedLines();
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package me.neznamy.tab.api.util;
|
||||
|
||||
/**
|
||||
* An interface for BiFunction which can throw an exception.
|
||||
* Used in {@link me.neznamy.tab.api.protocol.PacketBuilder} to
|
||||
* call build method for packet classes, which may throw an
|
||||
* exception due to reflection.
|
||||
* @param <A>
|
||||
* First function argument
|
||||
* @param <B>
|
||||
* Second function argument
|
||||
* @param <C>
|
||||
* Function return type
|
||||
*/
|
||||
public interface BiFunctionWithException<A, B, C> {
|
||||
|
||||
/**
|
||||
* Runs the function and returns the result
|
||||
*
|
||||
* @param a
|
||||
* First argument
|
||||
* @param b
|
||||
* Second argument
|
||||
* @return Output from function
|
||||
* @throws ReflectiveOperationException
|
||||
* If reflective operation fails
|
||||
*/
|
||||
C apply(A a, B b) throws ReflectiveOperationException;
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
package me.neznamy.tab.api.util;
|
||||
|
||||
import me.neznamy.tab.api.TabPlayer;
|
||||
|
||||
/**
|
||||
* Class with utility methods used in the plugin
|
||||
*/
|
||||
public class Preconditions {
|
||||
|
||||
/**
|
||||
* Private constructor preventing the class from being instantiated
|
||||
*/
|
||||
private Preconditions() {}
|
||||
|
||||
/**
|
||||
* Checks object and throws {@code IllegalArgumentException} if it is {@code null}.
|
||||
*
|
||||
* @param obj
|
||||
* Object to check
|
||||
* @param name
|
||||
* Name of the variable to use in exception message
|
||||
* @throws IllegalArgumentException
|
||||
* if {@code obj} is {@code null}
|
||||
*/
|
||||
public static void checkNotNull(Object obj, String name) {
|
||||
if (obj == null) throw new IllegalArgumentException(name + " cannot be null");
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks length of String and throws {@code IllegalArgumentException} if it is
|
||||
* longer than limit.
|
||||
*
|
||||
* @param string
|
||||
* String to check
|
||||
* @param maxLength
|
||||
* Maximum length of the string
|
||||
* @param name
|
||||
* Name of the variable to use in exception message
|
||||
* @throws IllegalArgumentException
|
||||
* if {@code string} is {@code null} or longer than {@code maxLength} characters
|
||||
*/
|
||||
public static void checkMaxLength(String string, int maxLength, String name) {
|
||||
checkNotNull(string, name);
|
||||
if (string.length() > maxLength) throw new IllegalArgumentException(name + " is longer than " + maxLength + " characters (" + string.length() + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks number range and throws {@code IllegalArgumentException} if number
|
||||
* is out of range.
|
||||
*
|
||||
* @param number
|
||||
* Number to check
|
||||
* @param min
|
||||
* Minimum allowed value
|
||||
* @param max
|
||||
* Maximum allowed value
|
||||
* @param variable
|
||||
* Variable name to use in exception message
|
||||
* @throws IllegalArgumentException
|
||||
* if {@code number} is out of range ({@code number < min || number > max})
|
||||
*/
|
||||
public static void checkRange(Number number, Number min, Number max, String variable) {
|
||||
if (number.doubleValue() < min.doubleValue() || number.doubleValue() > max.doubleValue())
|
||||
throw new IllegalArgumentException(variable + " index out of range (" + min + " - " + max + "), was " + number);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if player is loaded and throws {@code IllegalStateException} if not.
|
||||
*
|
||||
* @param player
|
||||
* Player to check
|
||||
* @throws IllegalStateException
|
||||
* If player is not loaded
|
||||
*/
|
||||
public static void checkLoaded(TabPlayer player) {
|
||||
if (!player.isLoaded()) throw new IllegalStateException("Player is not loaded yet. Try again later.");
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package me.neznamy.tab.api.util;
|
||||
|
||||
/**
|
||||
* Supplier that can throw an exception
|
||||
*
|
||||
* @param <T>
|
||||
* Return class type
|
||||
*/
|
||||
public interface SupplierWithException<T> {
|
||||
|
||||
T get() throws Exception;
|
||||
}
|
||||
@@ -3,15 +3,6 @@ plugins {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(libs.plugin.indra)
|
||||
implementation(libs.plugin.shadow)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(files(libs::class.java.protectionDomain.codeSource.location))
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
implementation("com.gradleup.shadow:shadow-gradle-plugin:9.4.0")
|
||||
implementation("io.freefair.gradle:lombok-plugin:9.2.0")
|
||||
}
|
||||
@@ -2,15 +2,11 @@ rootProject.name = "build-logic"
|
||||
|
||||
dependencyResolutionManagement {
|
||||
repositories {
|
||||
maven("https://maven.fabricmc.net/")
|
||||
maven("https://maven.architectury.dev/")
|
||||
maven("https://maven.minecraftforge.net/")
|
||||
maven("https://maven.neoforged.net/releases/")
|
||||
gradlePluginPortal()
|
||||
mavenCentral()
|
||||
}
|
||||
// You're a great IDE IntelliJ, but sometimes you really annoy me. >:(
|
||||
// repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||
|
||||
versionCatalogs {
|
||||
register("libs") {
|
||||
from(files("../gradle/libs.versions.toml"))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,19 @@
|
||||
import org.apache.tools.ant.filters.ReplaceTokens
|
||||
|
||||
plugins {
|
||||
id("net.kyori.indra")
|
||||
}
|
||||
|
||||
indra {
|
||||
javaVersions {
|
||||
target(8)
|
||||
}
|
||||
github("NEZNAMY", "TAB") {
|
||||
ci(true)
|
||||
}
|
||||
`java-library`
|
||||
id("io.freefair.lombok")
|
||||
}
|
||||
|
||||
tasks {
|
||||
processResources {
|
||||
filter<ReplaceTokens>("tokens" to mapOf(
|
||||
"id" to rootProject.ext.get("id")!!.toString(),
|
||||
"name" to rootProject.name,
|
||||
"version" to project.version,
|
||||
"description" to project.description
|
||||
"description" to project.description,
|
||||
"website" to rootProject.ext.get("website")!!.toString(),
|
||||
"author" to rootProject.ext.get("author")!!.toString()
|
||||
))
|
||||
}
|
||||
javadoc {
|
||||
@@ -27,4 +22,16 @@ tasks {
|
||||
options.encoding = Charsets.UTF_8.name()
|
||||
(options as StandardJavadocDocletOptions).addStringOption("Xdoclint:none", "-quiet")
|
||||
}
|
||||
compileJava {
|
||||
options.encoding = Charsets.UTF_8.name()
|
||||
options.release.set(17)
|
||||
options.compilerArgs.addAll(listOf("-nowarn", "-Xlint:-unchecked", "-Xlint:-deprecation"))
|
||||
}
|
||||
}
|
||||
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion.set(JavaLanguageVersion.of(17))
|
||||
vendor.set(JvmVendorSpec.GRAAL_VM)
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,26 @@
|
||||
plugins {
|
||||
id("tab.standard-conventions")
|
||||
id("com.github.johnrengelman.shadow")
|
||||
id("com.gradleup.shadow")
|
||||
}
|
||||
|
||||
tasks.withType<Zip>().configureEach {
|
||||
isZip64 = true
|
||||
}
|
||||
|
||||
tasks {
|
||||
shadowJar {
|
||||
archiveFileName.set("TAB-${project.name}-${project.version}.jar")
|
||||
archiveFileName.set("${rootProject.name}-${project.name}-${project.version}.jar")
|
||||
relocate("org.bstats", "me.neznamy.tab.libs.org.bstats")
|
||||
relocate("org.json.simple", "me.neznamy.tab.libs.org.json.simple")
|
||||
relocate("net.kyori.event", "me.neznamy.tab.libs.net.kyori.event")
|
||||
relocate("me.neznamy.yamlassist", "me.neznamy.tab.libs.me.neznamy.yamlassist")
|
||||
relocate("org.yaml.snakeyaml", "me.neznamy.tab.libs.org.yaml.snakeyaml")
|
||||
relocate("redis.clients.jedis", "me.neznamy.tab.libs.redis.clients.jedis")
|
||||
relocate("org.apache.commons.pool2", "me.neznamy.tab.libs.org.apache.commons.pool2")
|
||||
relocate("org.json", "me.neznamy.tab.libs.org.json")
|
||||
relocate("com.rabbitmq", "me.neznamy.tab.libs.com.rabbitmq")
|
||||
relocate("com.saicone.delivery4j", "me.neznamy.tab.libs.com.saicone.delivery4j")
|
||||
relocate("com.mysql", "me.neznamy.tab.libs.com.mysql")
|
||||
relocate("com.google.protobuf", "me.neznamy.tab.libs.com.google.protobuf")
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,8 @@
|
||||
plugins {
|
||||
id("tab.base-conventions")
|
||||
id("net.kyori.indra.publishing")
|
||||
}
|
||||
|
||||
indra {
|
||||
publishReleasesTo("krypton", "https://repo.kryptonmc.org/releases")
|
||||
publishSnapshotsTo("krypton", "https://repo.kryptonmc.org/snapshots")
|
||||
configurePublications {
|
||||
artifactId = "tab-$artifactId"
|
||||
}
|
||||
}
|
||||
java {
|
||||
withSourcesJar()
|
||||
withJavadocJar()
|
||||
}
|
||||
+30
-14
@@ -1,29 +1,45 @@
|
||||
plugins {
|
||||
eclipse
|
||||
id("tab.parent")
|
||||
}
|
||||
|
||||
allprojects {
|
||||
group = "me.neznamy"
|
||||
version = property("projectVersion") as String // from gradle.properties
|
||||
version = "5.9.9"
|
||||
description = "An all-in-one solution that works"
|
||||
|
||||
ext.set("id", "tab")
|
||||
ext.set("website", "https://git.trueog.net/trueog/TAB-OG")
|
||||
ext.set("author", "NEZNAMY")
|
||||
ext.set("credits", "Joseph T. McQuigg (JT122406)")
|
||||
}
|
||||
|
||||
val platforms = setOf(
|
||||
projects.bukkit,
|
||||
projects.bungeecord,
|
||||
// projects.krypton,
|
||||
projects.velocity
|
||||
).map { it.dependencyProject }
|
||||
val platformPaths = setOf(
|
||||
":bukkit",
|
||||
":bukkit:v1_19_R3",
|
||||
":bungeecord",
|
||||
":velocity"
|
||||
)
|
||||
|
||||
val special = setOf(
|
||||
projects.api,
|
||||
projects.shared
|
||||
).map { it.dependencyProject }
|
||||
val specialPaths = setOf(
|
||||
":api",
|
||||
":shared"
|
||||
)
|
||||
|
||||
subprojects {
|
||||
when (this) {
|
||||
in platforms -> plugins.apply("tab.platform-conventions")
|
||||
in special -> plugins.apply("tab.standard-conventions")
|
||||
when (path) {
|
||||
in platformPaths -> plugins.apply("tab.platform-conventions")
|
||||
in specialPaths -> plugins.apply("tab.standard-conventions")
|
||||
else -> plugins.apply("tab.base-conventions")
|
||||
}
|
||||
}
|
||||
|
||||
val copyShadowJar by tasks.registering(Copy::class) {
|
||||
dependsOn(":jar:shadowJar")
|
||||
from(project(":jar").tasks.named("shadowJar"))
|
||||
into(layout.buildDirectory.dir("libs"))
|
||||
}
|
||||
|
||||
tasks.register("build") {
|
||||
dependsOn(copyShadowJar)
|
||||
}
|
||||
+10
-8
@@ -1,12 +1,14 @@
|
||||
dependencies {
|
||||
implementation(projects.shared)
|
||||
implementation(libs.bstats.bukkit)
|
||||
compileOnly(libs.bukkit)
|
||||
compileOnly(libs.placeholderapi)
|
||||
compileOnly(libs.vault)
|
||||
compileOnly(libs.via)
|
||||
compileOnly(libs.authlib)
|
||||
compileOnly(libs.essentials) {
|
||||
api(projects.shared)
|
||||
implementation("org.bstats:bstats-bukkit:3.1.0")
|
||||
compileOnly("org.purpurmc.purpur:purpur-api:1.19.4-R0.1-SNAPSHOT")
|
||||
compileOnly("me.clip:placeholderapi:2.11.6")
|
||||
compileOnly("LibsDisguises:LibsDisguises:10.0.21") {
|
||||
exclude("org.spigotmc", "spigot")
|
||||
exclude("org.spigotmc", "spigot-api")
|
||||
exclude("com.github.dmulloy2", "ProtocolLib")
|
||||
exclude("org.ow2.asm", "asm")
|
||||
exclude("net.md-5", "bungeecord-chat")
|
||||
}
|
||||
compileOnly("com.github.LeonMangler:PremiumVanishAPI:2.8.8")
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
plugins {
|
||||
id("io.papermc.paperweight.userdev") version "2.0.0-beta.19"
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven("https://jitpack.io") // YamlAssist
|
||||
maven("https://repo.opencollab.dev/maven-snapshots/")
|
||||
maven("https://repo.viaversion.com/")
|
||||
maven {
|
||||
name = "luck-repo"
|
||||
url = uri("https://repo.lucko.me/")
|
||||
content {
|
||||
includeModule("me.lucko", "spark-api")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val version = "1.20.6-R0.1-SNAPSHOT" // 1.20.5 has a broken dependency, but there were no changes, so it's ok
|
||||
|
||||
dependencies {
|
||||
implementation(projects.bukkit)
|
||||
paperweight.paperDevBundle(version)
|
||||
compileOnly("io.papermc.paper:paper-api:${version}")
|
||||
}
|
||||
|
||||
tasks.compileJava {
|
||||
options.release.set(21)
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
package me.neznamy.tab.platforms.bukkit.paper_1_20_5;
|
||||
|
||||
import me.neznamy.tab.shared.chat.TabStyle;
|
||||
import me.neznamy.tab.shared.chat.component.object.TabAtlasSprite;
|
||||
import me.neznamy.tab.shared.chat.component.object.TabObjectComponent;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ComponentConverter;
|
||||
import me.neznamy.tab.shared.chat.component.object.TabPlayerSprite;
|
||||
import net.minecraft.network.chat.*;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Component converter using direct mojang-mapped code.
|
||||
*/
|
||||
public class NMSComponentConverter extends ComponentConverter<Component> {
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Component newTextComponent(@NotNull String text) {
|
||||
return Component.literal(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Component newTranslatableComponent(@NotNull String key) {
|
||||
return Component.translatable(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Component newKeybindComponent(@NotNull String keybind) {
|
||||
return Component.keybind(keybind);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Component newObjectComponent(@NotNull TabAtlasSprite sprite) {
|
||||
return Component.literal(TabObjectComponent.ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Component newObjectComponent(@NotNull TabPlayerSprite sprite) {
|
||||
return Component.literal(TabObjectComponent.ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyStyle(@NotNull Component nmsComponent, @NotNull TabStyle modifier) {
|
||||
Style style = Style.EMPTY
|
||||
.withColor(modifier.getColor() == null ? null : TextColor.fromRgb(modifier.getColor().getRgb()))
|
||||
.withBold(modifier.getBold())
|
||||
.withItalic(modifier.getItalic())
|
||||
.withUnderlined(modifier.getUnderlined())
|
||||
.withStrikethrough(modifier.getStrikethrough())
|
||||
.withObfuscated(modifier.getObfuscated())
|
||||
.withFont(modifier.getFont() == null ? null : ResourceLocation.tryParse(modifier.getFont()));
|
||||
((MutableComponent)nmsComponent).setStyle(style);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSibling(@NotNull Component parent, @NotNull Component child) {
|
||||
((MutableComponent)parent).append(child);
|
||||
}
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
package me.neznamy.tab.platforms.bukkit.paper_1_20_5;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.Getter;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ComponentConverter;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ImplementationProvider;
|
||||
import me.neznamy.tab.shared.platform.Scoreboard;
|
||||
import me.neznamy.tab.shared.platform.TabList;
|
||||
import me.neznamy.tab.shared.platform.TabListEntryTracker;
|
||||
import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Implementation provider using direct Mojang-mapped NMS code for paper 1.20.5 - 1.21.1.
|
||||
*/
|
||||
@Getter
|
||||
public class NMSImplementationProvider implements ImplementationProvider {
|
||||
|
||||
@NotNull
|
||||
private final ComponentConverter<?> componentConverter = new NMSComponentConverter();
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Scoreboard newScoreboard(@NotNull BukkitTabPlayer player) {
|
||||
return new NMSPacketScoreboard(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public TabList newTabList(@NotNull BukkitTabPlayer player) {
|
||||
return new NMSPacketTabList(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Channel getChannel(@NotNull Player player) {
|
||||
return ((CraftPlayer)player).getHandle().connection.connection.channel;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public TabListEntryTracker newTabListEntryTracker() {
|
||||
return new NMSTabListEntryTracker();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPing(@NotNull BukkitTabPlayer player) {
|
||||
return player.getPlayer().getPing();
|
||||
}
|
||||
}
|
||||
+176
@@ -0,0 +1,176 @@
|
||||
package me.neznamy.tab.platforms.bukkit.paper_1_20_5;
|
||||
|
||||
import lombok.NonNull;
|
||||
import lombok.SneakyThrows;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.platform.decorators.SafeScoreboard;
|
||||
import me.neznamy.tab.shared.util.ReflectionUtils;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.network.chat.numbers.FixedFormat;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.protocol.game.*;
|
||||
import net.minecraft.world.scores.PlayerTeam;
|
||||
import net.minecraft.world.scores.Scoreboard;
|
||||
import net.minecraft.world.scores.criteria.ObjectiveCriteria;
|
||||
import net.minecraft.world.scores.criteria.ObjectiveCriteria.RenderType;
|
||||
import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Scoreboard implementation using direct mojang-mapped code.
|
||||
*/
|
||||
public class NMSPacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
|
||||
private static final ChatFormatting[] formats = ChatFormatting.values();
|
||||
private static final net.minecraft.world.scores.Team.CollisionRule[] collisions = net.minecraft.world.scores.Team.CollisionRule.values();
|
||||
private static final net.minecraft.world.scores.Team.Visibility[] visibilities = net.minecraft.world.scores.Team.Visibility.values();
|
||||
private static final Scoreboard dummyScoreboard = new Scoreboard();
|
||||
private static final Field players = ReflectionUtils.getOnlyField(ClientboundSetPlayerTeamPacket.class, Collection.class);
|
||||
|
||||
/**
|
||||
* Constructs new instance with given player.
|
||||
*
|
||||
* @param player
|
||||
* Player this scoreboard will belong to
|
||||
*/
|
||||
public NMSPacketScoreboard(@NotNull BukkitTabPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerObjective(@NonNull Objective objective) {
|
||||
net.minecraft.world.scores.Objective obj = new net.minecraft.world.scores.Objective(
|
||||
dummyScoreboard,
|
||||
objective.getName(),
|
||||
ObjectiveCriteria.DUMMY,
|
||||
objective.getTitle().convert(),
|
||||
RenderType.values()[objective.getHealthDisplay().ordinal()],
|
||||
false,
|
||||
objective.getNumberFormat() == null ? null : objective.getNumberFormat().toFixedFormat(FixedFormat::new)
|
||||
);
|
||||
objective.setPlatformObjective(obj);
|
||||
sendPacket(new ClientboundSetObjectivePacket(obj, ObjectiveAction.REGISTER));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDisplaySlot(@NonNull Objective objective) {
|
||||
sendPacket(new ClientboundSetDisplayObjectivePacket(
|
||||
net.minecraft.world.scores.DisplaySlot.values()[objective.getDisplaySlot().ordinal()],
|
||||
(net.minecraft.world.scores.Objective) objective.getPlatformObjective()
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterObjective(@NonNull Objective objective) {
|
||||
sendPacket(new ClientboundSetObjectivePacket((net.minecraft.world.scores.Objective) objective.getPlatformObjective(), ObjectiveAction.UNREGISTER));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateObjective(@NonNull Objective objective) {
|
||||
net.minecraft.world.scores.Objective obj = (net.minecraft.world.scores.Objective) objective.getPlatformObjective();
|
||||
obj.setDisplayName(objective.getTitle().convert());
|
||||
obj.setRenderType(RenderType.values()[objective.getHealthDisplay().ordinal()]);
|
||||
sendPacket(new ClientboundSetObjectivePacket(obj, ObjectiveAction.UPDATE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScore(@NonNull Score score) {
|
||||
sendPacket(new ClientboundSetScorePacket(
|
||||
score.getHolder(),
|
||||
score.getObjective().getName(),
|
||||
score.getValue(),
|
||||
Optional.ofNullable(score.getDisplayName() == null ? null : score.getDisplayName().convert()),
|
||||
Optional.ofNullable(score.getNumberFormat() == null ? null : score.getNumberFormat().toFixedFormat(FixedFormat::new))
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeScore(@NonNull Score score) {
|
||||
sendPacket(new ClientboundResetScorePacket(score.getHolder(), score.getObjective().getName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Object createTeam(@NonNull String name) {
|
||||
return new PlayerTeam(dummyScoreboard, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerTeam(@NonNull Team team) {
|
||||
updateTeamProperties(team);
|
||||
PlayerTeam t = (PlayerTeam) team.getPlatformTeam();
|
||||
t.getPlayers().addAll(team.getPlayers());
|
||||
sendPacket(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(t, true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterTeam(@NonNull Team team) {
|
||||
sendPacket(ClientboundSetPlayerTeamPacket.createRemovePacket((PlayerTeam) team.getPlatformTeam()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTeam(@NonNull Team team) {
|
||||
updateTeamProperties(team);
|
||||
sendPacket(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket((PlayerTeam) team.getPlatformTeam(), false));
|
||||
}
|
||||
|
||||
private void updateTeamProperties(@NonNull Team team) {
|
||||
PlayerTeam t = (PlayerTeam) team.getPlatformTeam();
|
||||
t.setAllowFriendlyFire((team.getOptions() & 0x01) != 0);
|
||||
t.setSeeFriendlyInvisibles((team.getOptions() & 0x02) != 0);
|
||||
t.setColor(formats[team.getColor().ordinal()]);
|
||||
t.setCollisionRule(collisions[team.getCollision().ordinal()]);
|
||||
t.setNameTagVisibility(visibilities[team.getVisibility().ordinal()]);
|
||||
t.setPlayerPrefix(team.getPrefix().convert());
|
||||
t.setPlayerSuffix(team.getSuffix().convert());
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
@NotNull
|
||||
public Object onPacketSend(@NonNull Object packet) {
|
||||
if (packet instanceof ClientboundSetDisplayObjectivePacket display) {
|
||||
TAB.getInstance().getFeatureManager().onDisplayObjective(player, display.getSlot().ordinal(), display.getObjectiveName());
|
||||
}
|
||||
if (packet instanceof ClientboundSetObjectivePacket objective) {
|
||||
TAB.getInstance().getFeatureManager().onObjective(player, objective.getMethod(), objective.getObjectiveName());
|
||||
}
|
||||
if (packet instanceof ClientboundSetPlayerTeamPacket team) {
|
||||
int action = getMethod(team);
|
||||
if (action != TeamAction.UPDATE) {
|
||||
players.set(team, onTeamPacket(action, team.getName(), team.getPlayers() == null ? Collections.emptyList() : team.getPlayers()));
|
||||
}
|
||||
}
|
||||
return packet;
|
||||
}
|
||||
|
||||
private int getMethod(@NonNull ClientboundSetPlayerTeamPacket team) {
|
||||
if (team.getTeamAction() == ClientboundSetPlayerTeamPacket.Action.ADD) {
|
||||
return 0;
|
||||
} else if (team.getTeamAction() == ClientboundSetPlayerTeamPacket.Action.REMOVE) {
|
||||
return 1;
|
||||
} else if (team.getPlayerAction() == ClientboundSetPlayerTeamPacket.Action.ADD) {
|
||||
return 3;
|
||||
} else if (team.getPlayerAction() == ClientboundSetPlayerTeamPacket.Action.REMOVE) {
|
||||
return 4;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the packet to the player.
|
||||
*
|
||||
* @param packet
|
||||
* Packet to send
|
||||
*/
|
||||
private void sendPacket(@NotNull Packet<?> packet) {
|
||||
((CraftPlayer)player.getPlayer()).getHandle().connection.sendPacket(packet);
|
||||
}
|
||||
}
|
||||
+200
@@ -0,0 +1,200 @@
|
||||
package me.neznamy.tab.platforms.bukkit.paper_1_20_5;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.chat.component.TabComponent;
|
||||
import me.neznamy.tab.shared.platform.TabList;
|
||||
import me.neznamy.tab.shared.platform.decorators.TrackedTabList;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundTabListPacket;
|
||||
import net.minecraft.world.level.GameType;
|
||||
import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* TabList implementation using direct mojang-mapped code.
|
||||
*/
|
||||
public class NMSPacketTabList extends TrackedTabList<BukkitTabPlayer> {
|
||||
|
||||
private static final EnumSet<ClientboundPlayerInfoUpdatePacket.Action> addPlayer = EnumSet.allOf(ClientboundPlayerInfoUpdatePacket.Action.class);
|
||||
private static final EnumSet<ClientboundPlayerInfoUpdatePacket.Action> updateDisplayName = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME);
|
||||
private static final EnumSet<ClientboundPlayerInfoUpdatePacket.Action> updateLatency = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY);
|
||||
private static final EnumSet<ClientboundPlayerInfoUpdatePacket.Action> updateGameMode = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE);
|
||||
private static final EnumSet<ClientboundPlayerInfoUpdatePacket.Action> updateListed = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LISTED);
|
||||
|
||||
/**
|
||||
* Constructs new instance.
|
||||
*
|
||||
* @param player
|
||||
* Player this tablist will belong to
|
||||
*/
|
||||
public NMSPacketTabList(@NotNull BukkitTabPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeEntry(@NonNull UUID entry) {
|
||||
sendPacket(new ClientboundPlayerInfoRemovePacket(Collections.singletonList(entry)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDisplayName0(@NonNull UUID entry, @Nullable TabComponent displayName) {
|
||||
sendPacket(updateDisplayName, entry, "", null, false, 0, 0, displayName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLatency(@NonNull UUID entry, int latency) {
|
||||
sendPacket(updateLatency, entry, "", null, false, latency, 0, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateGameMode(@NonNull UUID entry, int gameMode) {
|
||||
sendPacket(updateGameMode, entry, "", null, false, 0, gameMode, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateListed(@NonNull UUID entry, boolean listed) {
|
||||
sendPacket(updateListed, entry, "", null, listed, 0, 0, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateListOrder(@NonNull UUID entry, int listOrder) {
|
||||
// Added in 1.21.2
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateHat(@NonNull UUID entry, boolean showHat) {
|
||||
// Added in 1.21.4
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEntry0(@NonNull Entry entry) {
|
||||
sendPacket(addPlayer, entry.getUniqueId(), entry.getName(), entry.getSkin(), entry.isListed(), entry.getLatency(),
|
||||
entry.getGameMode(), entry.getDisplayName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerListHeaderFooter0(@NonNull TabComponent header, @NonNull TabComponent footer) {
|
||||
sendPacket(new ClientboundTabListPacket(header.convert(), footer.convert()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Skin getSkin() {
|
||||
Collection<Property> properties = ((CraftPlayer)player.getPlayer()).getProfile().getProperties().get(TEXTURES_PROPERTY);
|
||||
if (properties.isEmpty()) return null; // Offline mode
|
||||
Property property = properties.iterator().next();
|
||||
return new Skin(property.value(), property.signature());
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Object onPacketSend(@NonNull Object packet) {
|
||||
if (packet instanceof ClientboundTabListPacket tablist) {
|
||||
if (header == null || footer == null) return packet;
|
||||
if (tablist.header() != header.convert() || tablist.footer() != footer.convert()) {
|
||||
return new ClientboundTabListPacket(header.convert(), footer.convert());
|
||||
}
|
||||
}
|
||||
if (packet instanceof ClientboundPlayerInfoUpdatePacket info) {
|
||||
EnumSet<ClientboundPlayerInfoUpdatePacket.Action> actions = info.actions();
|
||||
List<ClientboundPlayerInfoUpdatePacket.Entry> updatedList = new ArrayList<>();
|
||||
boolean rewritePacket = false;
|
||||
for (ClientboundPlayerInfoUpdatePacket.Entry nmsData : info.entries()) {
|
||||
boolean rewriteEntry = false;
|
||||
Component displayName = nmsData.displayName();
|
||||
int latency = nmsData.latency();
|
||||
int gameMode = nmsData.gameMode().getId();
|
||||
boolean listed = nmsData.listed();
|
||||
if (actions.contains(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME)) {
|
||||
TabComponent forcedDisplayName = getForcedDisplayNames().get(nmsData.profileId());
|
||||
if (forcedDisplayName != null && forcedDisplayName.convert() != displayName) {
|
||||
displayName = forcedDisplayName.convert();
|
||||
rewriteEntry = rewritePacket = true;
|
||||
}
|
||||
}
|
||||
if (actions.contains(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE)) {
|
||||
if (getBlockedSpectators().contains(nmsData.profileId()) && gameMode == 3) {
|
||||
gameMode = 0;
|
||||
rewriteEntry = rewritePacket = true;
|
||||
}
|
||||
}
|
||||
if (actions.contains(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY)) {
|
||||
if (getForcedLatency() != null) {
|
||||
latency = getForcedLatency();
|
||||
rewriteEntry = rewritePacket = true;
|
||||
}
|
||||
}
|
||||
if (actions.contains(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LISTED)) {
|
||||
if (allPlayersHidden && nmsData.profileId().getMostSignificantBits() != 0) { // Filter out layout entries
|
||||
listed = false;
|
||||
rewriteEntry = rewritePacket = true;
|
||||
}
|
||||
}
|
||||
if (actions.contains(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER)) {
|
||||
TAB.getInstance().getFeatureManager().onEntryAdd(player, nmsData.profileId(), nmsData.profile().getName());
|
||||
}
|
||||
updatedList.add(rewriteEntry ? new ClientboundPlayerInfoUpdatePacket.Entry(
|
||||
nmsData.profileId(), nmsData.profile(), listed, latency, GameType.byId(gameMode), displayName,
|
||||
nmsData.chatSession()
|
||||
) : nmsData);
|
||||
}
|
||||
if (rewritePacket) return new ClientboundPlayerInfoUpdatePacket(actions, updatedList);
|
||||
}
|
||||
return packet;
|
||||
}
|
||||
|
||||
private void sendPacket(@NonNull EnumSet<ClientboundPlayerInfoUpdatePacket.Action> action, @NonNull UUID id, @NonNull String name, @Nullable Skin skin,
|
||||
boolean listed, int latency, int gameMode, @Nullable TabComponent displayName) {
|
||||
ClientboundPlayerInfoUpdatePacket packet = new ClientboundPlayerInfoUpdatePacket(action, new ClientboundPlayerInfoUpdatePacket.Entry(
|
||||
id,
|
||||
action.contains(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER) ? createProfile(id, name, skin) : null,
|
||||
listed,
|
||||
latency,
|
||||
GameType.byId(gameMode),
|
||||
displayName == null ? null : displayName.convert(),
|
||||
null
|
||||
));
|
||||
sendPacket(packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates GameProfile from given parameters.
|
||||
*
|
||||
* @param id
|
||||
* Profile ID
|
||||
* @param name
|
||||
* Profile name
|
||||
* @param skin
|
||||
* Player skin
|
||||
* @return GameProfile from given parameters
|
||||
*/
|
||||
@NotNull
|
||||
private GameProfile createProfile(@NonNull UUID id, @NonNull String name, @Nullable Skin skin) {
|
||||
GameProfile profile = new GameProfile(id, name);
|
||||
if (skin != null) {
|
||||
profile.getProperties().put(TabList.TEXTURES_PROPERTY,
|
||||
new Property(TabList.TEXTURES_PROPERTY, skin.getValue(), skin.getSignature()));
|
||||
}
|
||||
return profile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the packet to the player.
|
||||
*
|
||||
* @param packet
|
||||
* Packet to send
|
||||
*/
|
||||
private void sendPacket(@NotNull Packet<?> packet) {
|
||||
((CraftPlayer)player.getPlayer()).getHandle().connection.send(packet);
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package me.neznamy.tab.platforms.bukkit.paper_1_20_5;
|
||||
|
||||
import me.neznamy.tab.shared.platform.TabListEntryTracker;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Implementation of TabListEntryTracker.
|
||||
*/
|
||||
public class NMSTabListEntryTracker extends TabListEntryTracker {
|
||||
|
||||
@Override
|
||||
public void onPacketSend(@NotNull Object packet) {
|
||||
if (packet instanceof ClientboundPlayerInfoRemovePacket remove) {
|
||||
for (UUID id : remove.profileIds()) {
|
||||
tablistEntries.remove(id);
|
||||
}
|
||||
}
|
||||
if (packet instanceof ClientboundPlayerInfoUpdatePacket update) {
|
||||
if (update.actions().contains(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER)) {
|
||||
for (ClientboundPlayerInfoUpdatePacket.Entry nmsData : update.entries()) {
|
||||
tablistEntries.add(nmsData.profileId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
plugins {
|
||||
id("io.papermc.paperweight.userdev") version "2.0.0-beta.19"
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven("https://jitpack.io") // YamlAssist
|
||||
maven("https://repo.opencollab.dev/maven-snapshots/")
|
||||
maven("https://repo.viaversion.com/")
|
||||
maven {
|
||||
name = "luck-repo"
|
||||
url = uri("https://repo.lucko.me/")
|
||||
content {
|
||||
includeModule("me.lucko", "spark-api")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val version = "1.21.11-R0.1-SNAPSHOT"
|
||||
|
||||
dependencies {
|
||||
implementation(projects.bukkit)
|
||||
paperweight.paperDevBundle(version)
|
||||
compileOnly("io.papermc.paper:paper-api:${version}")
|
||||
}
|
||||
|
||||
tasks.compileJava {
|
||||
options.release.set(21)
|
||||
}
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
package me.neznamy.tab.platforms.bukkit.paper_1_21_11;
|
||||
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import com.mojang.authlib.properties.PropertyMap;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ComponentConverter;
|
||||
import me.neznamy.tab.shared.chat.TabStyle;
|
||||
import me.neznamy.tab.shared.chat.component.object.TabAtlasSprite;
|
||||
import me.neznamy.tab.shared.chat.component.object.TabPlayerSprite;
|
||||
import me.neznamy.tab.shared.platform.TabList;
|
||||
import net.minecraft.network.chat.*;
|
||||
import net.minecraft.network.chat.contents.objects.AtlasSprite;
|
||||
import net.minecraft.network.chat.contents.objects.PlayerSprite;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.world.item.component.ResolvableProfile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Component converter using direct mojang-mapped code.
|
||||
*/
|
||||
public class NMSComponentConverter extends ComponentConverter<Component> {
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Component newTextComponent(@NotNull String text) {
|
||||
return Component.literal(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Component newTranslatableComponent(@NotNull String key) {
|
||||
return Component.translatable(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Component newKeybindComponent(@NotNull String keybind) {
|
||||
return Component.keybind(keybind);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Component newObjectComponent(@NotNull TabAtlasSprite sprite) {
|
||||
return Component.object(new AtlasSprite(Identifier.parse(sprite.getAtlas()), Identifier.parse(sprite.getSprite())));
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Component newObjectComponent(@NotNull TabPlayerSprite sprite) {
|
||||
ResolvableProfile profile;
|
||||
if (sprite.getId() != null) {
|
||||
profile = ResolvableProfile.createUnresolved(sprite.getId());
|
||||
} else if (sprite.getName() != null) {
|
||||
profile = ResolvableProfile.createUnresolved(sprite.getName());
|
||||
} else if (sprite.getSkin() != null) {
|
||||
ImmutableMultimap.Builder<String, Property> builder = ImmutableMultimap.builder();
|
||||
builder.put(TabList.TEXTURES_PROPERTY, new Property(TabList.TEXTURES_PROPERTY, sprite.getSkin().getValue(), sprite.getSkin().getSignature()));
|
||||
profile = ResolvableProfile.createResolved(new GameProfile(NIL_UUID, "", new PropertyMap(builder.build())));
|
||||
} else {
|
||||
throw new IllegalStateException("Player head component does not have id, name or skin set");
|
||||
}
|
||||
return Component.object(new PlayerSprite(profile, sprite.isShowHat()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyStyle(@NotNull Component nmsComponent, @NotNull TabStyle modifier) {
|
||||
Style style = Style.EMPTY
|
||||
.withColor(modifier.getColor() == null ? null : TextColor.fromRgb(modifier.getColor().getRgb()))
|
||||
.withBold(modifier.getBold())
|
||||
.withItalic(modifier.getItalic())
|
||||
.withUnderlined(modifier.getUnderlined())
|
||||
.withStrikethrough(modifier.getStrikethrough())
|
||||
.withObfuscated(modifier.getObfuscated())
|
||||
.withFont(modifier.getFont() == null ? null : new FontDescription.Resource(Identifier.parse(modifier.getFont())));
|
||||
if (modifier.getShadowColor() != null) style = style.withShadowColor(modifier.getShadowColor()); // withShadowColor takes int instead of Integer, bug?
|
||||
((MutableComponent)nmsComponent).setStyle(style);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSibling(@NotNull Component parent, @NotNull Component child) {
|
||||
((MutableComponent)parent).append(child);
|
||||
}
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
package me.neznamy.tab.platforms.bukkit.paper_1_21_11;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.Getter;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ComponentConverter;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ImplementationProvider;
|
||||
import me.neznamy.tab.shared.platform.Scoreboard;
|
||||
import me.neznamy.tab.shared.platform.TabList;
|
||||
import me.neznamy.tab.shared.platform.TabListEntryTracker;
|
||||
import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Implementation provider using direct Mojang-mapped NMS code for paper 1.21.11.
|
||||
*/
|
||||
@Getter
|
||||
public class NMSImplementationProvider implements ImplementationProvider {
|
||||
|
||||
@NotNull
|
||||
private final ComponentConverter<?> componentConverter = new NMSComponentConverter();
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Scoreboard newScoreboard(@NotNull BukkitTabPlayer player) {
|
||||
return new NMSPacketScoreboard(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public TabList newTabList(@NotNull BukkitTabPlayer player) {
|
||||
return new NMSPacketTabList(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Channel getChannel(@NotNull Player player) {
|
||||
return ((CraftPlayer)player).getHandle().connection.connection.channel;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public TabListEntryTracker newTabListEntryTracker() {
|
||||
return new NMSTabListEntryTracker();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPing(@NotNull BukkitTabPlayer player) {
|
||||
return player.getPlayer().getPing();
|
||||
}
|
||||
}
|
||||
+176
@@ -0,0 +1,176 @@
|
||||
package me.neznamy.tab.platforms.bukkit.paper_1_21_11;
|
||||
|
||||
import lombok.NonNull;
|
||||
import lombok.SneakyThrows;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.platform.decorators.SafeScoreboard;
|
||||
import me.neznamy.tab.shared.util.ReflectionUtils;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.network.chat.numbers.FixedFormat;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.protocol.game.*;
|
||||
import net.minecraft.world.scores.PlayerTeam;
|
||||
import net.minecraft.world.scores.Scoreboard;
|
||||
import net.minecraft.world.scores.criteria.ObjectiveCriteria;
|
||||
import net.minecraft.world.scores.criteria.ObjectiveCriteria.RenderType;
|
||||
import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Scoreboard implementation using direct mojang-mapped code.
|
||||
*/
|
||||
public class NMSPacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
|
||||
private static final ChatFormatting[] formats = ChatFormatting.values();
|
||||
private static final net.minecraft.world.scores.Team.CollisionRule[] collisions = net.minecraft.world.scores.Team.CollisionRule.values();
|
||||
private static final net.minecraft.world.scores.Team.Visibility[] visibilities = net.minecraft.world.scores.Team.Visibility.values();
|
||||
private static final Scoreboard dummyScoreboard = new Scoreboard();
|
||||
private static final Field players = ReflectionUtils.getOnlyField(ClientboundSetPlayerTeamPacket.class, Collection.class);
|
||||
|
||||
/**
|
||||
* Constructs new instance with given player.
|
||||
*
|
||||
* @param player
|
||||
* Player this scoreboard will belong to
|
||||
*/
|
||||
public NMSPacketScoreboard(@NotNull BukkitTabPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerObjective(@NonNull Objective objective) {
|
||||
net.minecraft.world.scores.Objective obj = new net.minecraft.world.scores.Objective(
|
||||
dummyScoreboard,
|
||||
objective.getName(),
|
||||
ObjectiveCriteria.DUMMY,
|
||||
objective.getTitle().convert(),
|
||||
RenderType.values()[objective.getHealthDisplay().ordinal()],
|
||||
false,
|
||||
objective.getNumberFormat() == null ? null : objective.getNumberFormat().toFixedFormat(FixedFormat::new)
|
||||
);
|
||||
objective.setPlatformObjective(obj);
|
||||
sendPacket(new ClientboundSetObjectivePacket(obj, ObjectiveAction.REGISTER));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDisplaySlot(@NonNull Objective objective) {
|
||||
sendPacket(new ClientboundSetDisplayObjectivePacket(
|
||||
net.minecraft.world.scores.DisplaySlot.values()[objective.getDisplaySlot().ordinal()],
|
||||
(net.minecraft.world.scores.Objective) objective.getPlatformObjective()
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterObjective(@NonNull Objective objective) {
|
||||
sendPacket(new ClientboundSetObjectivePacket((net.minecraft.world.scores.Objective) objective.getPlatformObjective(), ObjectiveAction.UNREGISTER));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateObjective(@NonNull Objective objective) {
|
||||
net.minecraft.world.scores.Objective obj = (net.minecraft.world.scores.Objective) objective.getPlatformObjective();
|
||||
obj.setDisplayName(objective.getTitle().convert());
|
||||
obj.setRenderType(RenderType.values()[objective.getHealthDisplay().ordinal()]);
|
||||
sendPacket(new ClientboundSetObjectivePacket(obj, ObjectiveAction.UPDATE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScore(@NonNull Score score) {
|
||||
sendPacket(new ClientboundSetScorePacket(
|
||||
score.getHolder(),
|
||||
score.getObjective().getName(),
|
||||
score.getValue(),
|
||||
Optional.ofNullable(score.getDisplayName() == null ? null : score.getDisplayName().convert()),
|
||||
Optional.ofNullable(score.getNumberFormat() == null ? null : score.getNumberFormat().toFixedFormat(FixedFormat::new))
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeScore(@NonNull Score score) {
|
||||
sendPacket(new ClientboundResetScorePacket(score.getHolder(), score.getObjective().getName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Object createTeam(@NonNull String name) {
|
||||
return new PlayerTeam(dummyScoreboard, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerTeam(@NonNull Team team) {
|
||||
updateTeamProperties(team);
|
||||
PlayerTeam t = (PlayerTeam) team.getPlatformTeam();
|
||||
t.getPlayers().addAll(team.getPlayers());
|
||||
sendPacket(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(t, true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterTeam(@NonNull Team team) {
|
||||
sendPacket(ClientboundSetPlayerTeamPacket.createRemovePacket((PlayerTeam) team.getPlatformTeam()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTeam(@NonNull Team team) {
|
||||
updateTeamProperties(team);
|
||||
sendPacket(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket((PlayerTeam) team.getPlatformTeam(), false));
|
||||
}
|
||||
|
||||
private void updateTeamProperties(@NonNull Team team) {
|
||||
PlayerTeam t = (PlayerTeam) team.getPlatformTeam();
|
||||
t.setAllowFriendlyFire((team.getOptions() & 0x01) != 0);
|
||||
t.setSeeFriendlyInvisibles((team.getOptions() & 0x02) != 0);
|
||||
t.setColor(formats[team.getColor().ordinal()]);
|
||||
t.setCollisionRule(collisions[team.getCollision().ordinal()]);
|
||||
t.setNameTagVisibility(visibilities[team.getVisibility().ordinal()]);
|
||||
t.setPlayerPrefix(team.getPrefix().convert());
|
||||
t.setPlayerSuffix(team.getSuffix().convert());
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
@NotNull
|
||||
public Object onPacketSend(@NonNull Object packet) {
|
||||
if (packet instanceof ClientboundSetDisplayObjectivePacket display) {
|
||||
TAB.getInstance().getFeatureManager().onDisplayObjective(player, display.getSlot().ordinal(), display.getObjectiveName());
|
||||
}
|
||||
if (packet instanceof ClientboundSetObjectivePacket objective) {
|
||||
TAB.getInstance().getFeatureManager().onObjective(player, objective.getMethod(), objective.getObjectiveName());
|
||||
}
|
||||
if (packet instanceof ClientboundSetPlayerTeamPacket team) {
|
||||
int action = getMethod(team);
|
||||
if (action != TeamAction.UPDATE) {
|
||||
players.set(team, onTeamPacket(action, team.getName(), team.getPlayers() == null ? Collections.emptyList() : team.getPlayers()));
|
||||
}
|
||||
}
|
||||
return packet;
|
||||
}
|
||||
|
||||
private int getMethod(@NonNull ClientboundSetPlayerTeamPacket team) {
|
||||
if (team.getTeamAction() == ClientboundSetPlayerTeamPacket.Action.ADD) {
|
||||
return 0;
|
||||
} else if (team.getTeamAction() == ClientboundSetPlayerTeamPacket.Action.REMOVE) {
|
||||
return 1;
|
||||
} else if (team.getPlayerAction() == ClientboundSetPlayerTeamPacket.Action.ADD) {
|
||||
return 3;
|
||||
} else if (team.getPlayerAction() == ClientboundSetPlayerTeamPacket.Action.REMOVE) {
|
||||
return 4;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the packet to the player.
|
||||
*
|
||||
* @param packet
|
||||
* Packet to send
|
||||
*/
|
||||
private void sendPacket(@NotNull Packet<?> packet) {
|
||||
((CraftPlayer)player.getPlayer()).getHandle().connection.send(packet);
|
||||
}
|
||||
}
|
||||
+204
@@ -0,0 +1,204 @@
|
||||
package me.neznamy.tab.platforms.bukkit.paper_1_21_11;
|
||||
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import com.mojang.authlib.properties.PropertyMap;
|
||||
import lombok.NonNull;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.chat.component.TabComponent;
|
||||
import me.neznamy.tab.shared.platform.decorators.TrackedTabList;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundTabListPacket;
|
||||
import net.minecraft.world.level.GameType;
|
||||
import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* TabList implementation using direct mojang-mapped code.
|
||||
*/
|
||||
public class NMSPacketTabList extends TrackedTabList<BukkitTabPlayer> {
|
||||
|
||||
private static final EnumSet<ClientboundPlayerInfoUpdatePacket.Action> addPlayer = EnumSet.allOf(ClientboundPlayerInfoUpdatePacket.Action.class);
|
||||
private static final EnumSet<ClientboundPlayerInfoUpdatePacket.Action> updateDisplayName = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME);
|
||||
private static final EnumSet<ClientboundPlayerInfoUpdatePacket.Action> updateLatency = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY);
|
||||
private static final EnumSet<ClientboundPlayerInfoUpdatePacket.Action> updateGameMode = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE);
|
||||
private static final EnumSet<ClientboundPlayerInfoUpdatePacket.Action> updateListed = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LISTED);
|
||||
private static final EnumSet<ClientboundPlayerInfoUpdatePacket.Action> updateListOrder = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LIST_ORDER);
|
||||
private static final EnumSet<ClientboundPlayerInfoUpdatePacket.Action> updateHat = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_HAT);
|
||||
|
||||
/**
|
||||
* Constructs new instance.
|
||||
*
|
||||
* @param player
|
||||
* Player this tablist will belong to
|
||||
*/
|
||||
public NMSPacketTabList(@NotNull BukkitTabPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeEntry(@NonNull UUID entry) {
|
||||
sendPacket(new ClientboundPlayerInfoRemovePacket(Collections.singletonList(entry)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDisplayName0(@NonNull UUID entry, @Nullable TabComponent displayName) {
|
||||
sendPacket(updateDisplayName, entry, "", null, false, 0, 0, displayName, 0, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLatency(@NonNull UUID entry, int latency) {
|
||||
sendPacket(updateLatency, entry, "", null, false, latency, 0, null, 0, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateGameMode(@NonNull UUID entry, int gameMode) {
|
||||
sendPacket(updateGameMode, entry, "", null, false, 0, gameMode, null, 0, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateListed(@NonNull UUID entry, boolean listed) {
|
||||
sendPacket(updateListed, entry, "", null, listed, 0, 0, null, 0, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateListOrder(@NonNull UUID entry, int listOrder) {
|
||||
sendPacket(updateListOrder, entry, "", null, false, 0, 0, null, listOrder, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateHat(@NonNull UUID entry, boolean showHat) {
|
||||
sendPacket(updateHat, entry, "", null, false, 0, 0, null, 0, showHat);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEntry0(@NonNull Entry entry) {
|
||||
sendPacket(addPlayer, entry.getUniqueId(), entry.getName(), entry.getSkin(), entry.isListed(), entry.getLatency(),
|
||||
entry.getGameMode(), entry.getDisplayName(), entry.getListOrder(), entry.isShowHat());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerListHeaderFooter0(@NonNull TabComponent header, @NonNull TabComponent footer) {
|
||||
sendPacket(new ClientboundTabListPacket(header.convert(), footer.convert()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Skin getSkin() {
|
||||
Collection<Property> properties = ((CraftPlayer)player.getPlayer()).getProfile().properties().get(TEXTURES_PROPERTY);
|
||||
if (properties.isEmpty()) return null; // Offline mode
|
||||
Property property = properties.iterator().next();
|
||||
return new Skin(property.value(), property.signature());
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Object onPacketSend(@NonNull Object packet) {
|
||||
if (packet instanceof ClientboundTabListPacket tablist) {
|
||||
if (header == null || footer == null) return packet;
|
||||
if (tablist.header() != header.convert() || tablist.footer() != footer.convert()) {
|
||||
return new ClientboundTabListPacket(header.convert(), footer.convert());
|
||||
}
|
||||
}
|
||||
if (packet instanceof ClientboundPlayerInfoUpdatePacket info) {
|
||||
EnumSet<ClientboundPlayerInfoUpdatePacket.Action> actions = info.actions();
|
||||
List<ClientboundPlayerInfoUpdatePacket.Entry> updatedList = new ArrayList<>();
|
||||
boolean rewritePacket = false;
|
||||
for (ClientboundPlayerInfoUpdatePacket.Entry nmsData : info.entries()) {
|
||||
boolean rewriteEntry = false;
|
||||
Component displayName = nmsData.displayName();
|
||||
int latency = nmsData.latency();
|
||||
int gameMode = nmsData.gameMode().getId();
|
||||
boolean listed = nmsData.listed();
|
||||
if (actions.contains(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME)) {
|
||||
TabComponent forcedDisplayName = getForcedDisplayNames().get(nmsData.profileId());
|
||||
if (forcedDisplayName != null && forcedDisplayName.convert() != displayName) {
|
||||
displayName = forcedDisplayName.convert();
|
||||
rewriteEntry = rewritePacket = true;
|
||||
}
|
||||
}
|
||||
if (actions.contains(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE)) {
|
||||
if (getBlockedSpectators().contains(nmsData.profileId()) && gameMode == 3) {
|
||||
gameMode = 0;
|
||||
rewriteEntry = rewritePacket = true;
|
||||
}
|
||||
}
|
||||
if (actions.contains(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY)) {
|
||||
if (getForcedLatency() != null) {
|
||||
latency = getForcedLatency();
|
||||
rewriteEntry = rewritePacket = true;
|
||||
}
|
||||
}
|
||||
if (actions.contains(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LISTED)) {
|
||||
if (allPlayersHidden && nmsData.profileId().getMostSignificantBits() != 0) { // Filter out layout entries
|
||||
listed = false;
|
||||
rewriteEntry = rewritePacket = true;
|
||||
}
|
||||
}
|
||||
if (actions.contains(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER)) {
|
||||
TAB.getInstance().getFeatureManager().onEntryAdd(player, nmsData.profileId(), nmsData.profile().name());
|
||||
}
|
||||
updatedList.add(rewriteEntry ? new ClientboundPlayerInfoUpdatePacket.Entry(
|
||||
nmsData.profileId(), nmsData.profile(), listed, latency, GameType.byId(gameMode), displayName,
|
||||
nmsData.showHat(), nmsData.listOrder(), nmsData.chatSession()
|
||||
) : nmsData);
|
||||
}
|
||||
if (rewritePacket) return new ClientboundPlayerInfoUpdatePacket(actions, updatedList);
|
||||
}
|
||||
return packet;
|
||||
}
|
||||
|
||||
private void sendPacket(@NonNull EnumSet<ClientboundPlayerInfoUpdatePacket.Action> action, @NonNull UUID id, @NonNull String name, @Nullable Skin skin,
|
||||
boolean listed, int latency, int gameMode, @Nullable TabComponent displayName, int listOrder, boolean showHat) {
|
||||
ClientboundPlayerInfoUpdatePacket packet = new ClientboundPlayerInfoUpdatePacket(action, new ClientboundPlayerInfoUpdatePacket.Entry(
|
||||
id,
|
||||
action.contains(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER) ? createProfile(id, name, skin) : null,
|
||||
listed,
|
||||
latency,
|
||||
GameType.byId(gameMode),
|
||||
displayName == null ? null : displayName.convert(),
|
||||
showHat,
|
||||
listOrder,
|
||||
null
|
||||
));
|
||||
sendPacket(packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates GameProfile from given parameters.
|
||||
*
|
||||
* @param id
|
||||
* Profile ID
|
||||
* @param name
|
||||
* Profile name
|
||||
* @param skin
|
||||
* Player skin
|
||||
* @return GameProfile from given parameters
|
||||
*/
|
||||
@NotNull
|
||||
private GameProfile createProfile(@NonNull UUID id, @NonNull String name, @Nullable Skin skin) {
|
||||
ImmutableMultimap.Builder<String, Property> builder = ImmutableMultimap.builder();
|
||||
if (skin != null) {
|
||||
builder.put(TEXTURES_PROPERTY, new Property(TEXTURES_PROPERTY, skin.getValue(), skin.getSignature()));
|
||||
}
|
||||
return new GameProfile(id, name, new PropertyMap(builder.build()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the packet to the player.
|
||||
*
|
||||
* @param packet
|
||||
* Packet to send
|
||||
*/
|
||||
private void sendPacket(@NotNull Packet<?> packet) {
|
||||
((CraftPlayer)player.getPlayer()).getHandle().connection.send(packet);
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package me.neznamy.tab.platforms.bukkit.paper_1_21_11;
|
||||
|
||||
import me.neznamy.tab.shared.platform.TabListEntryTracker;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Implementation of TabListEntryTracker.
|
||||
*/
|
||||
public class NMSTabListEntryTracker extends TabListEntryTracker {
|
||||
|
||||
@Override
|
||||
public void onPacketSend(@NotNull Object packet) {
|
||||
if (packet instanceof ClientboundPlayerInfoRemovePacket remove) {
|
||||
for (UUID id : remove.profileIds()) {
|
||||
tablistEntries.remove(id);
|
||||
}
|
||||
}
|
||||
if (packet instanceof ClientboundPlayerInfoUpdatePacket update) {
|
||||
if (update.actions().contains(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER)) {
|
||||
for (ClientboundPlayerInfoUpdatePacket.Entry nmsData : update.entries()) {
|
||||
tablistEntries.add(nmsData.profileId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loaded 100 of 792 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user