Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
476c61ed47 | ||
|
|
4b6bfbc08b | ||
|
|
0be838c58f | ||
|
|
d6c81f32cd | ||
|
|
5d2104dd91 | ||
|
|
969ce9d6a3 | ||
|
|
55b456cb95 | ||
|
|
062ffc18f9 | ||
|
|
95cbd40655 | ||
|
|
70d94137dd | ||
|
|
bbea70d1db | ||
|
|
b5e5b752a4 | ||
|
|
28b4dd8e08 | ||
|
|
1ae92a8b9d | ||
|
|
00bbea33f6 | ||
|
|
3fd3c397a6 | ||
|
|
f1f95a0aac | ||
|
|
6e90a3e376 | ||
|
|
41d51453a5 | ||
|
|
c74f8b2559 | ||
|
|
be2eb6a8ce | ||
|
|
9819db60cd | ||
|
|
2a86e0d355 | ||
|
|
4a209a342e | ||
|
|
33e5b58e3b | ||
|
|
fd11bd24a9 | ||
|
|
8c1f14de57 | ||
|
|
bc615355c8 | ||
|
|
28730806f9 | ||
|
|
4ec975fcd1 | ||
|
|
b6ce588e10 | ||
|
|
a1510b5f6d | ||
|
|
913d527a64 | ||
|
|
a1e250b521 | ||
|
|
887c107216 | ||
|
|
b6fb699a27 | ||
|
|
575aa4619c | ||
|
|
3f787c0e35 | ||
|
|
a0fc7f6978 | ||
|
|
2cd069ea72 | ||
|
|
d4b4b24e3c | ||
|
|
dca7daec04 | ||
|
|
b686eb467f | ||
|
|
d1f0618c0e | ||
|
|
ce06511b52 | ||
|
|
a2b0c0f28e | ||
|
|
da71044fc4 | ||
|
|
4167c949fe | ||
|
|
6f490a7e93 | ||
|
|
b14dfc710a | ||
|
|
1877bae091 | ||
|
|
4cf7069254 | ||
|
|
d4c89ebff0 | ||
|
|
f58005a412 | ||
|
|
382931f4f8 | ||
|
|
7be5b84b5d | ||
|
|
0db35d3bd7 | ||
|
|
6e2da40aa5 | ||
|
|
dae7c2e90b | ||
|
|
04db0ba88d | ||
|
|
9680bc77b3 | ||
|
|
85c0d3d9d3 | ||
|
|
b348af9581 | ||
|
|
aedb43b487 | ||
|
|
3b86806d8e | ||
|
|
c4cc09d8e0 | ||
|
|
1a3b2471b3 | ||
|
|
3a004572c1 | ||
|
|
feabf561c5 | ||
|
|
5247ccd129 | ||
|
|
c77390b86c | ||
|
|
8ecad1f93e | ||
|
|
dae82c4d65 | ||
|
|
8f8cc8ac43 | ||
|
|
f66626ae74 | ||
|
|
4ffcbcad91 | ||
|
|
fc31b7de7b | ||
|
|
c24f2d7849 | ||
|
|
b316f54fd8 | ||
|
|
2fda301027 | ||
|
|
9e6f3fbb2a | ||
|
|
980d306100 | ||
|
|
9d4a44b403 | ||
|
|
52d92e6c1a | ||
|
|
0a96edb1bb | ||
|
|
3ced349018 | ||
|
|
9649c99f90 | ||
|
|
0b587d398d | ||
|
|
47eaa1d1ca | ||
|
|
cbd170729d | ||
|
|
6997bb4615 | ||
|
|
dc6db3cfaa | ||
|
|
72c337a68c | ||
|
|
a9d0389adf | ||
|
|
76ea2aa665 | ||
|
|
672700afc5 | ||
|
|
d8a44fe8b6 | ||
|
|
2a777092d2 | ||
|
|
083a060371 | ||
|
|
b1b5dee5f0 | ||
|
|
05dfea6da2 | ||
|
|
208d6911f0 | ||
|
|
07ca508df1 | ||
|
|
40ab1419c5 | ||
|
|
cb48134548 | ||
|
|
ce287ad7db | ||
|
|
be1e743571 | ||
|
|
a57b911fd2 | ||
|
|
a3b7fc8908 | ||
|
|
85717a84b7 | ||
|
|
6a8e96382e | ||
|
|
52b6cb6a71 | ||
|
|
eda7d9273f | ||
|
|
9391b16f50 | ||
|
|
bd499550d8 | ||
|
|
dd6eb173a0 | ||
|
|
78c994987f | ||
|
|
d11a0bade5 | ||
|
|
e54035a683 | ||
|
|
5ef51406eb | ||
|
|
9843e9fd68 | ||
|
|
f3bdcbec83 | ||
|
|
a5d3cf5957 | ||
|
|
aa87cf8032 | ||
|
|
07137ddb26 | ||
|
|
92076e8559 | ||
|
|
5356a011ec | ||
|
|
b72502b8a1 | ||
|
|
20bee30f69 | ||
|
|
4f29b8a2c9 | ||
|
|
ef867acc36 | ||
|
|
da37c4320e | ||
|
|
6b2d3cbc7e | ||
|
|
397310df8b | ||
|
|
04d444cc30 | ||
|
|
eb68151a73 | ||
|
|
a2fcc30fbb | ||
|
|
6cdc535cbc | ||
|
|
095550e041 | ||
|
|
3b4a0609e3 | ||
|
|
54fe6b0dbd | ||
|
|
ff2b73e9b1 | ||
|
|
bb3630840d | ||
|
|
555aed78f3 | ||
|
|
1ed52f3f4e | ||
|
|
72a44648cd | ||
|
|
2db8e75a66 | ||
|
|
e9064c4e87 | ||
|
|
680cbbf932 | ||
|
|
7285af4481 | ||
|
|
bd4f5c2ecf | ||
|
|
dd94a9a677 | ||
|
|
341c70f6dd | ||
|
|
41a8a47060 | ||
|
|
881ad034a6 | ||
|
|
4a1c86cba3 | ||
|
|
56c9b73bcb | ||
|
|
93bac071ac | ||
|
|
f88c9f027d | ||
|
|
1cb2219dbb | ||
|
|
e00d5822f2 | ||
|
|
f64846f339 | ||
|
|
fd2480abbc | ||
|
|
4d820eef6d | ||
|
|
6bddd197db | ||
|
|
8439ca103c | ||
|
|
60e546b075 | ||
|
|
cfc0e5b260 | ||
|
|
3c11278949 | ||
|
|
8bde89d4ee | ||
|
|
a5ebc356ad | ||
|
|
aeb37c0a28 | ||
|
|
85106c8e59 | ||
|
|
06d350bb1e | ||
|
|
a612ffeba1 | ||
|
|
651051f136 | ||
|
|
3000d76272 | ||
|
|
e136327742 | ||
|
|
e1a22373d6 | ||
|
|
b7f4375599 | ||
|
|
bf97a66dd7 | ||
|
|
9077e346f2 | ||
|
|
0031d6aae3 | ||
|
|
cec46d111b | ||
|
|
ef151757db | ||
|
|
fef29a0697 | ||
|
|
b58b71a5b1 | ||
|
|
8a4fc799e4 | ||
|
|
979fc09e13 | ||
|
|
13fa3504bf | ||
|
|
adbaa5cfbc | ||
|
|
1881336a14 | ||
|
|
100d02904e | ||
|
|
be8e15e087 | ||
|
|
487bcc3461 | ||
|
|
1f86c651b8 | ||
|
|
388001447f | ||
|
|
13c59e2b5e | ||
|
|
5c236bb4ed | ||
|
|
fea6e90f12 | ||
|
|
fb098bd169 | ||
|
|
612b2bb6cc | ||
|
|
a145c10e5d | ||
|
|
cb57f4fd6a | ||
|
|
ed28da338a | ||
|
|
0d86b3b297 | ||
|
|
90bd1841f0 | ||
|
|
be24877913 | ||
|
|
7218c365e3 | ||
|
|
33dd09362a | ||
|
|
4aae57075a | ||
|
|
d90240641e | ||
|
|
a5871befe6 | ||
|
|
fa56d226f3 | ||
|
|
a5ff4a9ad8 | ||
|
|
d61c690075 | ||
|
|
873589bd7f | ||
|
|
032f2ff228 | ||
|
|
0c733b31a7 | ||
|
|
2baaf18db6 | ||
|
|
4d7314e2d8 | ||
|
|
f1f4ffe6b2 | ||
|
|
2fac9dc516 | ||
|
|
ab8faf358c | ||
|
|
243ce3c5dd | ||
|
|
d4762195f9 | ||
|
|
121e1615b6 | ||
|
|
350d33ae6f | ||
|
|
d4f7bced86 | ||
|
|
8037e659a8 | ||
|
|
28c7849252 | ||
|
|
cb277bf16a | ||
|
|
0612e1e188 | ||
|
|
7a9f83129e | ||
|
|
a17e5f13a7 | ||
|
|
02a565bf39 | ||
|
|
f1d7d5ac81 | ||
|
|
a1663f5a03 | ||
|
|
909492cfae | ||
|
|
a3b4cc21f5 | ||
|
|
402ebd729e | ||
|
|
349b5dc110 | ||
|
|
c778cc3368 | ||
|
|
26e5aab84e | ||
|
|
79da4e1bc4 | ||
|
|
51b550ca5e | ||
|
|
2877b74c42 | ||
|
|
c67d1a86c5 | ||
|
|
5cf9b34fd2 | ||
|
|
99acbe4960 | ||
|
|
2bf64b6107 | ||
|
|
4e86af8754 | ||
|
|
6bf639f18a | ||
|
|
9a7bb17459 | ||
|
|
6b84c683ee | ||
|
|
1260aa1de5 | ||
|
|
bdccde4040 | ||
|
|
7cdb95116a | ||
|
|
c9d42f8e8e | ||
|
|
1e738f038f | ||
|
|
57fb06ca5f | ||
|
|
83d925ead0 | ||
|
|
ce1baaad7a | ||
|
|
a370f6e7b7 | ||
|
|
dc015dc457 | ||
|
|
fd7bc84cd5 | ||
|
|
9fd5b3b912 | ||
|
|
a2d259af58 | ||
|
|
6cc21a6d98 | ||
|
|
e105770dde | ||
|
|
68b7ee51dc | ||
|
|
a4a375f411 | ||
|
|
ae6b3d18a4 | ||
|
|
8763b0e77f | ||
|
|
2440b64981 | ||
|
|
ebe73587fe | ||
|
|
5b87ac4f61 | ||
|
|
d9a3f33199 | ||
|
|
9f44834514 | ||
|
|
314d4a2813 | ||
|
|
97fee0c898 | ||
|
|
bdc96a88cd | ||
|
|
af1691e6e5 | ||
|
|
e4058f7f15 | ||
|
|
7f0c922e10 | ||
|
|
453793eb60 | ||
|
|
015e7a4647 | ||
|
|
45c0c580f7 | ||
|
|
1c12a868c8 | ||
|
|
a3f22320d5 | ||
|
|
f4bb1dd8fc | ||
|
|
5203b3a376 | ||
|
|
fe66d743a9 | ||
|
|
1d1cf84c60 | ||
|
|
1c81aab994 | ||
|
|
52559f6fc8 | ||
|
|
06cc25bf23 | ||
|
|
86cf0d51ed | ||
|
|
5fbb052d6f | ||
|
|
b7021fcd1f | ||
|
|
64db7f13c6 | ||
|
|
20c9fdf634 | ||
|
|
a71035a157 | ||
|
|
b0002102e3 | ||
|
|
a3e65cfcbe | ||
|
|
edd9c5ce3d | ||
|
|
e918e6b10a | ||
|
|
f6c309fd18 | ||
|
|
322a99dbc4 | ||
|
|
6793dee0bc | ||
|
|
d33751dbb0 | ||
|
|
fa67de16a1 | ||
|
|
57fc21f411 | ||
|
|
9999ee3b4a | ||
|
|
4a90cadeb1 | ||
|
|
048903f33f | ||
|
|
3fa5eaf2a3 | ||
|
|
93bd6d5ac9 | ||
|
|
aa5535615c | ||
|
|
9ccd85178d | ||
|
|
14fd279c06 | ||
|
|
6df845324b | ||
|
|
c3f233ca61 | ||
|
|
ed4f018b34 | ||
|
|
ef4bc1c02e | ||
|
|
ca725b68a5 | ||
|
|
40f7463e93 | ||
|
|
7778768c30 | ||
|
|
6a6be44ab2 | ||
|
|
fe67c23ad4 | ||
|
|
c09348d4f7 | ||
|
|
e04cd2108f | ||
|
|
39f0dee9f1 | ||
|
|
9b9ae8d36c | ||
|
|
fc934195de | ||
|
|
6c4db8029b | ||
|
|
c4ce7b7a87 | ||
|
|
b751c63625 | ||
|
|
31ac149b42 | ||
|
|
2f45e9e469 | ||
|
|
7b152ff264 | ||
|
|
e9eb441a1c | ||
|
|
55c1093783 | ||
|
|
963ec4e978 | ||
|
|
26c30f46e7 | ||
|
|
c2cdafb17f | ||
|
|
22060a9889 | ||
|
|
e1a54099a4 | ||
|
|
3fa6a0f69a | ||
|
|
676cb6c3ce | ||
|
|
a3063f0bcb | ||
|
|
c1520401b6 | ||
|
|
d988d0c684 | ||
|
|
e2283d6f4e | ||
|
|
ea56cfde04 | ||
|
|
16733e587e | ||
|
|
b247807f0f | ||
|
|
679aea8181 | ||
|
|
f0d499a008 | ||
|
|
b5320f2ae7 | ||
|
|
0fd0821a93 | ||
|
|
c7c1b9da17 | ||
|
|
d67d307788 | ||
|
|
c057f18914 | ||
|
|
7a5b425dbb | ||
|
|
9b22739977 | ||
|
|
12e0869e0a | ||
|
|
0039ab8704 | ||
|
|
7da389db14 | ||
|
|
1f85797768 | ||
|
|
3c55703718 | ||
|
|
e3734c2d94 | ||
|
|
afc571e331 | ||
|
|
4549d07a6c | ||
|
|
acc220729b | ||
|
|
b27f64c3b1 | ||
|
|
1f7a09a561 | ||
|
|
f0b15c3f94 | ||
|
|
cc03d3029d | ||
|
|
ef2d24c5ff | ||
|
|
6a69d1bcb4 | ||
|
|
ea1e11d690 | ||
|
|
65b51fa6f5 | ||
|
|
dae31cedf6 | ||
|
|
6179f997c9 | ||
|
|
8cb083c29a | ||
|
|
7dd2434ea9 | ||
|
|
66ca952a1d | ||
|
|
d6fef1180f | ||
|
|
32451165ba | ||
|
|
2c806b2d4e | ||
|
|
a8dadfdfff | ||
|
|
4524b4289c | ||
|
|
67010e8f11 | ||
|
|
245ee7699a | ||
|
|
25dfb3c5b9 | ||
|
|
52709f279b | ||
|
|
13d6437638 | ||
|
|
7a3505070e | ||
|
|
7d79603d08 | ||
|
|
7890a8ae97 | ||
|
|
c73e149f43 | ||
|
|
2f72766aac | ||
|
|
43d915d09c | ||
|
|
3444b07f6a | ||
|
|
3cfb1c5b3e | ||
|
|
150736b170 | ||
|
|
1f325a36d6 | ||
|
|
bdc8f6ef82 | ||
|
|
d365e4b949 | ||
|
|
4f4a3ba87b | ||
|
|
7ceeaa5f3f | ||
|
|
6f968275c1 | ||
|
|
245b7a0d2a | ||
|
|
13b1007c1c | ||
|
|
c164908aac | ||
|
|
1dd28f124a | ||
|
|
149483ef21 | ||
|
|
0a689564ce | ||
|
|
facc6bc074 | ||
|
|
41224c9faf | ||
|
|
14548f5679 | ||
|
|
d31d0b2487 | ||
|
|
1366872acb | ||
|
|
40fcd23d87 | ||
|
|
ba7d09ee91 | ||
|
|
b0fa4eb3b7 | ||
|
|
a8bf163355 | ||
|
|
f81730c689 | ||
|
|
a830fe8b63 | ||
|
|
05c116271e | ||
|
|
a08f89813e | ||
|
|
87fa35dea0 | ||
|
|
4ed644313a | ||
|
|
9fdd1615bd | ||
|
|
4ab220f189 | ||
|
|
adef187685 | ||
|
|
0e5a443e9b | ||
|
|
4961ad6e8d | ||
|
|
e056f1ca0a | ||
|
|
9d43fd7a35 | ||
|
|
45bafb37fe | ||
|
|
3554f3c6ac | ||
|
|
10d4cf4a9d | ||
|
|
7a1621aa37 | ||
|
|
22a5e67c69 | ||
|
|
8737ba218a | ||
|
|
98e0a35f0c | ||
|
|
21500f3cab | ||
|
|
750d87937a | ||
|
|
f78ffc9a5c | ||
|
|
48b789d268 | ||
|
|
a765347cba | ||
|
|
21fe4c920d | ||
|
|
d35505b83a | ||
|
|
930d1370ce | ||
|
|
4f01b9b2d6 | ||
|
|
79ae548463 | ||
|
|
08120db4b4 | ||
|
|
11d2d979cc | ||
|
|
3822609afe | ||
|
|
dd057ca20f | ||
|
|
42403c9f51 | ||
|
|
9eb6b11fe0 | ||
|
|
8c02988330 | ||
|
|
fd7223a259 | ||
|
|
b22560852f | ||
|
|
3498720e8c | ||
|
|
457aed221b | ||
|
|
d6fb68d8e7 | ||
|
|
0e6c15eb8b | ||
|
|
485124bfef | ||
|
|
3517d1fd00 | ||
|
|
7d80f08e1c | ||
|
|
ff0af88299 | ||
|
|
ba08959d39 | ||
|
|
050aab96f7 | ||
|
|
afcdfae5a1 | ||
|
|
8908cce24f | ||
|
|
31447cb6cf | ||
|
|
884ab800f5 | ||
|
|
6e87103114 | ||
|
|
c3b8c213d3 | ||
|
|
33f50a0eb9 | ||
|
|
3f309bc92d | ||
|
|
8315b8d335 | ||
|
|
902c99aca2 | ||
|
|
f4fc20a1c8 | ||
|
|
0690c45558 | ||
|
|
699fd9ac02 | ||
|
|
b01db5ca2a | ||
|
|
4fdc9c67ad | ||
|
|
395ed0d58e | ||
|
|
bcad08260c | ||
|
|
06be6d52b2 | ||
|
|
7ec896b8b0 | ||
|
|
2717a94db5 | ||
|
|
2ea20e3d19 | ||
|
|
94d939ba67 | ||
|
|
620af0aec0 | ||
|
|
2299d82b92 | ||
|
|
25dbe61f64 | ||
|
|
ecd183156a | ||
|
|
3f0cb7e799 | ||
|
|
7b209c9733 | ||
|
|
dfd490afc8 | ||
|
|
92564a3a09 | ||
|
|
172cfceed7 |
No files matched your search
+1
-3
@@ -1,5 +1,3 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: retrooper
|
||||
custom: ['https://paypal.me/retrooperdev']
|
||||
github: [retrooper]
|
||||
@@ -8,16 +8,19 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Validate gradle wrapper
|
||||
uses: gradle/actions/wrapper-validation@v3
|
||||
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v3
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '21'
|
||||
distribution: 'adopt'
|
||||
cache: 'gradle'
|
||||
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
|
||||
settings-path: ${{ github.workspace }} # location for the settings.xml file
|
||||
|
||||
@@ -25,37 +28,43 @@ jobs:
|
||||
run: chmod +x gradlew && ./gradlew build
|
||||
|
||||
- name: Upload build artifacts api
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: api-build
|
||||
path: api/build/libs
|
||||
|
||||
- name: Upload build artifacts spigot
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: spigot-build
|
||||
path: spigot/build/libs
|
||||
|
||||
- name: Upload build artifacts netty-common
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: netty-common-build
|
||||
path: netty-common/build/libs
|
||||
|
||||
- name: Upload build artifacts bungeecord
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: bungeecord-build
|
||||
path: bungeecord/build/libs
|
||||
|
||||
- name: Upload build artifacts velocity
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: velocity-build
|
||||
path: velocity/build/libs
|
||||
|
||||
- name: Upload build artifacts fabric
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fabric-build
|
||||
path: fabric/build/libs
|
||||
path: fabric/build/libs
|
||||
|
||||
- name: Upload build artifacts sponge
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: sponge-build
|
||||
path: sponge/build/libs
|
||||
@@ -1,33 +1,42 @@
|
||||
# packetevents
|
||||
<!--suppress HtmlDeprecatedAttribute -->
|
||||
<div align="center">
|
||||
<h2><i>packetevents</i></h2>
|
||||
<h3><i>Precision meets performance—a powerful tool for mastering Minecraft packet manipulation with speed and finesse.</i></h3>
|
||||
<a href="https://github.com/retrooper/packetevents/actions"><img src="https://img.shields.io/github/actions/workflow/status/retrooper/packetevents/gradle-publish.yml?style=for-the-badge&logo=github"></a>
|
||||
<a href="https://discord.gg/DVHxPPxHZc"><img src="https://img.shields.io/discord/721686193061888071?color=5562e9&logo=discord&logoColor=white&style=for-the-badge"></a>
|
||||
<img src="https://img.shields.io/github/license/retrooper/packetevents?style=for-the-badge&logo=github">
|
||||
<a href="https://bstats.org/plugin/bukkit/packetevents/11327"><img src="https://img.shields.io/bstats/servers/11327?style=for-the-badge"></a>
|
||||
<a href="https://github.com/retrooper/packetevents/releases"><img src="https://img.shields.io/github/downloads/retrooper/packetevents/total.svg?style=for-the-badge&logo=github"></a>
|
||||
</div>
|
||||
<h3>Resources</h3>
|
||||
|
||||
[](https://github.com/retrooper/packetevents/blob/2.0/LICENSE) [](https://github.com/retrooper/packetevents/actions) [](https://discord.gg/prqzNg9tRU)
|
||||
- [Read documentation](https://docs.packetevents.com/)
|
||||
- [Getting Started](https://docs.packetevents.com/getting-started)
|
||||
- [JavaDocs](https://javadocs.packetevents.com)
|
||||
- [Releases](https://github.com/retrooper/packetevents/releases/)
|
||||
- [GitHub](https://github.com/retrooper/packetevents/releases/)
|
||||
- [Modrinth](https://modrinth.com/plugin/packetevents)
|
||||
- [SpigotMC](https://www.spigotmc.org/resources/packetevents-api.80279/)
|
||||
- [Development Builds](https://ci.codemc.io/job/retrooper/job/packetevents)
|
||||
- [Statistics](https://bstats.org/plugin/bukkit/packetevents/11327)
|
||||
|
||||
PacketEvents is a fast and efficient multi-platform packet processing library. Our packet wrappers are easy to use with multi-version support. With our API you can write code that runs on Spigot, BungeeCord, Velocity, and Fabric! Switch to PacketEvents today by joining \
|
||||
our [Discord Server](https://discord.me/packetevents) for help.
|
||||
<h3>Sponsors</h3>
|
||||
|
||||
### Links
|
||||
* [Find release builds on Modrinth](https://modrinth.com/plugin/packetevents)
|
||||
* [Find development builds on Jenkins](https://ci.codemc.io/job/retrooper/job/packetevents)
|
||||
* [View documentation on our JavaDocs Page](https://packetevents.github.io/javadocs)
|
||||
<i>Thanks to the following sponsors for supporting this project:</i>
|
||||
|
||||
### Setup
|
||||
[How to Setup PacketEvents](https://github.com/retrooper/packetevents/wiki/Depending-on-pre%E2%80%90built-PacketEvents)
|
||||
<a href="https://pebblehost.com"><img src="https://pebblehost.com/src/img/logos/main-old.png" width=150><br>
|
||||
|
||||
### Examples / How to use PacketEvents
|
||||
[Example repository](https://github.com/retrooper/packetevents-example)
|
||||
<a href="https://www.ej-technologies.com"><img src="https://www.ej-technologies.com/images/product_banners/jprofiler_small.png"><br>
|
||||
|
||||
### Sponsorships
|
||||
[](https://www.ej-technologies.com/products/jprofiler/overview.html)
|
||||
<a href="https://github.com/radstevee"><img src="https://github.com/radstevee.png" width="50px" alt="radstevee"/></a><br>
|
||||
|
||||
### Statistics
|
||||
PacketEvents optionally collects statistics using [bStats](https://bstats.org/)\
|
||||
Check out our [bStats page](https://bstats.org/plugin/bukkit/packetevents/11327)
|
||||
<h3>Credits</h3>
|
||||
|
||||
### Credit to these projects
|
||||
[wiki.vg/Protocol](https://wiki.vg/Protocol)\
|
||||
[netty](https://github.com/netty/netty)\
|
||||
[gson](https://github.com/google/gson)\
|
||||
[adventure](https://github.com/KyoriPowered/adventure)\
|
||||
<i>Here are some projects that we are heavily inspired by, thus we have integrated</i>\
|
||||
<i>small portions of their code into our work.</i>
|
||||
|
||||
[Protocol Documentation for the Minecraft Java Edition](https://wiki.vg/Protocol)\
|
||||
[ViaVersion](https://github.com/ViaVersion/ViaVersion)\
|
||||
[ProtocolSupport](https://github.com/ProtocolSupport/ProtocolSupport)\
|
||||
[adventure](https://github.com/KyoriPowered/adventure)\
|
||||
[MCProtocolLib](https://github.com/GeyserMC/MCProtocolLib/)
|
||||
+26
-5
@@ -21,6 +21,7 @@ java {
|
||||
|
||||
dependencies {
|
||||
compileOnlyApi(libs.bundles.adventure)
|
||||
compileOnlyApi(libs.bundles.adventure.serializers)
|
||||
implementation(libs.adventure.api)
|
||||
api(project(":patch:adventure-text-serializer-gson", "shadow")) {
|
||||
excludeAdventure()
|
||||
@@ -37,6 +38,7 @@ dependencies {
|
||||
testImplementation(testlibs.mockbukkit)
|
||||
testImplementation(testlibs.slf4j)
|
||||
testImplementation(testlibs.bundles.junit)
|
||||
testImplementation(libs.netty)
|
||||
}
|
||||
|
||||
mappingCompression {
|
||||
@@ -47,7 +49,13 @@ mappingCompression {
|
||||
compress("block/legacy_block_mappings.json")
|
||||
compress("block/modern_block_mappings.json")
|
||||
|
||||
compress("enchantment/enchantment_type_data.json")
|
||||
|
||||
compress("item/item_base_components.json")
|
||||
|
||||
compress("stats/statistics.json")
|
||||
|
||||
compress("world/biome_data.json")
|
||||
}
|
||||
|
||||
with<JsonArrayCompressionStrategy> {
|
||||
@@ -60,23 +68,34 @@ mappingCompression {
|
||||
|
||||
compress("command/argument_parser_mappings.json")
|
||||
|
||||
compress("damage/damagetype_mappings.json")
|
||||
|
||||
compress("enchantment/effect_component_type.json")
|
||||
|
||||
compress("entity/entity_data_type_mappings.json")
|
||||
compress("entity/painting_mappings.json")
|
||||
compress("entity/wolf_variant_mappings.json")
|
||||
|
||||
compress("item/item_armor_material_mappings.json")
|
||||
compress("item/consume_effect_type_mappings.json")
|
||||
compress("item/equipment_asset_mappings.json")
|
||||
compress("item/item_banner_pattern_mappings.json")
|
||||
compress("item/item_component_mappings.json")
|
||||
compress("item/item_instrument_mappings.json")
|
||||
compress("item/item_jukebox_song_mappings.json")
|
||||
compress("item/item_map_decoration_type_mappings.json")
|
||||
compress("item/item_potion_mappings.json")
|
||||
compress("item/item_trim_material_mappings.json")
|
||||
compress("item/item_trim_pattern_mappings.json")
|
||||
compress("item/recipe_book_category.json")
|
||||
compress("item/recipe_display_types.json")
|
||||
compress("item/recipe_serializer_mappings.json")
|
||||
compress("item/recipe_slot_display_types.json")
|
||||
|
||||
compress("particle/particle_type_mappings.json")
|
||||
|
||||
compress("sound/sound_mappings.json")
|
||||
|
||||
compress("world/biome_mappings.json")
|
||||
compress("world/world_position_source_mappings.json")
|
||||
}
|
||||
|
||||
@@ -88,15 +107,17 @@ mappingCompression {
|
||||
compress("entity/legacy_entity_type_mappings.json")
|
||||
|
||||
compress("item/item_type_mappings.json")
|
||||
|
||||
compress("world/dimension_type_mappings.json")
|
||||
}
|
||||
}
|
||||
|
||||
tasks {
|
||||
assemble {
|
||||
setDependsOn(dependsOn.filterNot { it == "shadowNoAdventure" })
|
||||
}
|
||||
|
||||
javadoc {
|
||||
setDestinationDir(file("${project.layout.buildDirectory.asFile.get()}/docs/javadoc"))
|
||||
options {
|
||||
(this as CoreJavadocOptions).addBooleanOption("Xdoclint:none", true)
|
||||
}
|
||||
mustRunAfter(generateVersionsFile)
|
||||
}
|
||||
|
||||
|
||||
@@ -34,22 +34,22 @@ import com.github.retrooper.packetevents.util.updatechecker.UpdateChecker;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public abstract class PacketEventsAPI<T> {
|
||||
private static final EventManager EVENT_MANAGER = new EventManager();
|
||||
private static final PacketEventsSettings SETTINGS = new PacketEventsSettings();
|
||||
private static final UpdateChecker UPDATE_CHECKER = new UpdateChecker();
|
||||
private static final LogManager LOG_MANAGER = new LogManager();
|
||||
private final EventManager eventManager = new EventManager();
|
||||
private final PacketEventsSettings settings = new PacketEventsSettings();
|
||||
private final UpdateChecker updateChecker = new UpdateChecker();
|
||||
private final LogManager logManager = new LogManager();
|
||||
private static final Logger LOGGER = Logger.getLogger(PacketEventsAPI.class.getName());
|
||||
|
||||
public EventManager getEventManager() {
|
||||
return EVENT_MANAGER;
|
||||
return eventManager;
|
||||
}
|
||||
|
||||
public PacketEventsSettings getSettings() {
|
||||
return SETTINGS;
|
||||
return settings;
|
||||
}
|
||||
|
||||
public UpdateChecker getUpdateChecker() {
|
||||
return UPDATE_CHECKER;
|
||||
return updateChecker;
|
||||
}
|
||||
|
||||
public PEVersion getVersion() {
|
||||
@@ -62,7 +62,7 @@ public abstract class PacketEventsAPI<T> {
|
||||
}
|
||||
|
||||
public LogManager getLogManager() {
|
||||
return LOG_MANAGER;
|
||||
return logManager;
|
||||
}
|
||||
|
||||
public abstract void load();
|
||||
@@ -75,6 +75,8 @@ public abstract class PacketEventsAPI<T> {
|
||||
|
||||
public abstract void terminate();
|
||||
|
||||
public abstract boolean isTerminated();
|
||||
|
||||
public abstract T getPlugin();
|
||||
|
||||
public abstract ServerManager getServerManager();
|
||||
|
||||
@@ -23,12 +23,36 @@ import com.github.retrooper.packetevents.exception.InvalidHandshakeException;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
* Class for event managing. Implements both, internal and API methods.
|
||||
*
|
||||
* @apiNote It is highly recommended to register the event listeners at server start-up,
|
||||
* without frequent modifications during runtime, since this class needs to recalculate all of
|
||||
* its event listeners during any modifications. In other words, it assumes that reads (events fired)
|
||||
* greatly outnumber writes (listeners modifications). If your case requires frequent listener modifications,
|
||||
* open a pull request on GitHub and describe your case.
|
||||
*
|
||||
* @author retrooper
|
||||
* @author ShadowOfHeaven (optimization)
|
||||
*
|
||||
*/
|
||||
|
||||
public class EventManager {
|
||||
private final Map<PacketListenerPriority, Set<PacketListenerCommon>> listenersMap =
|
||||
Collections.synchronizedMap(new EnumMap<>(PacketListenerPriority.class));
|
||||
|
||||
//Using a ConcurrentHashMap is faster and more secure here, compared to Collections.synchronizedMap(new EnumMap<>(PacketListenerPriority.class))
|
||||
//This is mainly due to:
|
||||
//1. On each modification Collections.synchronizedMap synchronizes the whole Map object, while ConcurrentHashMap only it's internal, currently modified Node
|
||||
//2. ConcurrentHashMap won't fail in a multi-thread environment, while Collections.synchronizedMap is said to have a lot of potential problems,
|
||||
//being a generalized method for synchronization
|
||||
private final Map<PacketListenerPriority, Set<PacketListenerCommon>> listenersMap = new ConcurrentHashMap<>();
|
||||
//Since reads greatly outnumber writes, create an array for the best possible iteration time
|
||||
//Updated as a whole on writes, no index modifications are allowed
|
||||
private volatile PacketListenerCommon[] listeners = new PacketListenerCommon[0];
|
||||
|
||||
|
||||
/**
|
||||
* Call the PacketEvent.
|
||||
@@ -43,32 +67,43 @@ public class EventManager {
|
||||
callEvent(event, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call the PacketEvent.
|
||||
* This method processes the event on all the registered dynamic packet event listeners.
|
||||
* The {@link PacketListenerPriority#LOWEST} prioritized listeners will be processing first,
|
||||
* the {@link PacketListenerPriority#MONITOR} will be processing last and can
|
||||
* be the final decider whether the event has been cancelled or not.
|
||||
*
|
||||
* @param event {@link PacketEvent}
|
||||
* @param postCallListenerAction The action to be ran after all the listeners have finished processing
|
||||
*/
|
||||
public void callEvent(PacketEvent event, @Nullable Runnable postCallListenerAction) {
|
||||
for (PacketListenerPriority priority : PacketListenerPriority.values()) {
|
||||
Set<PacketListenerCommon> listeners = listenersMap.get(priority);
|
||||
if (listeners != null) {
|
||||
for (PacketListenerCommon listener : listeners) {
|
||||
try {
|
||||
event.call(listener);
|
||||
} catch (Exception t) {
|
||||
// ignore handshake exceptions
|
||||
if (t.getClass() != InvalidHandshakeException.class) {
|
||||
PacketEvents.getAPI().getLogger().log(Level.WARNING, "PacketEvents caught an unhandled exception while calling your listener.", t);
|
||||
}
|
||||
}
|
||||
if (postCallListenerAction != null) {
|
||||
postCallListenerAction.run();
|
||||
}
|
||||
for (PacketListenerCommon listener : listeners) {
|
||||
try {
|
||||
event.call(listener);
|
||||
} catch (Exception t) {
|
||||
// ignore handshake exceptions
|
||||
if (t.getClass() != InvalidHandshakeException.class) {
|
||||
PacketEvents.getAPI().getLogger().log(Level.WARNING, "PacketEvents caught an unhandled exception while calling your listener.", t);
|
||||
}
|
||||
}
|
||||
if (postCallListenerAction != null) {
|
||||
postCallListenerAction.run();
|
||||
}
|
||||
}
|
||||
// For performance reasons, we don't want to re-encode the packet if it's not needed.
|
||||
if (event instanceof ProtocolPacketEvent && !((ProtocolPacketEvent<?>) event).needsReEncode()) {
|
||||
((ProtocolPacketEvent<?>) event).setLastUsedWrapper(null);
|
||||
if (event instanceof ProtocolPacketEvent && !((ProtocolPacketEvent) event).needsReEncode()) {
|
||||
((ProtocolPacketEvent) event).setLastUsedWrapper(null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the dynamic packet event listener.
|
||||
*
|
||||
* @param listener {@link PacketListenerCommon}
|
||||
* @param priority {@link PacketListenerPriority}
|
||||
*/
|
||||
public PacketListenerCommon registerListener(PacketListener listener, PacketListenerPriority priority) {
|
||||
PacketListenerCommon packetListenerAbstract = listener.asAbstract(priority);
|
||||
return registerListener(packetListenerAbstract);
|
||||
@@ -80,12 +115,8 @@ public class EventManager {
|
||||
* @param listener {@link PacketListenerCommon}
|
||||
*/
|
||||
public PacketListenerCommon registerListener(PacketListenerCommon listener) {
|
||||
Set<PacketListenerCommon> listenerSet = listenersMap.get(listener.getPriority());
|
||||
if (listenerSet == null) {
|
||||
listenerSet = new CopyOnWriteArraySet<>();
|
||||
}
|
||||
listenerSet.add(listener);
|
||||
listenersMap.put(listener.getPriority(), listenerSet);
|
||||
this.registerListenerNoRecalculation(listener);
|
||||
this.recalculateListeners();
|
||||
return listener;
|
||||
}
|
||||
|
||||
@@ -96,21 +127,22 @@ public class EventManager {
|
||||
*/
|
||||
public PacketListenerCommon[] registerListeners(PacketListenerCommon... listeners) {
|
||||
for (PacketListenerCommon listener : listeners) {
|
||||
registerListener(listener);
|
||||
this.registerListenerNoRecalculation(listener);
|
||||
}
|
||||
this.recalculateListeners();
|
||||
return listeners;
|
||||
}
|
||||
|
||||
public void unregisterListener(PacketListenerCommon listener) {
|
||||
Set<PacketListenerCommon> listenerSet = listenersMap.get(listener.getPriority());
|
||||
if (listenerSet == null) return;
|
||||
listenerSet.remove(listener);
|
||||
if (this.unregisterListenerNoRecalculation(listener)) this.recalculateListeners();
|
||||
}
|
||||
|
||||
public void unregisterListeners(PacketListenerCommon... listeners) {
|
||||
boolean modified = false;
|
||||
for (PacketListenerCommon listener : listeners) {
|
||||
unregisterListener(listener);
|
||||
modified |= this.unregisterListenerNoRecalculation(listener);//OR - at least one of these needs to be true to return true, meaning the boolean will permanently stay true if once set so
|
||||
}
|
||||
if (modified) this.recalculateListeners();
|
||||
}
|
||||
|
||||
|
||||
@@ -118,6 +150,36 @@ public class EventManager {
|
||||
* Unregister all dynamic packet event listeners.
|
||||
*/
|
||||
public void unregisterAllListeners() {
|
||||
listenersMap.clear();
|
||||
this.listenersMap.clear();
|
||||
synchronized (this) {//like booky10 said, the synchronization is necessary here
|
||||
this.listeners = new PacketListenerCommon[0];
|
||||
}
|
||||
}
|
||||
|
||||
//Needs to be synchronized in order to avoid race conditions (for example where the 'listeners' variable
|
||||
//is overridden by its non-up-to-date value, simply because it finished a bit later than the most recent update)
|
||||
private void recalculateListeners() {
|
||||
synchronized (this) {
|
||||
List<PacketListenerCommon> list = new ArrayList<>();
|
||||
//adds from LOWEST to MONITOR, so in the correct order
|
||||
for (PacketListenerPriority priority : PacketListenerPriority.values()) {
|
||||
Set<PacketListenerCommon> set = this.listenersMap.get(priority);
|
||||
if (set != null) list.addAll(set);
|
||||
}
|
||||
this.listeners = list.toArray(new PacketListenerCommon[0]);
|
||||
}
|
||||
}
|
||||
|
||||
//Internal registration methods, specifically separated for lesser overhead when registering an array of Listeners
|
||||
|
||||
private void registerListenerNoRecalculation(PacketListenerCommon listener) {
|
||||
Set<PacketListenerCommon> listenerSet = this.listenersMap.computeIfAbsent(listener.getPriority(), p -> new CopyOnWriteArraySet<>());
|
||||
listenerSet.add(listener);
|
||||
}
|
||||
|
||||
//Returns true if the listener was removed, so a modification occurred
|
||||
private boolean unregisterListenerNoRecalculation(PacketListenerCommon listener) {
|
||||
Set<PacketListenerCommon> listenerSet = this.listenersMap.get(listener.getPriority());
|
||||
return listenerSet != null && listenerSet.remove(listener);
|
||||
}
|
||||
}
|
||||
+9
-7
@@ -30,8 +30,7 @@ package com.github.retrooper.packetevents.event;
|
||||
*/
|
||||
public enum PacketListenerPriority {
|
||||
/**
|
||||
* Listener is of very low importance.
|
||||
* This listener will be ran first.
|
||||
* This listener will be run first and has little say in the outcome of events.
|
||||
*/
|
||||
LOWEST,
|
||||
|
||||
@@ -41,8 +40,11 @@ public enum PacketListenerPriority {
|
||||
LOW,
|
||||
|
||||
/**
|
||||
* Default listener priority.
|
||||
* Listener is neither important nor unimportant and may run normally.
|
||||
* The normal listener priority.
|
||||
* If possible, always pick this.
|
||||
* It allows other projects to easily overturn your decisions.
|
||||
* Moreover, it is pretty bold to assume that your project should
|
||||
* always have the final say.
|
||||
*/
|
||||
NORMAL,
|
||||
|
||||
@@ -52,13 +54,13 @@ public enum PacketListenerPriority {
|
||||
HIGH,
|
||||
|
||||
/**
|
||||
* Listener is of critical importance and wants to decide the cancellation of an event.
|
||||
* Listener is of critical importance. Use this to decide the final state of packets.
|
||||
*/
|
||||
HIGHEST,
|
||||
|
||||
/**
|
||||
* Listener is purely trying to decide the cancellation of an event.
|
||||
* This listener should be ran last.
|
||||
* Only use this priority if you want to perform logic based on the outcome of an event.
|
||||
* Please do not modify packets in this stage.
|
||||
*/
|
||||
MONITOR;
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
package com.github.retrooper.packetevents.event;
|
||||
|
||||
import com.github.retrooper.packetevents.event.simple.*;
|
||||
import com.github.retrooper.packetevents.exception.PacketProcessException;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.netty.buffer.ByteBufHelper;
|
||||
@@ -26,7 +25,7 @@ import com.github.retrooper.packetevents.protocol.PacketSide;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketTypeCommon;
|
||||
import com.github.retrooper.packetevents.protocol.player.User;
|
||||
|
||||
public class PacketReceiveEvent extends ProtocolPacketEvent<Object> {
|
||||
public class PacketReceiveEvent extends ProtocolPacketEvent {
|
||||
protected PacketReceiveEvent(Object channel, User user, Object player, Object rawByteBuf,
|
||||
boolean autoProtocolTranslation) throws PacketProcessException {
|
||||
super(PacketSide.CLIENT, channel, user, player, rawByteBuf, autoProtocolTranslation);
|
||||
|
||||
@@ -29,7 +29,7 @@ import com.github.retrooper.packetevents.protocol.player.User;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class PacketSendEvent extends ProtocolPacketEvent<Object> {
|
||||
public class PacketSendEvent extends ProtocolPacketEvent {
|
||||
private List<Runnable> tasksAfterSend = null;
|
||||
|
||||
protected PacketSendEvent(Object channel, User user, Object player, Object rawByteBuf,
|
||||
|
||||
@@ -24,11 +24,11 @@ package com.github.retrooper.packetevents.event;
|
||||
* @author retrooper
|
||||
* @since 1.6.9
|
||||
*/
|
||||
public interface PlayerEvent<T> {
|
||||
public interface PlayerEvent {
|
||||
/**
|
||||
* Associated player.
|
||||
*
|
||||
* @return Player.
|
||||
*/
|
||||
T getPlayer();
|
||||
<T> T getPlayer();
|
||||
}
|
||||
@@ -36,14 +36,15 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class ProtocolPacketEvent<T> extends PacketEvent implements PlayerEvent<T>, CancellableEvent, UserEvent {
|
||||
public abstract class ProtocolPacketEvent extends PacketEvent implements PlayerEvent, CancellableEvent, UserEvent {
|
||||
private final Object channel;
|
||||
private final ConnectionState connectionState;
|
||||
private final User user;
|
||||
private final T player;
|
||||
private final Object player;
|
||||
private Object byteBuf;
|
||||
private final int packetID;
|
||||
private final PacketTypeCommon packetType;
|
||||
@@ -55,7 +56,7 @@ public abstract class ProtocolPacketEvent<T> extends PacketEvent implements Play
|
||||
private boolean needsReEncode = PacketEvents.getAPI().getSettings().reEncodeByDefault();
|
||||
|
||||
public ProtocolPacketEvent(PacketSide packetSide, Object channel,
|
||||
User user, T player, Object byteBuf,
|
||||
User user, Object player, Object byteBuf,
|
||||
boolean autoProtocolTranslation) throws PacketProcessException {
|
||||
this.channel = channel;
|
||||
this.user = user;
|
||||
@@ -92,7 +93,7 @@ public abstract class ProtocolPacketEvent<T> extends PacketEvent implements Play
|
||||
}
|
||||
|
||||
public ProtocolPacketEvent(int packetID, PacketTypeCommon packetType, ServerVersion serverVersion, Object channel,
|
||||
User user, T player, Object byteBuf) {
|
||||
User user, Object player, Object byteBuf) {
|
||||
this.channel = channel;
|
||||
this.user = user;
|
||||
this.player = player;
|
||||
@@ -123,8 +124,15 @@ public abstract class ProtocolPacketEvent<T> extends PacketEvent implements Play
|
||||
return channel;
|
||||
}
|
||||
|
||||
public SocketAddress getAddress() {
|
||||
return ChannelHelper.remoteAddress(this.channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* <strong>WARNING:</strong> This doesn't support local addresses or unix sockets.
|
||||
*/
|
||||
public InetSocketAddress getSocketAddress() {
|
||||
return (InetSocketAddress) ChannelHelper.remoteAddress(channel);
|
||||
return (InetSocketAddress) this.getAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -133,8 +141,8 @@ public abstract class ProtocolPacketEvent<T> extends PacketEvent implements Play
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getPlayer() {
|
||||
return player;
|
||||
public <T> T getPlayer() {
|
||||
return (T) player;
|
||||
}
|
||||
|
||||
public ConnectionState getConnectionState() {
|
||||
@@ -213,7 +221,7 @@ public abstract class ProtocolPacketEvent<T> extends PacketEvent implements Play
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProtocolPacketEvent<?> clone() {
|
||||
public ProtocolPacketEvent clone() {
|
||||
return this instanceof PacketReceiveEvent ? ((PacketReceiveEvent) this).clone()
|
||||
: ((PacketSendEvent) this).clone();
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ package com.github.retrooper.packetevents.event;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.player.User;
|
||||
|
||||
public class UserLoginEvent extends PacketEvent implements CallableEvent, UserEvent, PlayerEvent<Object> {
|
||||
public class UserLoginEvent extends PacketEvent implements CallableEvent, UserEvent, PlayerEvent {
|
||||
private final User user;
|
||||
private final Object player;
|
||||
|
||||
@@ -35,8 +35,8 @@ public class UserLoginEvent extends PacketEvent implements CallableEvent, UserEv
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getPlayer() {
|
||||
return player;
|
||||
public <T> T getPlayer() {
|
||||
return (T) player;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -18,9 +18,11 @@
|
||||
|
||||
package com.github.retrooper.packetevents.injector;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.PacketSide;
|
||||
import com.github.retrooper.packetevents.protocol.player.User;
|
||||
|
||||
public interface ChannelInjector {
|
||||
|
||||
default boolean isServerBound() {
|
||||
return true;
|
||||
}
|
||||
@@ -34,4 +36,8 @@ public interface ChannelInjector {
|
||||
void setPlayer(Object channel, Object player);
|
||||
|
||||
boolean isProxy();
|
||||
|
||||
default PacketSide getPacketSide() {
|
||||
return PacketSide.SERVER;
|
||||
}
|
||||
}
|
||||
+29
-95
@@ -26,31 +26,20 @@ import com.github.retrooper.packetevents.event.PacketSendEvent;
|
||||
import com.github.retrooper.packetevents.manager.protocol.ProtocolManager;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.protocol.ConnectionState;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTInt;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTList;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTType;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.player.User;
|
||||
import com.github.retrooper.packetevents.protocol.player.UserProfile;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.util.LogManager;
|
||||
import com.github.retrooper.packetevents.util.mappings.SynchronizedRegistriesHandler;
|
||||
import com.github.retrooper.packetevents.wrapper.configuration.server.WrapperConfigServerRegistryData;
|
||||
import com.github.retrooper.packetevents.wrapper.configuration.server.WrapperConfigServerRegistryData.RegistryElement;
|
||||
import com.github.retrooper.packetevents.wrapper.handshaking.client.WrapperHandshakingClientHandshake;
|
||||
import com.github.retrooper.packetevents.wrapper.login.server.WrapperLoginServerLoginSuccess;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerJoinGame;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerRespawn;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.List;
|
||||
|
||||
public class InternalPacketListener extends PacketListenerAbstract {
|
||||
|
||||
private static final ResourceLocation DIMENSION_TYPE_REGISTRY_KEY =
|
||||
ResourceLocation.minecraft("dimension_type");
|
||||
|
||||
public InternalPacketListener() {
|
||||
this(PacketListenerPriority.LOWEST);
|
||||
}
|
||||
@@ -92,94 +81,37 @@ public class InternalPacketListener extends PacketListenerAbstract {
|
||||
}
|
||||
}
|
||||
|
||||
// The server sends dimension information in configuration phase >= 1.20.2
|
||||
// The server sends dimension information in configuration phase, since 1.20.2
|
||||
else if (event.getPacketType() == PacketType.Configuration.Server.REGISTRY_DATA) {
|
||||
WrapperConfigServerRegistryData registryData = new WrapperConfigServerRegistryData(event);
|
||||
WrapperConfigServerRegistryData packet = new WrapperConfigServerRegistryData(event);
|
||||
|
||||
// Store world data
|
||||
NBTCompound registryDataTag = registryData.getRegistryData();
|
||||
NBTList<NBTCompound> list = null;
|
||||
if (registryDataTag != null) { // <1.20.5
|
||||
//Handle dimension type
|
||||
NBTCompound dimensionTypes = registryDataTag
|
||||
.getCompoundTagOrNull(DIMENSION_TYPE_REGISTRY_KEY.toString());
|
||||
if (dimensionTypes == null) {
|
||||
dimensionTypes = registryDataTag
|
||||
.getCompoundTagOrNull(DIMENSION_TYPE_REGISTRY_KEY.getKey());
|
||||
}
|
||||
if (dimensionTypes != null) {
|
||||
list = dimensionTypes.getCompoundListTagOrNull("value");
|
||||
}
|
||||
if (list == null) {
|
||||
list = new NBTList<>(NBTType.COMPOUND);
|
||||
PacketEvents.getAPI().getLogger().warning("Can't find dimension type registry in registry data, "
|
||||
+ "this may cause issues; available registries: " + registryDataTag.getTags().keySet());
|
||||
}
|
||||
} else if (DIMENSION_TYPE_REGISTRY_KEY.equals(registryData.getRegistryKey())) { // >=1.20.5
|
||||
// remap to legacy format
|
||||
list = new NBTList<>(NBTType.COMPOUND);
|
||||
List<RegistryElement> elements = registryData.getElements();
|
||||
if (elements != null) {
|
||||
int i = 0;
|
||||
for (RegistryElement element : elements) {
|
||||
NBTCompound tag = new NBTCompound();
|
||||
tag.setTag("name", new NBTString(element.getId().toString()));
|
||||
tag.setTag("id", new NBTInt(i++));
|
||||
if (element.getData() != null) { // may be null because of known packs not being sent
|
||||
tag.setTag("element", element.getData());
|
||||
}
|
||||
list.addTag(tag);
|
||||
}
|
||||
}
|
||||
if (packet.getElements() != null) { // 1.20.2 to 1.20.5
|
||||
SynchronizedRegistriesHandler.handleRegistry(user, packet.getServerVersion().toClientVersion(),
|
||||
packet.getRegistryKey(), packet.getElements());
|
||||
}
|
||||
if (list != null) {
|
||||
user.setWorldNBT(list);
|
||||
if (packet.getRegistryData() != null) { // since 1.20.5
|
||||
SynchronizedRegistriesHandler.handleLegacyRegistries(user, packet.getServerVersion()
|
||||
.toClientVersion(), packet.getRegistryData());
|
||||
}
|
||||
}
|
||||
|
||||
// The server sends dimension information in login packet for >= 1.17 and < 1.20.2
|
||||
// The server sends registry info in login packet for 1.16 to 1.20.1
|
||||
else if (event.getPacketType() == PacketType.Play.Server.JOIN_GAME) {
|
||||
WrapperPlayServerJoinGame joinGame = new WrapperPlayServerJoinGame(event);
|
||||
user.setEntityId(joinGame.getEntityId());
|
||||
user.setDimension(joinGame.getDimension());
|
||||
if (event.getServerVersion().isOlderThanOrEquals(ServerVersion.V_1_16_5)) {
|
||||
return; // Fixed world height, no tags are sent to the client
|
||||
|
||||
if (joinGame.getDimensionCodec() != null) { // 1.16 to 1.20.1
|
||||
SynchronizedRegistriesHandler.handleLegacyRegistries(user, joinGame.getServerVersion().toClientVersion(),
|
||||
joinGame.getDimensionCodec());
|
||||
}
|
||||
|
||||
// Store world data
|
||||
NBTCompound dimensionCodec = joinGame.getDimensionCodec();
|
||||
if (dimensionCodec != null) {
|
||||
NBTList<NBTCompound> types = null;
|
||||
NBTCompound dimensionTypes = dimensionCodec
|
||||
.getCompoundTagOrNull(DIMENSION_TYPE_REGISTRY_KEY.toString());
|
||||
if (dimensionTypes == null) {
|
||||
dimensionTypes = dimensionCodec
|
||||
.getCompoundTagOrNull(DIMENSION_TYPE_REGISTRY_KEY.getKey());
|
||||
}
|
||||
if (dimensionTypes != null) { // account for dimension type registry somehow going missing
|
||||
types = dimensionTypes.getCompoundListTagOrNull("value");
|
||||
}
|
||||
if (types == null) {
|
||||
types = new NBTList<>(NBTType.COMPOUND);
|
||||
PacketEvents.getAPI().getLogger().warning("Can't find dimension type registry in join packet, "
|
||||
+ "this may cause issues; available registries: " + dimensionCodec.getTags().keySet());
|
||||
}
|
||||
user.setWorldNBT(types);
|
||||
}
|
||||
|
||||
// Update world height
|
||||
user.switchDimensionType(joinGame.getServerVersion(), joinGame.getDimension());
|
||||
user.setDimensionType(joinGame.getDimensionType());
|
||||
}
|
||||
|
||||
// Respawn is used to switch dimensions
|
||||
else if (event.getPacketType() == PacketType.Play.Server.RESPAWN) {
|
||||
WrapperPlayServerRespawn respawn = new WrapperPlayServerRespawn(event);
|
||||
user.setDimension(respawn.getDimension());
|
||||
if (event.getServerVersion().isOlderThanOrEquals(ServerVersion.V_1_16_5)) {
|
||||
return; // Fixed world height, no tags are sent to the client
|
||||
}
|
||||
|
||||
user.switchDimensionType(respawn.getServerVersion(), respawn.getDimension());
|
||||
WrapperPlayServerRespawn packet = new WrapperPlayServerRespawn(event);
|
||||
user.setDimensionType(packet.getDimensionType());
|
||||
} else if (event.getPacketType() == PacketType.Play.Server.CONFIGURATION_START) {
|
||||
user.setEncoderState(ConnectionState.CONFIGURATION);
|
||||
} else if (event.getPacketType() == PacketType.Configuration.Server.CONFIGURATION_END) {
|
||||
@@ -191,16 +123,18 @@ public class InternalPacketListener extends PacketListenerAbstract {
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
User user = event.getUser();
|
||||
if (event.getPacketType() == PacketType.Handshaking.Client.HANDSHAKE) {
|
||||
Object channel = event.getChannel();
|
||||
InetSocketAddress address = event.getSocketAddress();
|
||||
WrapperHandshakingClientHandshake handshake = new WrapperHandshakingClientHandshake(event);
|
||||
ConnectionState nextState = handshake.getNextConnectionState();
|
||||
ClientVersion clientVersion = handshake.getClientVersion();
|
||||
//Update client version for this event call(and user)
|
||||
WrapperHandshakingClientHandshake packet = new WrapperHandshakingClientHandshake(event);
|
||||
ClientVersion clientVersion = packet.getClientVersion();
|
||||
ConnectionState state = packet.getNextConnectionState();
|
||||
|
||||
LogManager logger = PacketEvents.getAPI().getLogManager();
|
||||
if (logger.isDebug()) {
|
||||
logger.debug("Processed handshake for " + event.getAddress() + ": "
|
||||
+ state.name() + " / " + packet.getClientVersion().getReleaseName());
|
||||
}
|
||||
|
||||
user.setClientVersion(clientVersion);
|
||||
PacketEvents.getAPI().getLogManager().debug("Processed " + address.getHostString() + ":" + address.getPort() + "'s client version. Client Version: " + clientVersion.getReleaseName());
|
||||
//Transition into LOGIN or STATUS connection state immediately, to remain in sync with vanilla
|
||||
user.setConnectionState(nextState);
|
||||
user.setConnectionState(state);
|
||||
} else if (event.getPacketType() == PacketType.Login.Client.LOGIN_SUCCESS_ACK) {
|
||||
user.setDecoderState(ConnectionState.CONFIGURATION);
|
||||
} else if (event.getPacketType() == PacketType.Play.Client.CONFIGURATION_ACK) {
|
||||
|
||||
+7
-4
@@ -104,10 +104,13 @@ public interface ProtocolManager {
|
||||
PacketWrapper<?>[] wrappers = PacketTransformationUtil.transform(wrapper);
|
||||
Object[] buffers = new Object[wrappers.length];
|
||||
for (int i = 0; i < wrappers.length; i++) {
|
||||
wrappers[i].prepareForSend(channel, outgoing);
|
||||
buffers[i] = wrappers[i].buffer;
|
||||
// Fix race condition when sending packets to multiple people (due to when the buffer is freed)
|
||||
wrappers[i].buffer = null;
|
||||
PacketWrapper<?> wrappper = wrappers[i];
|
||||
synchronized (wrappper.bufferLock) {
|
||||
wrappper.prepareForSend(channel, outgoing);
|
||||
buffers[i] = wrappper.buffer;
|
||||
// Fix race condition when sending packets to multiple people (due to when the buffer is freed)
|
||||
wrappper.buffer = null;
|
||||
}
|
||||
}
|
||||
return buffers;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,10 @@
|
||||
|
||||
package com.github.retrooper.packetevents.manager.server;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.player.User;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface ServerManager {
|
||||
/**
|
||||
* Get the server version.
|
||||
@@ -34,4 +38,20 @@ public interface ServerManager {
|
||||
default SystemOS getOS() {
|
||||
return SystemOS.getOS();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a platform-specific network-synchronized-registries cache key.
|
||||
* <p>
|
||||
* This tells packetevents, if a registry should be cached or read again. On
|
||||
* backend servers with global registries, this may be a constant value. On
|
||||
* proxy servers with per-server registries, this may be a value which depends
|
||||
* on the current server the {@link User} is on.
|
||||
*
|
||||
* @param user the {@link User} for which the registry gets read
|
||||
* @param version the version the packet is for
|
||||
* @return some value or null for no caching at all
|
||||
*/
|
||||
default @Nullable Object getRegistryCacheKey(User user, ClientVersion version) {
|
||||
return null; // no caching
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -34,7 +34,7 @@ public enum ServerVersion {
|
||||
//TODO Rename to MinecraftVersion?
|
||||
V_1_7_10(5),
|
||||
V_1_8(47), V_1_8_3(47), V_1_8_8(47),
|
||||
V_1_9(107), V_1_9_2(109), V_1_9_4(110),
|
||||
V_1_9(107), V_1_9_1(108), V_1_9_2(109), V_1_9_4(110),
|
||||
//1.10 and 1.10.1 are redundant
|
||||
V_1_10(210), V_1_10_1(210), V_1_10_2(210),
|
||||
V_1_11(315), V_1_11_2(316),
|
||||
@@ -49,7 +49,8 @@ public enum ServerVersion {
|
||||
V_1_19(759), V_1_19_1(760), V_1_19_2(760), V_1_19_3(761), V_1_19_4(762),
|
||||
//1.20 and 1.20.1 have the same protocol version. 1.20.3 and 1.20.4 have the same protocol version. 1.20.5 and 1.20.6 have the same protocol version
|
||||
V_1_20(763), V_1_20_1(763), V_1_20_2(764), V_1_20_3(765), V_1_20_4(765), V_1_20_5(766), V_1_20_6(766),
|
||||
V_1_21(767),
|
||||
//1.21 and 1.21.1 have the same protocol version. 1.21.2 and 1.21.3 have the same protocol version
|
||||
V_1_21(767), V_1_21_1(767), V_1_21_2(768), V_1_21_3(768), V_1_21_4(769),
|
||||
//TODO UPDATE Add server version constant
|
||||
ERROR(-1, true);
|
||||
|
||||
|
||||
@@ -18,7 +18,35 @@
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.attribute;
|
||||
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.MappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.util.MathUtil;
|
||||
|
||||
public interface Attribute extends MappedEntity {
|
||||
|
||||
@Override
|
||||
default ResourceLocation getName() {
|
||||
return this.getName(PacketEvents.getAPI().getServerManager().getVersion().toClientVersion());
|
||||
}
|
||||
|
||||
ResourceLocation getName(ClientVersion version);
|
||||
|
||||
default double sanitizeValue(double value) {
|
||||
return this.sanitizeValue(value, PacketEvents.getAPI().getServerManager().getVersion().toClientVersion());
|
||||
}
|
||||
|
||||
default double sanitizeValue(double value, ClientVersion version) {
|
||||
if (!Double.isNaN(value)) {
|
||||
return MathUtil.clamp(value, this.getMinValue(), this.getMaxValue());
|
||||
}
|
||||
return this.getMinValue();
|
||||
}
|
||||
|
||||
double getDefaultValue();
|
||||
|
||||
double getMinValue();
|
||||
|
||||
double getMaxValue();
|
||||
}
|
||||
+316
-76
@@ -20,98 +20,338 @@ package com.github.retrooper.packetevents.protocol.attribute;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.util.mappings.MappingHelper;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilder;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import com.github.retrooper.packetevents.util.mappings.VersionedRegistry;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
public final class Attributes {
|
||||
|
||||
public class Attributes {
|
||||
private static final VersionedRegistry<Attribute> REGISTRY = new VersionedRegistry<>(
|
||||
"attribute", "attribute/attribute_mappings");
|
||||
|
||||
private static final Map<String, Attribute> ATTRIBUTE_MAP = new HashMap<>();
|
||||
private static final Map<Byte, Map<Integer, Attribute>> ATTRIBUTE_ID_MAP = new HashMap<>();
|
||||
private static final TypesBuilder TYPES_BUILDER = new TypesBuilder("attribute/attribute_mappings");
|
||||
|
||||
public static Attribute define(String key) {
|
||||
TypesBuilderData data = TYPES_BUILDER.define(key);
|
||||
Attribute attribute = new Attribute() {
|
||||
@Override
|
||||
public ResourceLocation getName() {
|
||||
return data.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId(ClientVersion version) {
|
||||
return MappingHelper.getId(version, TYPES_BUILDER, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof Attribute) {
|
||||
return this.getName().equals(((Attribute) obj).getName());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
MappingHelper.registerMapping(TYPES_BUILDER, ATTRIBUTE_MAP, ATTRIBUTE_ID_MAP, attribute);
|
||||
return attribute;
|
||||
private Attributes() {
|
||||
}
|
||||
|
||||
private static Attribute define(
|
||||
String key, @Nullable String legacyPrefix,
|
||||
double def, double min, double max
|
||||
) {
|
||||
return REGISTRY.define(key, data ->
|
||||
new StaticAttribute(data, legacyPrefix, def, min, max));
|
||||
}
|
||||
|
||||
public static VersionedRegistry<Attribute> getRegistry() {
|
||||
return REGISTRY;
|
||||
}
|
||||
|
||||
// with minecraft:key
|
||||
public static Attribute getByName(String name) {
|
||||
return ATTRIBUTE_MAP.get(name);
|
||||
// "remapping" to support < 1.21.2
|
||||
String normedName = ResourceLocation.normString(name);
|
||||
if (normedName.startsWith(ResourceLocation.VANILLA_NAMESPACE + ":generic.")
|
||||
|| normedName.startsWith(ResourceLocation.VANILLA_NAMESPACE + ":player.")
|
||||
|| normedName.startsWith(ResourceLocation.VANILLA_NAMESPACE + ":zombie.")) {
|
||||
normedName = normedName.substring(name.indexOf('.') + 1);
|
||||
}
|
||||
return REGISTRY.getByName(normedName);
|
||||
}
|
||||
|
||||
public static Attribute getById(ClientVersion version, int id) {
|
||||
int index = TYPES_BUILDER.getDataIndex(version);
|
||||
Map<Integer, Attribute> idMap = ATTRIBUTE_ID_MAP.get((byte) index);
|
||||
return idMap.get(id);
|
||||
return REGISTRY.getById(version, id);
|
||||
}
|
||||
|
||||
public static final Attribute GENERIC_ARMOR = define("generic.armor");
|
||||
public static final Attribute GENERIC_ARMOR_TOUGHNESS = define("generic.armor_toughness");
|
||||
public static final Attribute GENERIC_ATTACK_DAMAGE = define("generic.attack_damage");
|
||||
public static final Attribute GENERIC_ATTACK_KNOCKBACK = define("generic.attack_knockback");
|
||||
public static final Attribute GENERIC_ATTACK_SPEED = define("generic.attack_speed");
|
||||
public static final Attribute GENERIC_FLYING_SPEED = define("generic.flying_speed");
|
||||
public static final Attribute GENERIC_FOLLOW_RANGE = define("generic.follow_range");
|
||||
@ApiStatus.Obsolete // renamed in 1.20.5
|
||||
public static final Attribute HORSE_JUMP_STRENGTH = define("horse.jump_strength");
|
||||
public static final Attribute GENERIC_KNOCKBACK_RESISTANCE = define("generic.knockback_resistance");
|
||||
public static final Attribute GENERIC_LUCK = define("generic.luck");
|
||||
public static final Attribute GENERIC_MAX_HEALTH = define("generic.max_health");
|
||||
public static final Attribute GENERIC_MOVEMENT_SPEED = define("generic.movement_speed");
|
||||
public static final Attribute ZOMBIE_SPAWN_REINFORCEMENTS = define("zombie.spawn_reinforcements");
|
||||
public static final Attribute ARMOR = define("armor",
|
||||
"generic", 0d, 0d, 30d);
|
||||
public static final Attribute ARMOR_TOUGHNESS = define("armor_toughness",
|
||||
"generic", 0d, 0d, 20d);
|
||||
public static final Attribute ATTACK_DAMAGE = define("attack_damage",
|
||||
"generic", 2d, 0d, 2048d);
|
||||
public static final Attribute ATTACK_KNOCKBACK = define("attack_knockback",
|
||||
"generic", 0d, 0d, 5d);
|
||||
public static final Attribute ATTACK_SPEED = define("attack_speed",
|
||||
"generic", 4d, 0d, 1024d);
|
||||
public static final Attribute FLYING_SPEED = define("flying_speed",
|
||||
"generic", 0.4d, 0d, 1024d);
|
||||
public static final Attribute FOLLOW_RANGE = define("follow_range",
|
||||
"generic", 32d, 0d, 2048d);
|
||||
public static final Attribute KNOCKBACK_RESISTANCE = define("knockback_resistance",
|
||||
"generic", 0d, 0d, 1d);
|
||||
public static final Attribute LUCK = define("luck",
|
||||
"generic", 0d, -1024d, 1024d);
|
||||
public static final Attribute MAX_HEALTH = define("max_health",
|
||||
"generic", 20d, 1d, 1024d);
|
||||
public static final Attribute MOVEMENT_SPEED = define("movement_speed",
|
||||
"generic", 0.7d, 0d, 1024d);
|
||||
public static final Attribute SPAWN_REINFORCEMENTS = define("spawn_reinforcements",
|
||||
"zombie", 0d, 0d, 1d);
|
||||
|
||||
// Added in 1.20.2
|
||||
public static final Attribute GENERIC_MAX_ABSORPTION = define("generic.max_absorption");
|
||||
/**
|
||||
* Added with 1.20.2
|
||||
*/
|
||||
public static final Attribute MAX_ABSORPTION = define("max_absorption",
|
||||
"generic", 0d, 0d, 2048d);
|
||||
|
||||
// Added in 1.20.5
|
||||
public static final Attribute PLAYER_BLOCK_BREAK_SPEED = define("player.block_break_speed");
|
||||
public static final Attribute PLAYER_BLOCK_INTERACTION_RANGE = define("player.block_interaction_range");
|
||||
public static final Attribute PLAYER_ENTITY_INTERACTION_RANGE = define("player.entity_interaction_range");
|
||||
public static final Attribute GENERIC_FALL_DAMAGE_MULTIPLIER = define("generic.fall_damage_multiplier");
|
||||
public static final Attribute GENERIC_GRAVITY = define("generic.gravity");
|
||||
public static final Attribute GENERIC_JUMP_STRENGTH = define("generic.jump_strength");
|
||||
public static final Attribute GENERIC_SAFE_FALL_DISTANCE = define("generic.safe_fall_distance");
|
||||
public static final Attribute GENERIC_SCALE = define("generic.scale");
|
||||
public static final Attribute GENERIC_STEP_HEIGHT = define("generic.step_height");
|
||||
/**
|
||||
* Added with 1.20.5
|
||||
*/
|
||||
public static final Attribute BLOCK_BREAK_SPEED = define("block_break_speed",
|
||||
"player", 1d, 0d, 1024d);
|
||||
/**
|
||||
* Added with 1.20.5
|
||||
*/
|
||||
public static final Attribute BLOCK_INTERACTION_RANGE = define("block_interaction_range",
|
||||
"player", 4.5d, 0d, 64d);
|
||||
/**
|
||||
* Added with 1.20.5
|
||||
*/
|
||||
public static final Attribute ENTITY_INTERACTION_RANGE = define("entity_interaction_range",
|
||||
"player", 3d, 0d, 64d);
|
||||
/**
|
||||
* Added with 1.20.5
|
||||
*/
|
||||
public static final Attribute FALL_DAMAGE_MULTIPLIER = define("fall_damage_multiplier",
|
||||
"generic", 1d, 0d, 100d);
|
||||
/**
|
||||
* Added with 1.20.5
|
||||
*/
|
||||
public static final Attribute GRAVITY = define("gravity",
|
||||
"generic", 0.08d, -1d, 1d);
|
||||
/**
|
||||
* Added with 1.20.5
|
||||
*/
|
||||
public static final Attribute JUMP_STRENGTH = define("jump_strength",
|
||||
"generic", 0.42d, 0d, 32d);
|
||||
/**
|
||||
* Added with 1.20.5
|
||||
*/
|
||||
public static final Attribute SAFE_FALL_DISTANCE = define("safe_fall_distance",
|
||||
"generic", 3d, 0d, 1024d);
|
||||
/**
|
||||
* Added with 1.20.5
|
||||
*/
|
||||
public static final Attribute SCALE = define("scale",
|
||||
"generic", 1d, 1d / 16d, 16d);
|
||||
/**
|
||||
* Added with 1.20.5
|
||||
*/
|
||||
public static final Attribute STEP_HEIGHT = define("step_height",
|
||||
"generic", 0.6d, 0d, 10d);
|
||||
|
||||
// Added in 1.21
|
||||
public static final Attribute GENERIC_BURNING_TIME = define("generic.burning_time");
|
||||
public static final Attribute GENERIC_EXPLOSION_KNOCKBACK_RESISTANCE = define("generic.explosion_knockback_resistance");
|
||||
public static final Attribute PLAYER_MINING_EFFICIENCY = define("player.mining_efficiency");
|
||||
public static final Attribute GENERIC_MOVEMENT_EFFICIENCY = define("generic.movement_efficiency");
|
||||
public static final Attribute GENERIC_OXYGEN_BONUS = define("generic.oxygen_bonus");
|
||||
public static final Attribute PLAYER_SNEAKING_SPEED = define("player.sneaking_speed");
|
||||
public static final Attribute PLAYER_SUBMERGED_MINING_SPEED = define("player.submerged_mining_speed");
|
||||
public static final Attribute PLAYER_SWEEPING_DAMAGE_RATIO = define("player.sweeping_damage_ratio");
|
||||
public static final Attribute GENERIC_WATER_MOVEMENT_EFFICIENCY = define("generic.water_movement_efficiency");
|
||||
/**
|
||||
* Added with 1.21
|
||||
*/
|
||||
public static final Attribute BURNING_TIME = define("burning_time",
|
||||
"generic", 0d, 1d, 1024d);
|
||||
/**
|
||||
* Added with 1.21
|
||||
*/
|
||||
public static final Attribute EXPLOSION_KNOCKBACK_RESISTANCE = define("explosion_knockback_resistance",
|
||||
"generic", 0d, 0d, 1d);
|
||||
/**
|
||||
* Added with 1.21
|
||||
*/
|
||||
public static final Attribute MINING_EFFICIENCY = define("mining_efficiency",
|
||||
"player", 0d, 0d, 1024d);
|
||||
/**
|
||||
* Added with 1.21
|
||||
*/
|
||||
public static final Attribute MOVEMENT_EFFICIENCY = define("movement_efficiency",
|
||||
"generic", 0d, 0d, 1d);
|
||||
/**
|
||||
* Added with 1.21
|
||||
*/
|
||||
public static final Attribute OXYGEN_BONUS = define("oxygen_bonus",
|
||||
"generic", 0d, 0d, 1024d);
|
||||
/**
|
||||
* Added with 1.21
|
||||
*/
|
||||
public static final Attribute SNEAKING_SPEED = define("sneaking_speed",
|
||||
"player", 0.3d, 0d, 1d);
|
||||
/**
|
||||
* Added with 1.21
|
||||
*/
|
||||
public static final Attribute SUBMERGED_MINING_SPEED = define("submerged_mining_speed",
|
||||
"player", 0.2d, 0d, 20d);
|
||||
/**
|
||||
* Added with 1.21
|
||||
*/
|
||||
public static final Attribute SWEEPING_DAMAGE_RATIO = define("sweeping_damage_ratio",
|
||||
"player", 0d, 0d, 1d);
|
||||
/**
|
||||
* Added with 1.21
|
||||
*/
|
||||
public static final Attribute WATER_MOVEMENT_EFFICIENCY = define("water_movement_efficiency",
|
||||
"generic", 0d, 0d, 1d);
|
||||
|
||||
/**
|
||||
* Added with 1.21.2
|
||||
*/
|
||||
public static final Attribute TEMPT_RANGE = define("tempt_range",
|
||||
null, 10d, 0d, 2048d);
|
||||
|
||||
/**
|
||||
* This attribute has been renamed in 1.20.5 to {@link #JUMP_STRENGTH}
|
||||
*/
|
||||
@ApiStatus.Obsolete
|
||||
public static final Attribute HORSE_JUMP_STRENGTH = define("horse.jump_strength",
|
||||
null, 0.7d, 0d, 2d);
|
||||
|
||||
/**
|
||||
* All attribute "type" prefixes were removed with 1.21.2
|
||||
*/
|
||||
@Deprecated
|
||||
public static final Attribute GENERIC_ARMOR = ARMOR;
|
||||
/**
|
||||
* All attribute "type" prefixes were removed with 1.21.2
|
||||
*/
|
||||
@Deprecated
|
||||
public static final Attribute GENERIC_ARMOR_TOUGHNESS = ARMOR_TOUGHNESS;
|
||||
/**
|
||||
* All attribute "type" prefixes were removed with 1.21.2
|
||||
*/
|
||||
@Deprecated
|
||||
public static final Attribute GENERIC_ATTACK_DAMAGE = ATTACK_DAMAGE;
|
||||
/**
|
||||
* All attribute "type" prefixes were removed with 1.21.2
|
||||
*/
|
||||
@Deprecated
|
||||
public static final Attribute GENERIC_ATTACK_KNOCKBACK = ATTACK_KNOCKBACK;
|
||||
/**
|
||||
* All attribute "type" prefixes were removed with 1.21.2
|
||||
*/
|
||||
@Deprecated
|
||||
public static final Attribute GENERIC_ATTACK_SPEED = ATTACK_SPEED;
|
||||
/**
|
||||
* All attribute "type" prefixes were removed with 1.21.2
|
||||
*/
|
||||
@Deprecated
|
||||
public static final Attribute GENERIC_FLYING_SPEED = FLYING_SPEED;
|
||||
/**
|
||||
* All attribute "type" prefixes were removed with 1.21.2
|
||||
*/
|
||||
@Deprecated
|
||||
public static final Attribute GENERIC_FOLLOW_RANGE = FOLLOW_RANGE;
|
||||
/**
|
||||
* All attribute "type" prefixes were removed with 1.21.2
|
||||
*/
|
||||
@Deprecated
|
||||
public static final Attribute GENERIC_KNOCKBACK_RESISTANCE = KNOCKBACK_RESISTANCE;
|
||||
/**
|
||||
* All attribute "type" prefixes were removed with 1.21.2
|
||||
*/
|
||||
@Deprecated
|
||||
public static final Attribute GENERIC_LUCK = LUCK;
|
||||
/**
|
||||
* All attribute "type" prefixes were removed with 1.21.2
|
||||
*/
|
||||
@Deprecated
|
||||
public static final Attribute GENERIC_MAX_HEALTH = MAX_HEALTH;
|
||||
/**
|
||||
* All attribute "type" prefixes were removed with 1.21.2
|
||||
*/
|
||||
@Deprecated
|
||||
public static final Attribute GENERIC_MOVEMENT_SPEED = MOVEMENT_SPEED;
|
||||
/**
|
||||
* All attribute "type" prefixes were removed with 1.21.2
|
||||
*/
|
||||
@Deprecated
|
||||
public static final Attribute ZOMBIE_SPAWN_REINFORCEMENTS = SPAWN_REINFORCEMENTS;
|
||||
/**
|
||||
* All attribute "type" prefixes were removed with 1.21.2
|
||||
*/
|
||||
@Deprecated
|
||||
public static final Attribute GENERIC_MAX_ABSORPTION = MAX_ABSORPTION;
|
||||
/**
|
||||
* All attribute "type" prefixes were removed with 1.21.2
|
||||
*/
|
||||
@Deprecated
|
||||
public static final Attribute PLAYER_BLOCK_BREAK_SPEED = BLOCK_BREAK_SPEED;
|
||||
/**
|
||||
* All attribute "type" prefixes were removed with 1.21.2
|
||||
*/
|
||||
@Deprecated
|
||||
public static final Attribute PLAYER_BLOCK_INTERACTION_RANGE = BLOCK_INTERACTION_RANGE;
|
||||
/**
|
||||
* All attribute "type" prefixes were removed with 1.21.2
|
||||
*/
|
||||
@Deprecated
|
||||
public static final Attribute PLAYER_ENTITY_INTERACTION_RANGE = ENTITY_INTERACTION_RANGE;
|
||||
/**
|
||||
* All attribute "type" prefixes were removed with 1.21.2
|
||||
*/
|
||||
@Deprecated
|
||||
public static final Attribute GENERIC_FALL_DAMAGE_MULTIPLIER = FALL_DAMAGE_MULTIPLIER;
|
||||
/**
|
||||
* All attribute "type" prefixes were removed with 1.21.2
|
||||
*/
|
||||
@Deprecated
|
||||
public static final Attribute GENERIC_GRAVITY = GRAVITY;
|
||||
/**
|
||||
* All attribute "type" prefixes were removed with 1.21.2
|
||||
*/
|
||||
@Deprecated
|
||||
public static final Attribute GENERIC_JUMP_STRENGTH = JUMP_STRENGTH;
|
||||
/**
|
||||
* All attribute "type" prefixes were removed with 1.21.2
|
||||
*/
|
||||
@Deprecated
|
||||
public static final Attribute GENERIC_SAFE_FALL_DISTANCE = SAFE_FALL_DISTANCE;
|
||||
/**
|
||||
* All attribute "type" prefixes were removed with 1.21.2
|
||||
*/
|
||||
@Deprecated
|
||||
public static final Attribute GENERIC_SCALE = SCALE;
|
||||
/**
|
||||
* All attribute "type" prefixes were removed with 1.21.2
|
||||
*/
|
||||
@Deprecated
|
||||
public static final Attribute GENERIC_STEP_HEIGHT = STEP_HEIGHT;
|
||||
/**
|
||||
* All attribute "type" prefixes were removed with 1.21.2
|
||||
*/
|
||||
@Deprecated
|
||||
public static final Attribute GENERIC_BURNING_TIME = BURNING_TIME;
|
||||
/**
|
||||
* All attribute "type" prefixes were removed with 1.21.2
|
||||
*/
|
||||
@Deprecated
|
||||
public static final Attribute GENERIC_EXPLOSION_KNOCKBACK_RESISTANCE = EXPLOSION_KNOCKBACK_RESISTANCE;
|
||||
/**
|
||||
* All attribute "type" prefixes were removed with 1.21.2
|
||||
*/
|
||||
@Deprecated
|
||||
public static final Attribute PLAYER_MINING_EFFICIENCY = MINING_EFFICIENCY;
|
||||
/**
|
||||
* All attribute "type" prefixes were removed with 1.21.2
|
||||
*/
|
||||
@Deprecated
|
||||
public static final Attribute GENERIC_MOVEMENT_EFFICIENCY = MOVEMENT_EFFICIENCY;
|
||||
/**
|
||||
* All attribute "type" prefixes were removed with 1.21.2
|
||||
*/
|
||||
@Deprecated
|
||||
public static final Attribute GENERIC_OXYGEN_BONUS = OXYGEN_BONUS;
|
||||
/**
|
||||
* All attribute "type" prefixes were removed with 1.21.2
|
||||
*/
|
||||
@Deprecated
|
||||
public static final Attribute PLAYER_SNEAKING_SPEED = SNEAKING_SPEED;
|
||||
/**
|
||||
* All attribute "type" prefixes were removed with 1.21.2
|
||||
*/
|
||||
@Deprecated
|
||||
public static final Attribute PLAYER_SUBMERGED_MINING_SPEED = SUBMERGED_MINING_SPEED;
|
||||
/**
|
||||
* All attribute "type" prefixes were removed with 1.21.2
|
||||
*/
|
||||
@Deprecated
|
||||
public static final Attribute PLAYER_SWEEPING_DAMAGE_RATIO = SWEEPING_DAMAGE_RATIO;
|
||||
/**
|
||||
* All attribute "type" prefixes were removed with 1.21.2
|
||||
*/
|
||||
@Deprecated
|
||||
public static final Attribute GENERIC_WATER_MOVEMENT_EFFICIENCY = WATER_MOVEMENT_EFFICIENCY;
|
||||
|
||||
static {
|
||||
TYPES_BUILDER.unloadFileMappings();
|
||||
REGISTRY.unloadMappings();
|
||||
}
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.attribute;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.mapper.AbstractMappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class StaticAttribute extends AbstractMappedEntity implements Attribute {
|
||||
|
||||
private final @Nullable ResourceLocation legacyName;
|
||||
private final double defaultValue;
|
||||
private final double minValue;
|
||||
private final double maxValue;
|
||||
|
||||
StaticAttribute(
|
||||
TypesBuilderData data, String legacyPrefix,
|
||||
double defaultValue, double minValue, double maxValue
|
||||
) {
|
||||
super(data);
|
||||
this.defaultValue = defaultValue;
|
||||
this.minValue = minValue;
|
||||
this.maxValue = maxValue;
|
||||
this.legacyName = legacyPrefix == null ? null : new ResourceLocation(
|
||||
data.getName().getNamespace(), legacyPrefix + "." + data.getName().getKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getName(ClientVersion version) {
|
||||
assert this.data != null; // not marked as nullable in ctor
|
||||
return version.isNewerThanOrEquals(ClientVersion.V_1_21_2) || this.legacyName == null
|
||||
? this.data.getName() : this.legacyName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDefaultValue() {
|
||||
return this.defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getMinValue() {
|
||||
return this.minValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getMaxValue() {
|
||||
return this.maxValue;
|
||||
}
|
||||
}
|
||||
@@ -19,17 +19,39 @@
|
||||
package com.github.retrooper.packetevents.protocol.chat;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.chat.message.ChatMessage_v1_19_1;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.CopyableEntity;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.DeepComparableEntity;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.MappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.util.Index;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.UnknownNullability;
|
||||
|
||||
public interface ChatType extends MappedEntity {
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.github.retrooper.packetevents.util.adventure.AdventureIndexUtil.indexValueOrThrow;
|
||||
|
||||
public interface ChatType extends MappedEntity, CopyableEntity<ChatType>, DeepComparableEntity {
|
||||
|
||||
@UnknownNullability("only nullable for 1.19")
|
||||
ChatTypeDecoration getChatDecoration();
|
||||
|
||||
@ApiStatus.Obsolete(since = "1.19.1")
|
||||
@Nullable ChatTypeDecoration getOverlayDecoration();
|
||||
|
||||
@UnknownNullability("only nullable for 1.19")
|
||||
ChatTypeDecoration getNarrationDecoration();
|
||||
|
||||
@ApiStatus.Obsolete(since = "1.19.1")
|
||||
@Nullable NarrationPriority getNarrationPriority();
|
||||
|
||||
static ChatType readDirect(PacketWrapper<?> wrapper) {
|
||||
ChatTypeDecoration chatDecoration = ChatTypeDecoration.read(wrapper);
|
||||
ChatTypeDecoration narrationDecoration = ChatTypeDecoration.read(wrapper);
|
||||
@@ -41,9 +63,105 @@ public interface ChatType extends MappedEntity {
|
||||
ChatTypeDecoration.write(wrapper, chatType.getNarrationDecoration());
|
||||
}
|
||||
|
||||
static ChatType decode(NBT nbt, ClientVersion version, @Nullable TypesBuilderData data) {
|
||||
// everything is nullable in 1.19, even the chat format!
|
||||
NBTCompound compound = (NBTCompound) nbt;
|
||||
NBTCompound chatTag = compound.getCompoundTagOrNull("chat");
|
||||
NBTCompound narrationTag = compound.getCompoundTagOrNull("narration");
|
||||
|
||||
ChatTypeDecoration overlay = null;
|
||||
NarrationPriority narrationPriority = null;
|
||||
if (version.isOlderThan(ClientVersion.V_1_19_1)) {
|
||||
NBTCompound overlayTag = compound.getCompoundTagOrNull("overlay");
|
||||
if (overlayTag != null) {
|
||||
// why is this nullable? why is this wrapped? There is no reason to wrap this...
|
||||
overlayTag = overlayTag.getCompoundTagOrNull("description");
|
||||
if (overlayTag != null) {
|
||||
overlay = ChatTypeDecoration.decode(overlayTag, version);
|
||||
}
|
||||
}
|
||||
if (chatTag != null) {
|
||||
chatTag = chatTag.getCompoundTagOrNull("description");
|
||||
}
|
||||
if (narrationTag != null) {
|
||||
// the priority is the ONLY value which isn't nullable!
|
||||
narrationPriority = indexValueOrThrow(NarrationPriority.ID_INDEX,
|
||||
narrationTag.getStringTagValueOrThrow("priority"));
|
||||
narrationTag = narrationTag.getCompoundTagOrNull("description");
|
||||
}
|
||||
} else {
|
||||
// ensure this isn't null in everything but 1.19
|
||||
Objects.requireNonNull(chatTag, "NBT chat does not exist");
|
||||
Objects.requireNonNull(narrationTag, "NBT narration does not exist");
|
||||
}
|
||||
|
||||
ChatTypeDecoration chat = chatTag == null ? null : ChatTypeDecoration.decode(chatTag, version);
|
||||
ChatTypeDecoration narration = narrationTag == null ? null : ChatTypeDecoration.decode(narrationTag, version);
|
||||
return new StaticChatType(data, chat, overlay, narration, narrationPriority);
|
||||
}
|
||||
|
||||
static NBT encode(ChatType chatType, ClientVersion version) {
|
||||
NBTCompound compound = new NBTCompound();
|
||||
NBT chatTag = chatType.getChatDecoration() == null ? null :
|
||||
ChatTypeDecoration.encode(chatType.getChatDecoration(), version);
|
||||
NBT narrationTag = chatType.getNarrationDecoration() == null ? null :
|
||||
ChatTypeDecoration.encode(chatType.getNarrationDecoration(), version);
|
||||
|
||||
if (version.isOlderThan(ClientVersion.V_1_19_1)) {
|
||||
ChatTypeDecoration overlayDeco = chatType.getOverlayDecoration();
|
||||
if (overlayDeco != null) {
|
||||
NBTCompound overlayCompound = new NBTCompound();
|
||||
overlayCompound.setTag("description",
|
||||
ChatTypeDecoration.encode(overlayDeco, version));
|
||||
compound.setTag("overlay", overlayCompound);
|
||||
}
|
||||
if (narrationTag != null) {
|
||||
NBTCompound narrationCompound = new NBTCompound();
|
||||
narrationCompound.setTag("description", narrationTag);
|
||||
if (chatType.getNarrationPriority() != null) {
|
||||
narrationCompound.setTag("priority", new NBTString(chatType.getNarrationPriority().getId()));
|
||||
}
|
||||
narrationTag = narrationCompound;
|
||||
}
|
||||
if (chatTag != null) {
|
||||
NBTCompound chatCompound = new NBTCompound();
|
||||
chatCompound.setTag("description", chatTag);
|
||||
chatTag = chatCompound;
|
||||
}
|
||||
}
|
||||
|
||||
if (chatTag != null) {
|
||||
compound.setTag("chat", chatTag);
|
||||
}
|
||||
if (narrationTag != null) {
|
||||
compound.setTag("narration", narrationTag);
|
||||
}
|
||||
return compound;
|
||||
}
|
||||
|
||||
class Bound extends ChatMessage_v1_19_1.ChatTypeBoundNetwork {
|
||||
public Bound(ChatType type, Component name, @Nullable Component targetName) {
|
||||
super(type, name, targetName);
|
||||
}
|
||||
}
|
||||
|
||||
@ApiStatus.Obsolete(since = "1.19.1")
|
||||
enum NarrationPriority {
|
||||
|
||||
CHAT("chat"),
|
||||
SYSTEM("system");
|
||||
|
||||
public static final Index<String, NarrationPriority> ID_INDEX = Index.create(
|
||||
NarrationPriority.class, NarrationPriority::getId);
|
||||
|
||||
private final String id;
|
||||
|
||||
NarrationPriority(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
}
|
||||
}
|
||||
+80
-40
@@ -18,23 +18,29 @@
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.chat;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.chat.message.ChatMessage_v1_19_1;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTList;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.util.adventure.AdventureSerializer;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.ComponentLike;
|
||||
import net.kyori.adventure.text.format.Style;
|
||||
import net.kyori.adventure.util.Index;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import static com.github.retrooper.packetevents.protocol.chat.ChatTypeDecoration.Parameter.*;
|
||||
import static com.github.retrooper.packetevents.protocol.chat.ChatTypeDecoration.Parameter.CONTENT;
|
||||
import static com.github.retrooper.packetevents.protocol.chat.ChatTypeDecoration.Parameter.SENDER;
|
||||
import static com.github.retrooper.packetevents.protocol.chat.ChatTypeDecoration.Parameter.TARGET;
|
||||
import static com.github.retrooper.packetevents.util.adventure.AdventureIndexUtil.indexValueOrThrow;
|
||||
import static java.util.Arrays.asList;
|
||||
import static net.kyori.adventure.text.format.NamedTextColor.GRAY;
|
||||
import static net.kyori.adventure.text.format.Style.empty;
|
||||
@@ -53,32 +59,6 @@ public class ChatTypeDecoration {
|
||||
this.style = style;
|
||||
}
|
||||
|
||||
public ChatTypeDecoration(NBTCompound nbt) {
|
||||
//Read the translation key
|
||||
this.translationKey = nbt.getStringTagValueOrDefault("translation_key", null);
|
||||
|
||||
//Read parameters
|
||||
List<Parameter> temporaryList = new ArrayList<>();
|
||||
NBTList<NBTString> parametersTag = nbt.getStringListTagOrNull("parameters");
|
||||
if (parametersTag != null) {
|
||||
for (NBTString p : parametersTag.getTags()) {
|
||||
Parameter parameter = Parameter.valueByName(p.getValue().toUpperCase());
|
||||
if (parameter != null) {
|
||||
temporaryList.add(parameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.parameters = Collections.unmodifiableList(temporaryList);
|
||||
|
||||
//Read style
|
||||
NBTCompound styleTag = nbt.getCompoundTagOrNull("style");
|
||||
if (styleTag != null) {
|
||||
style = AdventureSerializer.getNBTSerializer().deserializeStyle(styleTag);
|
||||
} else {
|
||||
style = empty();
|
||||
}
|
||||
}
|
||||
|
||||
public static ChatTypeDecoration read(PacketWrapper<?> wrapper) {
|
||||
String translationKey = wrapper.readString();
|
||||
List<Parameter> parameters = wrapper.readList(ew -> ew.readEnum(Parameter.values()));
|
||||
@@ -92,6 +72,44 @@ public class ChatTypeDecoration {
|
||||
wrapper.writeStyle(decoration.style);
|
||||
}
|
||||
|
||||
public static ChatTypeDecoration decode(NBT nbt, ClientVersion version) {
|
||||
NBTCompound compound = (NBTCompound) nbt;
|
||||
String translationKey = compound.getStringTagValueOrThrow("translation_key");
|
||||
NBT paramsTag = compound.getTagOrThrow("parameters");
|
||||
List<Parameter> params;
|
||||
if (paramsTag instanceof NBTList<?>) {
|
||||
params = new ArrayList<>();
|
||||
NBTList<?> paramsTagList = (NBTList<?>) paramsTag;
|
||||
for (NBT paramTag : paramsTagList.getTags()) {
|
||||
String paramId = ((NBTString) paramTag).getValue();
|
||||
params.add(indexValueOrThrow(Parameter.ID_INDEX, paramId));
|
||||
}
|
||||
} else {
|
||||
String paramId = ((NBTString) paramsTag).getValue();
|
||||
params = Collections.singletonList(indexValueOrThrow(Parameter.ID_INDEX, paramId));
|
||||
}
|
||||
NBTCompound styleTag = compound.getCompoundTagOrNull("style");
|
||||
Style style = styleTag == null ? empty() :
|
||||
AdventureSerializer.getNBTSerializer().deserializeStyle(styleTag);
|
||||
return new ChatTypeDecoration(translationKey, params, style);
|
||||
}
|
||||
|
||||
public static NBT encode(ChatTypeDecoration decoration, ClientVersion version) {
|
||||
NBTList<NBTString> paramsTag = NBTList.createStringList();
|
||||
for (Parameter param : decoration.parameters) {
|
||||
paramsTag.addTag(new NBTString(param.getId()));
|
||||
}
|
||||
|
||||
NBTCompound compound = new NBTCompound();
|
||||
compound.setTag("translation_key", new NBTString(decoration.translationKey));
|
||||
compound.setTag("parameters", paramsTag);
|
||||
if (!decoration.style.isEmpty()) {
|
||||
compound.setTag("style", AdventureSerializer.getNBTSerializer()
|
||||
.serializeStyle(decoration.style));
|
||||
}
|
||||
return compound;
|
||||
}
|
||||
|
||||
public static ChatTypeDecoration withSender(String translationKey) {
|
||||
return new ChatTypeDecoration(translationKey, asList(SENDER, CONTENT), empty());
|
||||
}
|
||||
@@ -131,24 +149,46 @@ public class ChatTypeDecoration {
|
||||
return this.style;
|
||||
}
|
||||
|
||||
public enum Parameter {
|
||||
SENDER((component, type) -> type.getName()),
|
||||
TARGET((component, type) -> type.getTargetName() != null ? type.getTargetName() : Component.empty()),
|
||||
CONTENT((component, type) -> component);
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof ChatTypeDecoration)) return false;
|
||||
ChatTypeDecoration that = (ChatTypeDecoration) obj;
|
||||
if (!this.translationKey.equals(that.translationKey)) return false;
|
||||
if (!this.parameters.equals(that.parameters)) return false;
|
||||
return this.style.equals(that.style);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.translationKey, this.parameters, this.style);
|
||||
}
|
||||
|
||||
public enum Parameter {
|
||||
|
||||
SENDER("sender", (component, type) -> type.getName()),
|
||||
TARGET("target", (component, type) -> type.getTargetName() != null
|
||||
? type.getTargetName() : Component.empty()),
|
||||
CONTENT("content", (component, type) -> component);
|
||||
|
||||
public static final Index<String, Parameter> ID_INDEX = Index.create(
|
||||
Parameter.class, Parameter::getId);
|
||||
|
||||
private final String id;
|
||||
private final BiFunction<Component, ChatType.Bound, Component> selector;
|
||||
|
||||
Parameter(BiFunction<Component, ChatType.Bound, Component> selector) {
|
||||
Parameter(String id, BiFunction<Component, ChatType.Bound, Component> selector) {
|
||||
this.id = id;
|
||||
this.selector = selector;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Parameter valueByName(String name) {
|
||||
try {
|
||||
return valueOf(name);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
return null;
|
||||
}
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static @Nullable Parameter valueByName(String id) {
|
||||
return ID_INDEX.value(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,71 +19,50 @@
|
||||
package com.github.retrooper.packetevents.protocol.chat;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.util.mappings.MappingHelper;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilder;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import com.github.retrooper.packetevents.util.mappings.VersionedRegistry;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.github.retrooper.packetevents.protocol.chat.ChatTypeDecoration.incomingDirectMessage;
|
||||
import static com.github.retrooper.packetevents.protocol.chat.ChatTypeDecoration.outgoingDirectMessage;
|
||||
import static com.github.retrooper.packetevents.protocol.chat.ChatTypeDecoration.teamMessage;
|
||||
import static com.github.retrooper.packetevents.protocol.chat.ChatTypeDecoration.withSender;
|
||||
|
||||
public class ChatTypes {
|
||||
public final class ChatTypes {
|
||||
|
||||
private static final Map<String, ChatType> CHAT_TYPE_MAP = new HashMap<>();
|
||||
//Key - mappings version, value - map with chat type ids and chat types
|
||||
private static final Map<Byte, Map<Integer, ChatType>> CHAT_TYPE_ID_MAP = new HashMap<>();
|
||||
private static final TypesBuilder TYPES_BUILDER = new TypesBuilder("chat/chat_type_mappings");
|
||||
private static final VersionedRegistry<ChatType> REGISTRY = new VersionedRegistry<>(
|
||||
"chat_type", "chat/chat_type_mappings");
|
||||
|
||||
private ChatTypes() {
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static ChatType define(String key) {
|
||||
return define(key, withSender("chat.type.text"));
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static ChatType define(String key, ChatTypeDecoration chatDeco) {
|
||||
return define(key, chatDeco, withSender("chat.type.text.narrate"));
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static ChatType define(String key, ChatTypeDecoration chatDeco, ChatTypeDecoration narrationDeco) {
|
||||
TypesBuilderData data = TYPES_BUILDER.define(key);
|
||||
ChatType chatType = new ChatType() {
|
||||
@Override
|
||||
public ChatTypeDecoration getChatDecoration() {
|
||||
return chatDeco;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChatTypeDecoration getNarrationDecoration() {
|
||||
return narrationDeco;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getName() {
|
||||
return data.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId(ClientVersion version) {
|
||||
return MappingHelper.getId(version, TYPES_BUILDER, data);
|
||||
}
|
||||
};
|
||||
MappingHelper.registerMapping(TYPES_BUILDER, CHAT_TYPE_MAP, CHAT_TYPE_ID_MAP, chatType);
|
||||
return chatType;
|
||||
return REGISTRY.define(key, data ->
|
||||
new StaticChatType(data, chatDeco, narrationDeco));
|
||||
}
|
||||
|
||||
public static VersionedRegistry<ChatType> getRegistry() {
|
||||
return REGISTRY;
|
||||
}
|
||||
|
||||
//with minecraft:key
|
||||
public static ChatType getByName(String name) {
|
||||
return CHAT_TYPE_MAP.get(name);
|
||||
return REGISTRY.getByName(name);
|
||||
}
|
||||
|
||||
public static ChatType getById(ClientVersion version, int id) {
|
||||
int index = TYPES_BUILDER.getDataIndex(version);
|
||||
return CHAT_TYPE_ID_MAP.get((byte) index).get(id);
|
||||
return REGISTRY.getById(version, id);
|
||||
}
|
||||
|
||||
public static final ChatType CHAT = define("chat");
|
||||
@@ -115,13 +94,14 @@ public class ChatTypes {
|
||||
|
||||
/**
|
||||
* Returns an immutable view of the chat types.
|
||||
*
|
||||
* @return Chat Types
|
||||
*/
|
||||
public static Collection<ChatType> values() {
|
||||
return Collections.unmodifiableCollection(CHAT_TYPE_MAP.values());
|
||||
return REGISTRY.getEntries();
|
||||
}
|
||||
|
||||
static {
|
||||
TYPES_BUILDER.unloadFileMappings();
|
||||
REGISTRY.unloadMappings();
|
||||
}
|
||||
}
|
||||
+76
-14
@@ -18,41 +18,103 @@
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.chat;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.AbstractMappedEntity;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.UnknownNullability;
|
||||
|
||||
public class StaticChatType implements ChatType {
|
||||
import java.util.Objects;
|
||||
|
||||
private final ChatTypeDecoration chatDecoration;
|
||||
private final ChatTypeDecoration narrationDecoration;
|
||||
public class StaticChatType extends AbstractMappedEntity implements ChatType {
|
||||
|
||||
public StaticChatType(ChatTypeDecoration chatDecoration, ChatTypeDecoration narrationDecoration) {
|
||||
private final @UnknownNullability("only nullable for 1.19") ChatTypeDecoration chatDecoration;
|
||||
private final @Nullable ChatTypeDecoration overlayDecoration;
|
||||
private final @UnknownNullability("only nullable for 1.19") ChatTypeDecoration narrationDecoration;
|
||||
private final @Nullable NarrationPriority narrationPriority;
|
||||
|
||||
public StaticChatType(
|
||||
ChatTypeDecoration chatDecoration,
|
||||
ChatTypeDecoration narrationDecoration
|
||||
) {
|
||||
this(null, chatDecoration, null, narrationDecoration, null);
|
||||
}
|
||||
|
||||
public StaticChatType(
|
||||
@Nullable TypesBuilderData data,
|
||||
ChatTypeDecoration chatDecoration,
|
||||
ChatTypeDecoration narrationDecoration
|
||||
) {
|
||||
this(data, chatDecoration, null, narrationDecoration, null);
|
||||
}
|
||||
|
||||
public StaticChatType(
|
||||
@UnknownNullability("only nullable for 1.19") ChatTypeDecoration chatDecoration,
|
||||
@Nullable ChatTypeDecoration overlayDecoration,
|
||||
@UnknownNullability("only nullable for 1.19") ChatTypeDecoration narrationDecoration,
|
||||
@Nullable NarrationPriority narrationPriority
|
||||
) {
|
||||
this(null, chatDecoration, overlayDecoration, narrationDecoration, narrationPriority);
|
||||
}
|
||||
|
||||
public StaticChatType(
|
||||
@Nullable TypesBuilderData data,
|
||||
@UnknownNullability("only nullable for 1.19") ChatTypeDecoration chatDecoration,
|
||||
@Nullable ChatTypeDecoration overlayDecoration,
|
||||
@UnknownNullability("only nullable for 1.19") ChatTypeDecoration narrationDecoration,
|
||||
@Nullable NarrationPriority narrationPriority
|
||||
) {
|
||||
super(data);
|
||||
this.chatDecoration = chatDecoration;
|
||||
this.overlayDecoration = overlayDecoration;
|
||||
this.narrationDecoration = narrationDecoration;
|
||||
this.narrationPriority = narrationPriority;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChatTypeDecoration getChatDecoration() {
|
||||
public ChatType copy(@Nullable TypesBuilderData newData) {
|
||||
return new StaticChatType(newData, this.chatDecoration,
|
||||
this.overlayDecoration, this.narrationDecoration, this.narrationPriority);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @UnknownNullability("only nullable for 1.19") ChatTypeDecoration getChatDecoration() {
|
||||
return this.chatDecoration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChatTypeDecoration getNarrationDecoration() {
|
||||
public @Nullable ChatTypeDecoration getOverlayDecoration() {
|
||||
return this.overlayDecoration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @UnknownNullability("only nullable for 1.19") ChatTypeDecoration getNarrationDecoration() {
|
||||
return this.narrationDecoration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getName() {
|
||||
throw new UnsupportedOperationException();
|
||||
public @Nullable NarrationPriority getNarrationPriority() {
|
||||
return this.narrationPriority;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId(ClientVersion version) {
|
||||
throw new UnsupportedOperationException();
|
||||
public boolean deepEquals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof StaticChatType)) return false;
|
||||
if (!super.equals(obj)) return false;
|
||||
StaticChatType that = (StaticChatType) obj;
|
||||
if (!Objects.equals(this.chatDecoration, that.chatDecoration)) return false;
|
||||
if (!Objects.equals(this.overlayDecoration, that.overlayDecoration)) return false;
|
||||
if (!Objects.equals(this.narrationDecoration, that.narrationDecoration)) return false;
|
||||
return this.narrationPriority == that.narrationPriority;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRegistered() {
|
||||
return false;
|
||||
public int deepHashCode() {
|
||||
return Objects.hash(super.hashCode(), this.chatDecoration, this.overlayDecoration, this.narrationDecoration, this.narrationPriority);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "StaticChatType{chatDecoration=" + this.chatDecoration + ", overlayDecoration=" + this.overlayDecoration + ", narrationDecoration=" + this.narrationDecoration + ", narrationPriority=" + this.narrationPriority + '}';
|
||||
}
|
||||
}
|
||||
+2
-3
@@ -31,14 +31,13 @@ public class ChatMessageProcessorLegacy implements ChatMessageProcessor {
|
||||
@Override
|
||||
public ChatMessage readChatMessage(@NotNull PacketWrapper<?> wrapper) {
|
||||
Component chatContent = wrapper.readComponent();
|
||||
int id = wrapper.readByte();
|
||||
ChatType type = ChatTypes.getById(wrapper.getServerVersion().toClientVersion(), id);
|
||||
ChatType type = wrapper.readMappedEntity(ChatTypes.getRegistry());
|
||||
return new ChatMessageLegacy(chatContent, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeChatMessage(@NotNull PacketWrapper<?> wrapper, @NotNull ChatMessage data) {
|
||||
wrapper.writeComponent(data.getChatContent());
|
||||
wrapper.writeByte(data.getType().getId(wrapper.getServerVersion().toClientVersion()));
|
||||
wrapper.writeMappedEntity(data.getType());
|
||||
}
|
||||
}
|
||||
+2
-3
@@ -33,8 +33,7 @@ public class ChatMessageProcessor_v1_16 implements ChatMessageProcessor {
|
||||
@Override
|
||||
public ChatMessage readChatMessage(@NotNull PacketWrapper<?> wrapper) {
|
||||
Component chatContent = wrapper.readComponent();
|
||||
int id = wrapper.readByte();
|
||||
ChatType type = ChatTypes.getById(wrapper.getServerVersion().toClientVersion(), id);
|
||||
ChatType type = wrapper.readMappedEntity(ChatTypes.getRegistry());
|
||||
UUID senderUUID = wrapper.readUUID();
|
||||
return new ChatMessage_v1_16(chatContent, type, senderUUID);
|
||||
}
|
||||
@@ -42,7 +41,7 @@ public class ChatMessageProcessor_v1_16 implements ChatMessageProcessor {
|
||||
@Override
|
||||
public void writeChatMessage(@NotNull PacketWrapper<?> wrapper, @NotNull ChatMessage data) {
|
||||
wrapper.writeComponent(data.getChatContent());
|
||||
wrapper.writeByte(data.getType().getId(wrapper.getServerVersion().toClientVersion()));
|
||||
wrapper.writeMappedEntity(data.getType());
|
||||
wrapper.writeUUID(((ChatMessage_v1_16) data).getSenderUUID());
|
||||
}
|
||||
}
|
||||
+2
-3
@@ -36,8 +36,7 @@ public class ChatMessageProcessor_v1_19 implements ChatMessageProcessor {
|
||||
public ChatMessage readChatMessage(@NotNull PacketWrapper<?> wrapper) {
|
||||
Component chatContent = wrapper.readComponent();
|
||||
Component unsignedChatContent = wrapper.readOptional(PacketWrapper::readComponent);
|
||||
int id = wrapper.readVarInt();
|
||||
ChatType type = ChatTypes.getById(wrapper.getServerVersion().toClientVersion(), id);
|
||||
ChatType type = wrapper.readMappedEntity(ChatTypes.getRegistry());
|
||||
UUID senderUUID = wrapper.readUUID();
|
||||
Component senderDisplayName = wrapper.readComponent();
|
||||
@Nullable Component teamName = wrapper.readOptional(PacketWrapper::readComponent);
|
||||
@@ -53,7 +52,7 @@ public class ChatMessageProcessor_v1_19 implements ChatMessageProcessor {
|
||||
ChatMessage_v1_19 newData = (ChatMessage_v1_19) data;
|
||||
wrapper.writeComponent(newData.getChatContent());
|
||||
wrapper.writeOptional(newData.getUnsignedChatContent(), PacketWrapper::writeComponent);
|
||||
wrapper.writeVarInt(newData.getType().getId(wrapper.getServerVersion().toClientVersion()));
|
||||
wrapper.writeMappedEntity(newData.getType());
|
||||
wrapper.writeUUID(newData.getSenderUUID());
|
||||
wrapper.writeComponent(newData.getSenderDisplayName());
|
||||
wrapper.writeOptional(newData.getTeamName(), PacketWrapper::writeComponent);
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.color;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTFloat;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTInt;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTList;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTNumber;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTType;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.util.MathUtil;
|
||||
import org.jetbrains.annotations.Range;
|
||||
|
||||
public final class AlphaColor extends Color {
|
||||
|
||||
public static final AlphaColor WHITE = new AlphaColor(0xFFFFFFFF);
|
||||
|
||||
private final int alpha;
|
||||
|
||||
public AlphaColor(
|
||||
@Range(from = 0L, to = 255L) int red,
|
||||
@Range(from = 0L, to = 255L) int green,
|
||||
@Range(from = 0L, to = 255L) int blue
|
||||
) {
|
||||
this(255, red, green, blue);
|
||||
}
|
||||
|
||||
public AlphaColor(
|
||||
@Range(from = 0L, to = 255L) int alpha,
|
||||
@Range(from = 0L, to = 255L) int red,
|
||||
@Range(from = 0L, to = 255L) int green,
|
||||
@Range(from = 0L, to = 255L) int blue
|
||||
) {
|
||||
super(red, green, blue);
|
||||
this.alpha = alpha;
|
||||
}
|
||||
|
||||
public AlphaColor(
|
||||
@Range(from = 0L, to = 1L) float red,
|
||||
@Range(from = 0L, to = 1L) float green,
|
||||
@Range(from = 0L, to = 1L) float blue
|
||||
) {
|
||||
this(1f, red, green, blue);
|
||||
}
|
||||
|
||||
public AlphaColor(
|
||||
@Range(from = 0L, to = 1L) float alpha,
|
||||
@Range(from = 0L, to = 1L) float red,
|
||||
@Range(from = 0L, to = 1L) float green,
|
||||
@Range(from = 0L, to = 1L) float blue
|
||||
) {
|
||||
super(red, green, blue);
|
||||
this.alpha = MathUtil.floor(alpha * 255f);
|
||||
}
|
||||
|
||||
public AlphaColor(int rgb) {
|
||||
this((rgb >> 24) & BIT_MASK,
|
||||
(rgb >> 16) & BIT_MASK,
|
||||
(rgb >> 8) & BIT_MASK,
|
||||
rgb & BIT_MASK);
|
||||
}
|
||||
|
||||
public static AlphaColor decode(NBT nbt, ClientVersion version) {
|
||||
if (nbt instanceof NBTNumber) {
|
||||
return new AlphaColor(((NBTNumber) nbt).getAsInt());
|
||||
}
|
||||
NBTList<?> list = (NBTList<?>) nbt;
|
||||
float red = ((NBTNumber) list.getTag(0)).getAsFloat();
|
||||
float green = ((NBTNumber) list.getTag(1)).getAsFloat();
|
||||
float blue = ((NBTNumber) list.getTag(2)).getAsFloat();
|
||||
float alpha = ((NBTNumber) list.getTag(3)).getAsFloat();
|
||||
return new AlphaColor(alpha, red, green, blue);
|
||||
}
|
||||
|
||||
public static NBT encode(AlphaColor color, ClientVersion version) {
|
||||
if (version.isNewerThanOrEquals(ClientVersion.V_1_21_2)) {
|
||||
return new NBTInt(color.asRGB());
|
||||
}
|
||||
NBTList<NBTFloat> list = new NBTList<>(NBTType.FLOAT, 4);
|
||||
list.addTag(new NBTFloat(color.red));
|
||||
list.addTag(new NBTFloat(color.green));
|
||||
list.addTag(new NBTFloat(color.blue));
|
||||
list.addTag(new NBTFloat(color.alpha));
|
||||
return list;
|
||||
}
|
||||
|
||||
public AlphaColor withAlpha(@Range(from = 0L, to = 255L) int alpha) {
|
||||
return new AlphaColor(alpha, this.red, this.green, this.blue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AlphaColor withRed(@Range(from = 0L, to = 255L) int red) {
|
||||
return new AlphaColor(this.alpha, red, this.green, this.blue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AlphaColor withGreen(@Range(from = 0L, to = 255L) int green) {
|
||||
return new AlphaColor(this.alpha, this.red, green, this.blue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AlphaColor withBlue(@Range(from = 0L, to = 255L) int blue) {
|
||||
return new AlphaColor(this.alpha, this.red, this.green, blue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int asRGB() {
|
||||
return (this.alpha << 24) | (this.red << 16) | (this.green << 8) | this.blue;
|
||||
}
|
||||
|
||||
public @Range(from = 0L, to = 255L) int alpha() {
|
||||
return this.alpha;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Range(from = 0L, to = 255L) int red() {
|
||||
return this.red;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Range(from = 0L, to = 255L) int green() {
|
||||
return this.green;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Range(from = 0L, to = 255L) int blue() {
|
||||
return this.blue;
|
||||
}
|
||||
}
|
||||
@@ -18,15 +18,24 @@
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.color;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTFloat;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTInt;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTList;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTNumber;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTType;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.util.MathUtil;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import net.kyori.adventure.util.RGBLike;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Range;
|
||||
|
||||
public final class Color implements RGBLike {
|
||||
public class Color implements RGBLike {
|
||||
|
||||
private static final int BIT_MASK = 0xFF;
|
||||
protected static final int BIT_MASK = 0xFF;
|
||||
|
||||
private final int red, green, blue;
|
||||
protected final int red, green, blue;
|
||||
|
||||
public Color(@Range(from = 0L, to = 255L) int red, @Range(from = 0L, to = 255L) int green, @Range(from = 0L, to = 255L) int blue) {
|
||||
this.red = red;
|
||||
@@ -34,10 +43,50 @@ public final class Color implements RGBLike {
|
||||
this.blue = blue;
|
||||
}
|
||||
|
||||
public Color(
|
||||
@Range(from = 0L, to = 1L) float red,
|
||||
@Range(from = 0L, to = 1L) float green,
|
||||
@Range(from = 0L, to = 1L) float blue
|
||||
) {
|
||||
this(MathUtil.floor(red * 255f),
|
||||
MathUtil.floor(green * 255f),
|
||||
MathUtil.floor(blue * 255f));
|
||||
}
|
||||
|
||||
public Color(int rgb) {
|
||||
this((rgb >> 16) & BIT_MASK, (rgb >> 8) & BIT_MASK, rgb & BIT_MASK);
|
||||
}
|
||||
|
||||
public static Color read(PacketWrapper<?> wrapper) {
|
||||
return new Color(wrapper.readInt());
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, Color color) {
|
||||
wrapper.writeInt(color.asRGB());
|
||||
}
|
||||
|
||||
public static Color decode(NBT nbt, ClientVersion version) {
|
||||
if (nbt instanceof NBTNumber) {
|
||||
return new Color(((NBTNumber) nbt).getAsInt());
|
||||
}
|
||||
NBTList<?> list = (NBTList<?>) nbt;
|
||||
float red = ((NBTNumber) list.getTag(0)).getAsFloat();
|
||||
float green = ((NBTNumber) list.getTag(1)).getAsFloat();
|
||||
float blue = ((NBTNumber) list.getTag(2)).getAsFloat();
|
||||
return new Color(red, green, blue);
|
||||
}
|
||||
|
||||
public static NBT encode(Color color, ClientVersion version) {
|
||||
if (version.isNewerThanOrEquals(ClientVersion.V_1_21_2)) {
|
||||
return new NBTInt(color.asRGB());
|
||||
}
|
||||
NBTList<NBTFloat> list = new NBTList<>(NBTType.FLOAT, 3);
|
||||
list.addTag(new NBTFloat(color.red));
|
||||
list.addTag(new NBTFloat(color.green));
|
||||
list.addTag(new NBTFloat(color.blue));
|
||||
return list;
|
||||
}
|
||||
|
||||
public @NotNull Color withRed(@Range(from = 0L, to = 255L) int red) {
|
||||
return new Color(red, green, blue);
|
||||
}
|
||||
@@ -51,9 +100,7 @@ public final class Color implements RGBLike {
|
||||
}
|
||||
|
||||
public int asRGB() {
|
||||
int rgb = red;
|
||||
rgb = (rgb << 8) + green;
|
||||
return (rgb << 8) + blue;
|
||||
return (this.red << 16) | (this.green << 8) | this.blue;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -70,4 +117,4 @@ public final class Color implements RGBLike {
|
||||
public @Range(from = 0L, to = 255L) int blue() {
|
||||
return blue;
|
||||
}
|
||||
}
|
||||
}
|
||||
+19
@@ -23,6 +23,7 @@ import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
@@ -88,4 +89,22 @@ public class ComponentPredicate implements Predicate<IComponentMap> {
|
||||
public void setRequiredComponents(List<ComponentValue<?>> requiredComponents) {
|
||||
this.requiredComponents = requiredComponents;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof ComponentPredicate)) return false;
|
||||
ComponentPredicate that = (ComponentPredicate) obj;
|
||||
return this.requiredComponents.equals(that.requiredComponents);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(this.requiredComponents);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ComponentPredicate{requiredComponents=" + this.requiredComponents + '}';
|
||||
}
|
||||
}
|
||||
+22
@@ -19,11 +19,33 @@
|
||||
package com.github.retrooper.packetevents.protocol.component;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.mapper.MappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public interface ComponentType<T> extends MappedEntity {
|
||||
|
||||
T read(PacketWrapper<?> wrapper);
|
||||
|
||||
void write(PacketWrapper<?> wrapper, T content);
|
||||
|
||||
T decode(NBT nbt, ClientVersion version);
|
||||
|
||||
NBT encode(T value, ClientVersion version);
|
||||
|
||||
@ApiStatus.Internal
|
||||
<Z> ComponentType<Z> legacyMap(Function<T, Z> mapper, Function<Z, T> unmapper);
|
||||
|
||||
interface Decoder<T> {
|
||||
|
||||
T decode(NBT nbt, ClientVersion version);
|
||||
}
|
||||
|
||||
interface Encoder<T> {
|
||||
|
||||
NBT encode(T value, ClientVersion version);
|
||||
}
|
||||
}
|
||||
+73
-68
@@ -31,21 +31,32 @@ import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemAdv
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemAttributeModifiers;
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemBees;
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemBlockStateProperties;
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemConsumable;
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemContainerContents;
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemContainerLoot;
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemCustomModelData;
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemDamageResistant;
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemDeathProtection;
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemDyeColor;
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemEnchantable;
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemEnchantments;
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemEquippable;
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemFireworks;
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemJukeboxPlayable;
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemLock;
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemLore;
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemMapDecorations;
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemMapPostProcessingState;
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemModel;
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemPotionContents;
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemProfile;
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemRarity;
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemRecipes;
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemRepairable;
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemTool;
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemTooltipStyle;
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemUseCooldown;
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemUseRemainder;
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.LodestoneTracker;
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.PotDecorations;
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.SuspiciousStewEffects;
|
||||
@@ -56,85 +67,51 @@ import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.util.Dummy;
|
||||
import com.github.retrooper.packetevents.util.mappings.MappingHelper;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilder;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import com.github.retrooper.packetevents.util.mappings.VersionedRegistry;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper.Reader;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper.Writer;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class ComponentTypes {
|
||||
/**
|
||||
* Contains all item data component types.
|
||||
*
|
||||
* @see EnchantEffectComponentTypes
|
||||
*/
|
||||
public final class ComponentTypes {
|
||||
|
||||
private static final Map<String, ComponentType<?>> COMPONENT_TYPE_MAP = new HashMap<>();
|
||||
private static final Map<Byte, Map<Integer, ComponentType<?>>> COMPONENT_TYPE_ID_MAP = new HashMap<>();
|
||||
private static final TypesBuilder TYPES_BUILDER = new TypesBuilder("item/item_component_mappings");
|
||||
private static final VersionedRegistry<ComponentType<?>> REGISTRY = new VersionedRegistry<>(
|
||||
"data_component_type", "item/item_component_mappings");
|
||||
|
||||
private ComponentTypes() {
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static <T> ComponentType<T> define(String key) {
|
||||
return define(key, null, null);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static <T> ComponentType<T> define(String key, @Nullable Reader<T> reader, @Nullable Writer<T> writer) {
|
||||
TypesBuilderData data = TYPES_BUILDER.define(key);
|
||||
ComponentType<T> type = new ComponentType<T>() {
|
||||
@Override
|
||||
public T read(PacketWrapper<?> wrapper) {
|
||||
return reader == null ? null : reader.apply(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(PacketWrapper<?> wrapper, T content) {
|
||||
if (writer != null) {
|
||||
writer.accept(wrapper, content);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getName() {
|
||||
return data.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId(ClientVersion version) {
|
||||
return MappingHelper.getId(version, TYPES_BUILDER, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof ComponentType<?>) {
|
||||
return this.getName().equals(((ComponentType<?>) obj).getName());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Component[" + this.getName() + "]";
|
||||
}
|
||||
};
|
||||
|
||||
MappingHelper.registerMapping(TYPES_BUILDER, COMPONENT_TYPE_MAP, COMPONENT_TYPE_ID_MAP, type);
|
||||
return type;
|
||||
return REGISTRY.define(key, data -> new StaticComponentType<>(data, reader, writer));
|
||||
}
|
||||
|
||||
public static VersionedRegistry<ComponentType<?>> getRegistry() {
|
||||
return REGISTRY;
|
||||
}
|
||||
|
||||
// with key
|
||||
public static ComponentType<?> getByName(String name) {
|
||||
return COMPONENT_TYPE_MAP.get(name);
|
||||
return REGISTRY.getByName(name);
|
||||
}
|
||||
|
||||
public static ComponentType<?> getById(ClientVersion version, int id) {
|
||||
int index = TYPES_BUILDER.getDataIndex(version);
|
||||
Map<Integer, ComponentType<?>> idMap = COMPONENT_TYPE_ID_MAP.get((byte) index);
|
||||
return idMap.get(id);
|
||||
return REGISTRY.getById(version, id);
|
||||
}
|
||||
|
||||
// item component types
|
||||
public static final ComponentType<NBTCompound> CUSTOM_DATA = define("custom_data",
|
||||
// mojang wraps their "persistent" codec as a stream codec just here,
|
||||
// so packetevents has to handle nbt strings
|
||||
@@ -163,8 +140,14 @@ public class ComponentTypes {
|
||||
ItemAdventurePredicate::read, ItemAdventurePredicate::write);
|
||||
public static final ComponentType<ItemAttributeModifiers> ATTRIBUTE_MODIFIERS = define("attribute_modifiers",
|
||||
ItemAttributeModifiers::read, ItemAttributeModifiers::write);
|
||||
public static final ComponentType<Integer> CUSTOM_MODEL_DATA = define("custom_model_data",
|
||||
PacketWrapper::readVarInt, PacketWrapper::writeVarInt);
|
||||
public static final ComponentType<ItemCustomModelData> CUSTOM_MODEL_DATA_LISTS = define("custom_model_data",
|
||||
ItemCustomModelData::read, ItemCustomModelData::write);
|
||||
/**
|
||||
* Rewritten in 1.21.4
|
||||
*/
|
||||
@Deprecated
|
||||
public static final ComponentType<Integer> CUSTOM_MODEL_DATA = CUSTOM_MODEL_DATA_LISTS.legacyMap(
|
||||
ItemCustomModelData::getLegacyId, ItemCustomModelData::new);
|
||||
public static final ComponentType<Dummy> HIDE_ADDITIONAL_TOOLTIP = define("hide_additional_tooltip",
|
||||
Dummy::dummyRead, Dummy::dummyWrite);
|
||||
public static final ComponentType<Dummy> HIDE_TOOLTIP = define("hide_tooltip",
|
||||
@@ -179,6 +162,10 @@ public class ComponentTypes {
|
||||
Dummy::dummyReadNbt, Dummy::dummyWriteNbt);
|
||||
public static final ComponentType<FoodProperties> FOOD = define("food",
|
||||
FoodProperties::read, FoodProperties::write);
|
||||
/**
|
||||
* Has been migrated to #DAMAGE_RESISTANT with 1.21.2.
|
||||
*/
|
||||
@ApiStatus.Obsolete
|
||||
public static final ComponentType<Dummy> FIRE_RESISTANT = define("fire_resistant",
|
||||
Dummy::dummyRead, Dummy::dummyWrite);
|
||||
public static final ComponentType<ItemTool> TOOL = define("tool",
|
||||
@@ -254,22 +241,40 @@ public class ComponentTypes {
|
||||
public static final ComponentType<ItemJukeboxPlayable> JUKEBOX_PLAYABLE = define("jukebox_playable",
|
||||
ItemJukeboxPlayable::read, ItemJukeboxPlayable::write);
|
||||
|
||||
// added in 1.21.2
|
||||
public static final ComponentType<ItemConsumable> CONSUMABLE = define("consumable",
|
||||
ItemConsumable::read, ItemConsumable::write);
|
||||
public static final ComponentType<ItemUseRemainder> USE_REMAINDER = define("use_remainder",
|
||||
ItemUseRemainder::read, ItemUseRemainder::write);
|
||||
public static final ComponentType<ItemUseCooldown> USE_COOLDOWN = define("use_cooldown",
|
||||
ItemUseCooldown::read, ItemUseCooldown::write);
|
||||
public static final ComponentType<ItemEnchantable> ENCHANTABLE = define("enchantable",
|
||||
ItemEnchantable::read, ItemEnchantable::write);
|
||||
public static final ComponentType<ItemRepairable> REPAIRABLE = define("repairable",
|
||||
ItemRepairable::read, ItemRepairable::write);
|
||||
public static final ComponentType<ItemModel> ITEM_MODEL = define("item_model",
|
||||
ItemModel::read, ItemModel::write);
|
||||
public static final ComponentType<ItemDamageResistant> DAMAGE_RESISTANT = define("damage_resistant",
|
||||
ItemDamageResistant::read, ItemDamageResistant::write);
|
||||
public static final ComponentType<ItemEquippable> EQUIPPABLE = define("equippable",
|
||||
ItemEquippable::read, ItemEquippable::write);
|
||||
public static final ComponentType<Dummy> GLIDER = define("glider",
|
||||
Dummy::dummyRead, Dummy::dummyWrite);
|
||||
public static final ComponentType<ItemDeathProtection> DEATH_PROTECTION = define("death_protection",
|
||||
ItemDeathProtection::read, ItemDeathProtection::write);
|
||||
public static final ComponentType<ItemTooltipStyle> TOOLTIP_STYLE = define("tooltip_style",
|
||||
ItemTooltipStyle::read, ItemTooltipStyle::write);
|
||||
|
||||
/**
|
||||
* Returns an immutable view of the component types.
|
||||
*
|
||||
* @return Component Types
|
||||
*/
|
||||
public static Collection<ComponentType<?>> values() {
|
||||
return Collections.unmodifiableCollection(COMPONENT_TYPE_MAP.values());
|
||||
return REGISTRY.getEntries();
|
||||
}
|
||||
|
||||
static {
|
||||
TYPES_BUILDER.unloadFileMappings();
|
||||
REGISTRY.unloadMappings();
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Reader<T> extends Function<PacketWrapper<?>, T> {}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Writer<T> extends BiConsumer<PacketWrapper<?>, T> {}
|
||||
}
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.component;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.component.ComponentType.Decoder;
|
||||
import com.github.retrooper.packetevents.protocol.component.ComponentType.Encoder;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||
import com.github.retrooper.packetevents.util.mappings.VersionedRegistry;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Contains all enchantment effect component types.
|
||||
*
|
||||
* @see ComponentTypes
|
||||
*/
|
||||
public final class EnchantEffectComponentTypes {
|
||||
|
||||
private static final VersionedRegistry<ComponentType<?>> REGISTRY = new VersionedRegistry<>(
|
||||
"enchantment_effect_component_type", "enchantment/effect_component_type");
|
||||
|
||||
private EnchantEffectComponentTypes() {
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static <T> ComponentType<T> define(String key) {
|
||||
return define(key, null, null);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static <T> ComponentType<T> define(String key, @Nullable Decoder<T> reader, @Nullable Encoder<T> writer) {
|
||||
return REGISTRY.define(key, data -> new StaticComponentType<>(data, reader, writer));
|
||||
}
|
||||
|
||||
public static VersionedRegistry<ComponentType<?>> getRegistry() {
|
||||
return REGISTRY;
|
||||
}
|
||||
|
||||
// just pass everything through for now
|
||||
public static ComponentType<NBT> DAMAGE_PROTECTION = define("damage_protection",
|
||||
(nbt, version) -> nbt, (val, version) -> val);
|
||||
public static ComponentType<NBT> DAMAGE_IMMUNITY = define("damage_immunity",
|
||||
(nbt, version) -> nbt, (val, version) -> val);
|
||||
public static ComponentType<NBT> DAMAGE = define("damage",
|
||||
(nbt, version) -> nbt, (val, version) -> val);
|
||||
public static ComponentType<NBT> SMASH_DAMAGE_PER_FALLEN_BLOCK = define("smash_damage_per_fallen_block",
|
||||
(nbt, version) -> nbt, (val, version) -> val);
|
||||
public static ComponentType<NBT> KNOCKBACK = define("knockback",
|
||||
(nbt, version) -> nbt, (val, version) -> val);
|
||||
public static ComponentType<NBT> ARMOR_EFFECTIVENESS = define("armor_effectiveness",
|
||||
(nbt, version) -> nbt, (val, version) -> val);
|
||||
public static ComponentType<NBT> POST_ATTACK = define("post_attack",
|
||||
(nbt, version) -> nbt, (val, version) -> val);
|
||||
public static ComponentType<NBT> HIT_BLOCK = define("hit_block",
|
||||
(nbt, version) -> nbt, (val, version) -> val);
|
||||
public static ComponentType<NBT> ITEM_DAMAGE = define("item_damage",
|
||||
(nbt, version) -> nbt, (val, version) -> val);
|
||||
public static ComponentType<NBT> ATTRIBUTES = define("attributes",
|
||||
(nbt, version) -> nbt, (val, version) -> val);
|
||||
public static ComponentType<NBT> EQUIPMENT_DROPS = define("equipment_drops",
|
||||
(nbt, version) -> nbt, (val, version) -> val);
|
||||
public static ComponentType<NBT> LOCATION_CHANGED = define("location_changed",
|
||||
(nbt, version) -> nbt, (val, version) -> val);
|
||||
public static ComponentType<NBT> TICK = define("tick",
|
||||
(nbt, version) -> nbt, (val, version) -> val);
|
||||
public static ComponentType<NBT> AMMO_USE = define("ammo_use",
|
||||
(nbt, version) -> nbt, (val, version) -> val);
|
||||
public static ComponentType<NBT> PROJECTILE_PIERCING = define("projectile_piercing",
|
||||
(nbt, version) -> nbt, (val, version) -> val);
|
||||
public static ComponentType<NBT> PROJECTILE_SPAWNED = define("projectile_spawned",
|
||||
(nbt, version) -> nbt, (val, version) -> val);
|
||||
public static ComponentType<NBT> PROJECTILE_SPREAD = define("projectile_spread",
|
||||
(nbt, version) -> nbt, (val, version) -> val);
|
||||
public static ComponentType<NBT> PROJECTILE_COUNT = define("projectile_count",
|
||||
(nbt, version) -> nbt, (val, version) -> val);
|
||||
public static ComponentType<NBT> TRIDENT_RETURN_ACCELERATION = define("trident_return_acceleration",
|
||||
(nbt, version) -> nbt, (val, version) -> val);
|
||||
public static ComponentType<NBT> FISHING_TIME_REDUCTION = define("fishing_time_reduction",
|
||||
(nbt, version) -> nbt, (val, version) -> val);
|
||||
public static ComponentType<NBT> FISHING_LUCK_BONUS = define("fishing_luck_bonus",
|
||||
(nbt, version) -> nbt, (val, version) -> val);
|
||||
public static ComponentType<NBT> BLOCK_EXPERIENCE = define("block_experience",
|
||||
(nbt, version) -> nbt, (val, version) -> val);
|
||||
public static ComponentType<NBT> MOB_EXPERIENCE = define("mob_experience",
|
||||
(nbt, version) -> nbt, (val, version) -> val);
|
||||
public static ComponentType<NBT> REPAIR_WITH_XP = define("repair_with_xp",
|
||||
(nbt, version) -> nbt, (val, version) -> val);
|
||||
public static ComponentType<NBT> CROSSBOW_CHARGE_TIME = define("crossbow_charge_time",
|
||||
(nbt, version) -> nbt, (val, version) -> val);
|
||||
public static ComponentType<NBT> CROSSBOW_CHARGING_SOUNDS = define("crossbow_charging_sounds",
|
||||
(nbt, version) -> nbt, (val, version) -> val);
|
||||
public static ComponentType<NBT> TRIDENT_SOUND = define("trident_sound",
|
||||
(nbt, version) -> nbt, (val, version) -> val);
|
||||
public static ComponentType<NBT> PREVENT_EQUIPMENT_DROP = define("prevent_equipment_drop",
|
||||
(nbt, version) -> nbt, (val, version) -> val);
|
||||
public static ComponentType<NBT> PREVENT_ARMOR_CHANGE = define("prevent_armor_change",
|
||||
(nbt, version) -> nbt, (val, version) -> val);
|
||||
public static ComponentType<NBT> TRIDENT_SPIN_ATTACK_STRENGTH = define("trident_spin_attack_strength",
|
||||
(nbt, version) -> nbt, (val, version) -> val);
|
||||
|
||||
static {
|
||||
REGISTRY.unloadMappings();
|
||||
}
|
||||
}
|
||||
+31
@@ -18,13 +18,44 @@
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.component;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.util.mappings.IRegistry;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface IComponentMap {
|
||||
|
||||
@SuppressWarnings("unchecked") // safe in this case
|
||||
static StaticComponentMap decode(NBT nbt, ClientVersion version, IRegistry<? extends ComponentType<?>> registry) {
|
||||
NBTCompound compound = (NBTCompound) nbt;
|
||||
StaticComponentMap.Builder components = StaticComponentMap.builder();
|
||||
for (Map.Entry<String, NBT> entry : compound.getTags().entrySet()) {
|
||||
ComponentType<?> type = registry.getByName(entry.getKey());
|
||||
if (type == null) {
|
||||
throw new IllegalStateException("Unknown component type named " + entry.getKey() + " encountered");
|
||||
}
|
||||
Object value = type.decode(entry.getValue(), version);
|
||||
components.set((ComponentType<? super Object>) type, value);
|
||||
}
|
||||
return components.build();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked") // safe in this case
|
||||
static NBT encode(StaticComponentMap components, ClientVersion version) {
|
||||
NBTCompound compound = new NBTCompound();
|
||||
for (Map.Entry<ComponentType<?>, ?> entry : components.getDelegate().entrySet()) {
|
||||
String key = entry.getKey().getName().toString();
|
||||
NBT value = ((ComponentType<? super Object>) entry.getKey()).encode(entry.getValue(), version);
|
||||
compound.setTag(key, value);
|
||||
}
|
||||
return compound;
|
||||
}
|
||||
|
||||
default <T> Optional<T> getOptional(ComponentType<T> type) {
|
||||
return Optional.ofNullable(this.get(type));
|
||||
}
|
||||
|
||||
+14
@@ -96,6 +96,20 @@ public class PatchableComponentMap implements IComponentMap {
|
||||
return this.patches;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof PatchableComponentMap)) return false;
|
||||
PatchableComponentMap that = (PatchableComponentMap) obj;
|
||||
if (!this.base.equals(that.base)) return false;
|
||||
return this.patches.equals(that.patches);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.base, this.patches);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PatchableComponentMap{base=" + this.base + ", patches=" + this.patches + '}';
|
||||
|
||||
+26
@@ -22,16 +22,20 @@ import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemAtt
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemEnchantments;
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemLore;
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemRarity;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
public class StaticComponentMap implements IComponentMap {
|
||||
|
||||
public static final StaticComponentMap EMPTY = new StaticComponentMap(Collections.emptyMap());
|
||||
|
||||
@ApiStatus.Obsolete
|
||||
public static final StaticComponentMap SHARED_ITEM_COMPONENTS = builder()
|
||||
.set(ComponentTypes.MAX_STACK_SIZE, 64)
|
||||
.set(ComponentTypes.LORE, ItemLore.EMPTY)
|
||||
@@ -82,6 +86,24 @@ public class StaticComponentMap implements IComponentMap {
|
||||
return this.empty;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof StaticComponentMap)) return false;
|
||||
StaticComponentMap that = (StaticComponentMap) obj;
|
||||
return this.delegate.equals(that.delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(this.delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Components" + this.delegate;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
private final Map<ComponentType<?>, Object> map = new HashMap<>();
|
||||
@@ -93,6 +115,10 @@ public class StaticComponentMap implements IComponentMap {
|
||||
return new StaticComponentMap(this.map);
|
||||
}
|
||||
|
||||
public Builder setAll(StaticComponentMap.Builder map) {
|
||||
return this.setAll(map.map);
|
||||
}
|
||||
|
||||
public Builder setAll(StaticComponentMap map) {
|
||||
return this.setAll(map.getDelegate());
|
||||
}
|
||||
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.component;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.mapper.AbstractMappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper.Reader;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper.Writer;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public class StaticComponentType<T> extends AbstractMappedEntity implements ComponentType<T> {
|
||||
|
||||
private final @Nullable Reader<T> reader;
|
||||
private final @Nullable Writer<T> writer;
|
||||
private final @Nullable Decoder<T> decoder;
|
||||
private final @Nullable Encoder<T> encoder;
|
||||
|
||||
public StaticComponentType(
|
||||
@Nullable TypesBuilderData data,
|
||||
@Nullable Reader<T> reader,
|
||||
@Nullable Writer<T> writer
|
||||
) {
|
||||
this(data, reader, writer, null, null);
|
||||
}
|
||||
|
||||
public StaticComponentType(
|
||||
@Nullable TypesBuilderData data,
|
||||
@Nullable Decoder<T> decoder,
|
||||
@Nullable Encoder<T> encoder
|
||||
) {
|
||||
this(data, null, null, decoder, encoder);
|
||||
}
|
||||
|
||||
public StaticComponentType(
|
||||
@Nullable TypesBuilderData data,
|
||||
@Nullable Reader<T> reader,
|
||||
@Nullable Writer<T> writer,
|
||||
@Nullable Decoder<T> decoder,
|
||||
@Nullable Encoder<T> encoder
|
||||
) {
|
||||
super(data);
|
||||
this.reader = reader;
|
||||
this.writer = writer;
|
||||
this.decoder = decoder;
|
||||
this.encoder = encoder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T read(PacketWrapper<?> wrapper) {
|
||||
return this.reader != null ? this.reader.apply(wrapper) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(PacketWrapper<?> wrapper, T content) {
|
||||
if (this.writer != null) {
|
||||
this.writer.accept(wrapper, content);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public T decode(NBT nbt, ClientVersion version) {
|
||||
if (this.decoder != null) {
|
||||
return this.decoder.decode(nbt, version);
|
||||
}
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NBT encode(T value, ClientVersion version) {
|
||||
if (this.encoder != null) {
|
||||
return this.encoder.encode(value, version);
|
||||
}
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <Z> ComponentType<Z> legacyMap(Function<T, Z> mapper, Function<Z, T> unmapper) {
|
||||
Reader<Z> reader = this.reader != null ? wrapper -> mapper.apply(this.reader.apply(wrapper)) : null;
|
||||
Writer<Z> writer = this.writer != null ? (wrapper, value) -> this.writer.accept(wrapper, unmapper.apply(value)) : null;
|
||||
Decoder<Z> decoder = this.decoder != null ? (nbt, version) -> mapper.apply(this.decoder.decode(nbt, version)) : null;
|
||||
Encoder<Z> encoder = this.encoder != null ? (value, version) -> this.encoder.encode(unmapper.apply(value), version) : null;
|
||||
return new StaticComponentType<>(this.data, reader, writer, decoder, encoder);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -80,7 +80,7 @@ public class BannerLayers {
|
||||
|
||||
public static Layer read(PacketWrapper<?> wrapper) {
|
||||
BannerPattern pattern = wrapper.readMappedEntityOrDirect(
|
||||
BannerPatterns::getById, BannerPattern::readDirect);
|
||||
BannerPatterns.getRegistry(), BannerPattern::readDirect);
|
||||
DyeColor color = wrapper.readEnum(DyeColor.values());
|
||||
return new Layer(pattern, color);
|
||||
}
|
||||
|
||||
+60
-5
@@ -22,8 +22,10 @@ import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||
import com.github.retrooper.packetevents.protocol.potion.PotionEffect;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -36,6 +38,17 @@ public class FoodProperties {
|
||||
private List<PossibleEffect> effects;
|
||||
private @Nullable ItemStack usingConvertsTo;
|
||||
|
||||
public FoodProperties(
|
||||
int nutrition, float saturation, boolean canAlwaysEat
|
||||
) {
|
||||
this(nutrition, saturation, canAlwaysEat, 1.6f, Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
* <code>eatSeconds</code> and <code>effects</code>
|
||||
* have been moved to {@link ItemConsumable} in 1.21.2
|
||||
*/
|
||||
@ApiStatus.Obsolete
|
||||
public FoodProperties(
|
||||
int nutrition, float saturation, boolean canAlwaysEat,
|
||||
float eatSeconds, List<PossibleEffect> effects
|
||||
@@ -43,6 +56,11 @@ public class FoodProperties {
|
||||
this(nutrition, saturation, canAlwaysEat, eatSeconds, effects, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* <code>eatSeconds</code>, <code>effects</code> and <code>usingConvertsTo</code>
|
||||
* have been moved to {@link ItemConsumable} in 1.21.2
|
||||
*/
|
||||
@ApiStatus.Obsolete
|
||||
public FoodProperties(
|
||||
int nutrition, float saturation, boolean canAlwaysEat, float eatSeconds,
|
||||
List<PossibleEffect> effects, @Nullable ItemStack usingConvertsTo
|
||||
@@ -59,10 +77,13 @@ public class FoodProperties {
|
||||
int nutrition = wrapper.readVarInt();
|
||||
float saturation = wrapper.readFloat();
|
||||
boolean canAlwaysEat = wrapper.readBoolean();
|
||||
if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_2)) {
|
||||
return new FoodProperties(nutrition, saturation, canAlwaysEat);
|
||||
}
|
||||
float eatSeconds = wrapper.readFloat();
|
||||
List<PossibleEffect> effects = wrapper.readList(PossibleEffect::read);
|
||||
ItemStack usingConvertsTo = wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21)
|
||||
? wrapper.readOptional(PacketWrapper::readItemStack) : null;
|
||||
List<PossibleEffect> effects = wrapper.readList(PossibleEffect::read);
|
||||
return new FoodProperties(nutrition, saturation, canAlwaysEat, eatSeconds, effects, usingConvertsTo);
|
||||
}
|
||||
|
||||
@@ -70,10 +91,12 @@ public class FoodProperties {
|
||||
wrapper.writeVarInt(props.nutrition);
|
||||
wrapper.writeFloat(props.saturation);
|
||||
wrapper.writeBoolean(props.canAlwaysEat);
|
||||
wrapper.writeFloat(props.eatSeconds);
|
||||
wrapper.writeList(props.effects, PossibleEffect::write);
|
||||
if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21)) {
|
||||
wrapper.writeOptional(props.usingConvertsTo, PacketWrapper::writeItemStack);
|
||||
if (wrapper.getServerVersion().isOlderThan(ServerVersion.V_1_21_2)) {
|
||||
wrapper.writeFloat(props.eatSeconds);
|
||||
if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21)) {
|
||||
wrapper.writeOptional(props.usingConvertsTo, PacketWrapper::writeItemStack);
|
||||
}
|
||||
wrapper.writeList(props.effects, PossibleEffect::write);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,30 +124,58 @@ public class FoodProperties {
|
||||
this.canAlwaysEat = canAlwaysEat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Has been moved to {@link ItemConsumable} in 1.21.2
|
||||
*/
|
||||
@ApiStatus.Obsolete
|
||||
public float getEatSeconds() {
|
||||
return this.eatSeconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Has been moved to {@link ItemConsumable} in 1.21.2
|
||||
*/
|
||||
@ApiStatus.Obsolete
|
||||
public void setEatSeconds(float eatSeconds) {
|
||||
this.eatSeconds = eatSeconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Has been moved to {@link ItemConsumable} in 1.21.2
|
||||
*/
|
||||
@ApiStatus.Obsolete
|
||||
public void addEffect(PossibleEffect effect) {
|
||||
this.effects.add(effect);
|
||||
}
|
||||
|
||||
/**
|
||||
* Has been moved to {@link ItemConsumable} in 1.21.2
|
||||
*/
|
||||
@ApiStatus.Obsolete
|
||||
public List<PossibleEffect> getEffects() {
|
||||
return this.effects;
|
||||
}
|
||||
|
||||
/**
|
||||
* Has been moved to {@link ItemConsumable} in 1.21.2
|
||||
*/
|
||||
@ApiStatus.Obsolete
|
||||
public void setEffects(List<PossibleEffect> effects) {
|
||||
this.effects = effects;
|
||||
}
|
||||
|
||||
/**
|
||||
* Has been moved to {@link ItemConsumable} in 1.21.2
|
||||
*/
|
||||
@ApiStatus.Obsolete
|
||||
public @Nullable ItemStack getUsingConvertsTo() {
|
||||
return this.usingConvertsTo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Has been moved to {@link ItemConsumable} in 1.21.2
|
||||
*/
|
||||
@ApiStatus.Obsolete
|
||||
public void setUsingConvertsTo(@Nullable ItemStack usingConvertsTo) {
|
||||
this.usingConvertsTo = usingConvertsTo;
|
||||
}
|
||||
@@ -147,6 +198,10 @@ public class FoodProperties {
|
||||
return Objects.hash(this.nutrition, this.saturation, this.canAlwaysEat, this.eatSeconds, this.effects, this.usingConvertsTo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Has been moved to {@link ItemConsumable} in 1.21.2
|
||||
*/
|
||||
@ApiStatus.Obsolete
|
||||
public static class PossibleEffect {
|
||||
|
||||
private PotionEffect effect;
|
||||
|
||||
+3
-2
@@ -104,8 +104,9 @@ public class ItemAdventurePredicate {
|
||||
public static BlockPredicate read(PacketWrapper<?> wrapper) {
|
||||
MappedEntitySet<StateType.Mapped> blocks = wrapper.readOptional(
|
||||
ew -> MappedEntitySet.read(ew, StateTypes::getMappedById));
|
||||
List<PropertyMatcher> properties = wrapper.readList(PropertyMatcher::read);
|
||||
NBTCompound nbt = wrapper.readNBT();
|
||||
List<PropertyMatcher> properties = wrapper.readOptional(
|
||||
ew -> wrapper.readList(PropertyMatcher::read));
|
||||
NBTCompound nbt = wrapper.readOptional(PacketWrapper::readNBT);
|
||||
return new BlockPredicate(blocks, properties, nbt);
|
||||
}
|
||||
|
||||
|
||||
+64
-16
@@ -18,10 +18,15 @@
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.component.builtin.item;
|
||||
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.protocol.attribute.Attribute;
|
||||
import com.github.retrooper.packetevents.protocol.attribute.AttributeOperation;
|
||||
import com.github.retrooper.packetevents.protocol.attribute.Attributes;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerUpdateAttributes.PropertyModifier;
|
||||
import net.kyori.adventure.util.Index;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -168,11 +173,16 @@ public class ItemAttributeModifiers {
|
||||
|
||||
public static class Modifier {
|
||||
|
||||
private UUID id;
|
||||
private String name;
|
||||
private UUID id; // removed in 1.21
|
||||
private String name; // ResourceLocation since 1.21
|
||||
private double value;
|
||||
private AttributeOperation operation;
|
||||
|
||||
public Modifier(ResourceLocation name, double value, AttributeOperation operation) {
|
||||
this(PropertyModifier.generateSemiUniqueId(name), name.toString(), value, operation);
|
||||
}
|
||||
|
||||
@ApiStatus.Obsolete
|
||||
public Modifier(UUID id, String name, double value, AttributeOperation operation) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
@@ -181,32 +191,56 @@ public class ItemAttributeModifiers {
|
||||
}
|
||||
|
||||
public static Modifier read(PacketWrapper<?> wrapper) {
|
||||
UUID id = wrapper.readUUID();
|
||||
String name = wrapper.readString();
|
||||
UUID id;
|
||||
String name;
|
||||
if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21)) {
|
||||
ResourceLocation nameKey = wrapper.readIdentifier();
|
||||
name = nameKey.toString();
|
||||
id = PropertyModifier.generateSemiUniqueId(nameKey);
|
||||
} else {
|
||||
id = wrapper.readUUID();
|
||||
name = wrapper.readString();
|
||||
}
|
||||
double value = wrapper.readDouble();
|
||||
AttributeOperation operation = wrapper.readEnum(AttributeOperation.values());
|
||||
return new Modifier(id, name, value, operation);
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, Modifier modifier) {
|
||||
wrapper.writeUUID(modifier.id);
|
||||
wrapper.writeString(modifier.name);
|
||||
if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21)) {
|
||||
wrapper.writeIdentifier(new ResourceLocation(modifier.name));
|
||||
} else {
|
||||
wrapper.writeUUID(modifier.id);
|
||||
wrapper.writeString(modifier.name);
|
||||
}
|
||||
wrapper.writeDouble(modifier.value);
|
||||
wrapper.writeEnum(modifier.operation);
|
||||
}
|
||||
|
||||
public ResourceLocation getNameKey() {
|
||||
return new ResourceLocation(this.name);
|
||||
}
|
||||
|
||||
public void setNameKey(ResourceLocation nameKey) {
|
||||
this.name = nameKey.toString();
|
||||
}
|
||||
|
||||
@ApiStatus.Obsolete
|
||||
public UUID getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@ApiStatus.Obsolete
|
||||
public void setId(UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@ApiStatus.Obsolete
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@ApiStatus.Obsolete
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
@@ -250,15 +284,29 @@ public class ItemAttributeModifiers {
|
||||
}
|
||||
|
||||
public enum EquipmentSlotGroup {
|
||||
ANY,
|
||||
MAINHAND,
|
||||
OFFHAND,
|
||||
HAND,
|
||||
FEET,
|
||||
LEGS,
|
||||
CHEST,
|
||||
HEAD,
|
||||
ARMOR,
|
||||
BODY,
|
||||
|
||||
ANY("any"),
|
||||
MAINHAND("mainhand"),
|
||||
OFFHAND("offhand"),
|
||||
HAND("hand"),
|
||||
FEET("feet"),
|
||||
LEGS("legs"),
|
||||
CHEST("chest"),
|
||||
HEAD("head"),
|
||||
ARMOR("armor"),
|
||||
BODY("body");
|
||||
|
||||
public static final Index<String, EquipmentSlotGroup> ID_INDEX = Index.create(
|
||||
EquipmentSlotGroup.class, EquipmentSlotGroup::getId);
|
||||
|
||||
private final String id;
|
||||
|
||||
EquipmentSlotGroup(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
}
|
||||
}
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.component.builtin.item;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.item.consumables.ConsumeEffect;
|
||||
import com.github.retrooper.packetevents.protocol.sound.Sound;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class ItemConsumable {
|
||||
|
||||
private float consumeSeconds;
|
||||
private Animation animation;
|
||||
private Sound sound;
|
||||
private boolean consumeParticles;
|
||||
private List<ConsumeEffect<?>> effects;
|
||||
|
||||
public ItemConsumable(
|
||||
float consumeSeconds, Animation animation, Sound sound,
|
||||
boolean consumeParticles, List<ConsumeEffect<?>> effects
|
||||
) {
|
||||
this.consumeSeconds = consumeSeconds;
|
||||
this.animation = animation;
|
||||
this.sound = sound;
|
||||
this.consumeParticles = consumeParticles;
|
||||
this.effects = effects;
|
||||
}
|
||||
|
||||
public static ItemConsumable read(PacketWrapper<?> wrapper) {
|
||||
float consumeSeconds = wrapper.readFloat();
|
||||
Animation animation = wrapper.readEnum(Animation.values());
|
||||
Sound sound = Sound.read(wrapper);
|
||||
boolean consumeParticles = wrapper.readBoolean();
|
||||
List<ConsumeEffect<?>> effects = wrapper.readList(ConsumeEffect::readFull);
|
||||
return new ItemConsumable(consumeSeconds, animation, sound, consumeParticles, effects);
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, ItemConsumable consumable) {
|
||||
wrapper.writeFloat(consumable.consumeSeconds);
|
||||
wrapper.writeEnum(consumable.animation);
|
||||
Sound.write(wrapper, consumable.sound);
|
||||
wrapper.writeBoolean(consumable.consumeParticles);
|
||||
wrapper.writeList(consumable.effects, ConsumeEffect::writeFull);
|
||||
}
|
||||
|
||||
public float getConsumeSeconds() {
|
||||
return this.consumeSeconds;
|
||||
}
|
||||
|
||||
public void setConsumeSeconds(float consumeSeconds) {
|
||||
this.consumeSeconds = consumeSeconds;
|
||||
}
|
||||
|
||||
public Animation getAnimation() {
|
||||
return this.animation;
|
||||
}
|
||||
|
||||
public void setAnimation(Animation animation) {
|
||||
this.animation = animation;
|
||||
}
|
||||
|
||||
public Sound getSound() {
|
||||
return this.sound;
|
||||
}
|
||||
|
||||
public void setSound(Sound sound) {
|
||||
this.sound = sound;
|
||||
}
|
||||
|
||||
public boolean isConsumeParticles() {
|
||||
return this.consumeParticles;
|
||||
}
|
||||
|
||||
public void setConsumeParticles(boolean consumeParticles) {
|
||||
this.consumeParticles = consumeParticles;
|
||||
}
|
||||
|
||||
public List<ConsumeEffect<?>> getEffects() {
|
||||
return this.effects;
|
||||
}
|
||||
|
||||
public void setEffects(List<ConsumeEffect<?>> effects) {
|
||||
this.effects = effects;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof ItemConsumable)) return false;
|
||||
ItemConsumable that = (ItemConsumable) obj;
|
||||
if (Float.compare(that.consumeSeconds, this.consumeSeconds) != 0) return false;
|
||||
if (this.consumeParticles != that.consumeParticles) return false;
|
||||
if (this.animation != that.animation) return false;
|
||||
if (!this.sound.equals(that.sound)) return false;
|
||||
return this.effects.equals(that.effects);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.consumeSeconds, this.animation, this.sound, this.consumeParticles, this.effects);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ItemConsumable{consumeSeconds=" + this.consumeSeconds + ", animation=" + this.animation + ", sound=" + this.sound + ", consumeParticles=" + this.consumeParticles + ", effects=" + this.effects + '}';
|
||||
}
|
||||
|
||||
public enum Animation {
|
||||
|
||||
NONE,
|
||||
EAT,
|
||||
DRINK,
|
||||
BLOCK,
|
||||
BOW,
|
||||
SPEAR,
|
||||
CROSSBOW,
|
||||
SPYGLASS,
|
||||
TOOT_HORN,
|
||||
BRUSH,
|
||||
/**
|
||||
* Added with 1.21.4
|
||||
*/
|
||||
BUNDLE,
|
||||
;
|
||||
}
|
||||
}
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.component.builtin.item;
|
||||
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.protocol.color.Color;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Custom model data was completely rewritten with 1.21.4.
|
||||
* <p>
|
||||
* Before 1.21.4, this used to be a single integer.<br/>
|
||||
* With 1.21.4, this is now a holder of many elements.
|
||||
* <p>
|
||||
* If possible, use {@link com.github.retrooper.packetevents.protocol.component.ComponentTypes#ITEM_MODEL}
|
||||
* instead for specifying which model an item should have.
|
||||
* <p>
|
||||
* When working with legacy versions, the first element in the {@link #floats}
|
||||
* will represent the legacy single integer, just like Mojang is handling this.
|
||||
*/
|
||||
public class ItemCustomModelData {
|
||||
|
||||
private List<Float> floats;
|
||||
private List<Boolean> flags;
|
||||
private List<String> strings;
|
||||
private List<Color> colors;
|
||||
|
||||
public ItemCustomModelData(List<Float> floats, List<Boolean> flags, List<String> strings, List<Color> colors) {
|
||||
this.floats = floats;
|
||||
this.flags = flags;
|
||||
this.strings = strings;
|
||||
this.colors = colors;
|
||||
}
|
||||
|
||||
public ItemCustomModelData(int legacyId) {
|
||||
this.floats = new ArrayList<>(1);
|
||||
this.flags = new ArrayList<>(0);
|
||||
this.strings = new ArrayList<>(0);
|
||||
this.colors = new ArrayList<>(0);
|
||||
this.setLegacyId(legacyId);
|
||||
}
|
||||
|
||||
public static ItemCustomModelData read(PacketWrapper<?> wrapper) {
|
||||
if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_4)) {
|
||||
return new ItemCustomModelData(
|
||||
wrapper.readList(PacketWrapper::readFloat),
|
||||
wrapper.readList(PacketWrapper::readBoolean),
|
||||
wrapper.readList(PacketWrapper::readString),
|
||||
wrapper.readList(Color::read));
|
||||
} else {
|
||||
return new ItemCustomModelData(wrapper.readVarInt());
|
||||
}
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, ItemCustomModelData data) {
|
||||
if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_4)) {
|
||||
wrapper.writeList(data.floats, PacketWrapper::writeFloat);
|
||||
wrapper.writeList(data.flags, PacketWrapper::writeBoolean);
|
||||
wrapper.writeList(data.strings, PacketWrapper::writeString);
|
||||
wrapper.writeList(data.colors, Color::write);
|
||||
} else {
|
||||
wrapper.writeVarInt(data.getLegacyId());
|
||||
}
|
||||
}
|
||||
|
||||
public List<Float> getFloats() {
|
||||
return this.floats;
|
||||
}
|
||||
|
||||
public void setFloats(List<Float> floats) {
|
||||
this.floats = floats;
|
||||
}
|
||||
|
||||
public List<Boolean> getFlags() {
|
||||
return this.flags;
|
||||
}
|
||||
|
||||
public void setFlags(List<Boolean> flags) {
|
||||
this.flags = flags;
|
||||
}
|
||||
|
||||
public List<String> getStrings() {
|
||||
return this.strings;
|
||||
}
|
||||
|
||||
public void setStrings(List<String> strings) {
|
||||
this.strings = strings;
|
||||
}
|
||||
|
||||
public List<Color> getColors() {
|
||||
return this.colors;
|
||||
}
|
||||
|
||||
public void setColors(List<Color> colors) {
|
||||
this.colors = colors;
|
||||
}
|
||||
|
||||
@ApiStatus.Obsolete
|
||||
public int getLegacyId() {
|
||||
if (!this.floats.isEmpty()) {
|
||||
return this.floats.get(0).intValue();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ApiStatus.Obsolete
|
||||
public void setLegacyId(int legacyId) {
|
||||
if (this.flags.isEmpty()) {
|
||||
this.floats.add((float) legacyId);
|
||||
} else {
|
||||
this.floats.set(0, (float) legacyId);
|
||||
}
|
||||
}
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.component.builtin.item;
|
||||
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class ItemDamageResistant {
|
||||
|
||||
private ResourceLocation typesTagKey;
|
||||
|
||||
public ItemDamageResistant(ResourceLocation typesTagKey) {
|
||||
this.typesTagKey = typesTagKey;
|
||||
}
|
||||
|
||||
public static ItemDamageResistant read(PacketWrapper<?> wrapper) {
|
||||
return new ItemDamageResistant(wrapper.readIdentifier());
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, ItemDamageResistant resistant) {
|
||||
wrapper.writeIdentifier(resistant.typesTagKey);
|
||||
}
|
||||
|
||||
public ResourceLocation getTypesTagKey() {
|
||||
return this.typesTagKey;
|
||||
}
|
||||
|
||||
public void setTypesTagKey(ResourceLocation typesTagKey) {
|
||||
this.typesTagKey = typesTagKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof ItemDamageResistant)) return false;
|
||||
ItemDamageResistant that = (ItemDamageResistant) obj;
|
||||
return this.typesTagKey.equals(that.typesTagKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(this.typesTagKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ItemDamageResistant{typesTagKey=" + this.typesTagKey + '}';
|
||||
}
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.component.builtin.item;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.item.consumables.ConsumeEffect;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class ItemDeathProtection {
|
||||
|
||||
private List<ConsumeEffect<?>> deathEffects;
|
||||
|
||||
public ItemDeathProtection(List<ConsumeEffect<?>> deathEffects) {
|
||||
this.deathEffects = deathEffects;
|
||||
}
|
||||
|
||||
public static ItemDeathProtection read(PacketWrapper<?> wrapper) {
|
||||
List<ConsumeEffect<?>> deathEffects = wrapper.readList(ConsumeEffect::readFull);
|
||||
return new ItemDeathProtection(deathEffects);
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, ItemDeathProtection deathProtection) {
|
||||
wrapper.writeList(deathProtection.deathEffects, ConsumeEffect::writeFull);
|
||||
}
|
||||
|
||||
public List<ConsumeEffect<?>> getDeathEffects() {
|
||||
return this.deathEffects;
|
||||
}
|
||||
|
||||
public void setDeathEffects(List<ConsumeEffect<?>> deathEffects) {
|
||||
this.deathEffects = deathEffects;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof ItemDeathProtection)) return false;
|
||||
ItemDeathProtection that = (ItemDeathProtection) obj;
|
||||
return this.deathEffects.equals(that.deathEffects);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(this.deathEffects);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ItemDeathProtection{deathEffects=" + this.deathEffects + '}';
|
||||
}
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.component.builtin.item;
|
||||
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class ItemEnchantable {
|
||||
|
||||
private int value;
|
||||
|
||||
public ItemEnchantable(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public static ItemEnchantable read(PacketWrapper<?> wrapper) {
|
||||
int value = wrapper.readVarInt();
|
||||
return new ItemEnchantable(value);
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, ItemEnchantable enchantable) {
|
||||
wrapper.writeVarInt(enchantable.value);
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public void setValue(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof ItemEnchantable)) return false;
|
||||
ItemEnchantable that = (ItemEnchantable) obj;
|
||||
return this.value == that.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(this.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ItemEnchantable{value=" + this.value + '}';
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -47,9 +47,8 @@ public class ItemEnchantments implements Iterable<Map.Entry<EnchantmentType, Int
|
||||
}
|
||||
|
||||
public static ItemEnchantments read(PacketWrapper<?> wrapper) {
|
||||
ClientVersion version = wrapper.getServerVersion().toClientVersion();
|
||||
Map<EnchantmentType, Integer> enchantments = wrapper.readMap(
|
||||
ew -> EnchantmentTypes.getById(version, ew.readVarInt()),
|
||||
ew -> wrapper.readMappedEntity(EnchantmentTypes.getRegistry()),
|
||||
PacketWrapper::readVarInt
|
||||
);
|
||||
boolean showInTooltip = wrapper.readBoolean();
|
||||
|
||||
+186
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.component.builtin.item;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
|
||||
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.MappedEntitySet;
|
||||
import com.github.retrooper.packetevents.protocol.player.EquipmentSlot;
|
||||
import com.github.retrooper.packetevents.protocol.sound.Sound;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class ItemEquippable {
|
||||
|
||||
private EquipmentSlot slot;
|
||||
private Sound equipSound;
|
||||
private @Nullable ResourceLocation assetId;
|
||||
private @Nullable ResourceLocation cameraOverlay;
|
||||
private @Nullable MappedEntitySet<EntityType> allowedEntities;
|
||||
private boolean dispensable;
|
||||
private boolean swappable;
|
||||
private boolean damageOnHurt;
|
||||
|
||||
public ItemEquippable(
|
||||
EquipmentSlot slot,
|
||||
Sound equipSound,
|
||||
@Nullable ResourceLocation assetId,
|
||||
@Nullable ResourceLocation cameraOverlay,
|
||||
@Nullable MappedEntitySet<EntityType> allowedEntities,
|
||||
boolean dispensable,
|
||||
boolean swappable,
|
||||
boolean damageOnHurt
|
||||
) {
|
||||
this.slot = slot;
|
||||
this.equipSound = equipSound;
|
||||
this.assetId = assetId;
|
||||
this.cameraOverlay = cameraOverlay;
|
||||
this.allowedEntities = allowedEntities;
|
||||
this.dispensable = dispensable;
|
||||
this.swappable = swappable;
|
||||
this.damageOnHurt = damageOnHurt;
|
||||
}
|
||||
|
||||
public static ItemEquippable read(PacketWrapper<?> wrapper) {
|
||||
EquipmentSlot slot = wrapper.readEnum(EquipmentSlot.values());
|
||||
Sound equipSound = Sound.read(wrapper);
|
||||
ResourceLocation model = wrapper.readOptional(PacketWrapper::readIdentifier);
|
||||
ResourceLocation cameraOverlay = wrapper.readOptional(PacketWrapper::readIdentifier);
|
||||
MappedEntitySet<EntityType> allowedEntities = wrapper.readOptional(
|
||||
ew -> MappedEntitySet.read(ew, EntityTypes::getById));
|
||||
boolean dispensable = wrapper.readBoolean();
|
||||
boolean swappable = wrapper.readBoolean();
|
||||
boolean damageOnHurt = wrapper.readBoolean();
|
||||
return new ItemEquippable(slot, equipSound, model,
|
||||
cameraOverlay, allowedEntities, dispensable, swappable, damageOnHurt);
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, ItemEquippable equippable) {
|
||||
wrapper.writeEnum(equippable.slot);
|
||||
Sound.write(wrapper, equippable.equipSound);
|
||||
wrapper.writeOptional(equippable.assetId, PacketWrapper::writeIdentifier);
|
||||
wrapper.writeOptional(equippable.cameraOverlay, PacketWrapper::writeIdentifier);
|
||||
wrapper.writeOptional(equippable.allowedEntities, MappedEntitySet::write);
|
||||
wrapper.writeBoolean(equippable.dispensable);
|
||||
wrapper.writeBoolean(equippable.swappable);
|
||||
wrapper.writeBoolean(equippable.damageOnHurt);
|
||||
}
|
||||
|
||||
public EquipmentSlot getSlot() {
|
||||
return this.slot;
|
||||
}
|
||||
|
||||
public void setSlot(EquipmentSlot slot) {
|
||||
this.slot = slot;
|
||||
}
|
||||
|
||||
public Sound getEquipSound() {
|
||||
return this.equipSound;
|
||||
}
|
||||
|
||||
public void setEquipSound(Sound equipSound) {
|
||||
this.equipSound = equipSound;
|
||||
}
|
||||
|
||||
public @Nullable ResourceLocation getAssetId() {
|
||||
return this.assetId;
|
||||
}
|
||||
|
||||
public void setAssetId(@Nullable ResourceLocation assetId) {
|
||||
this.assetId = assetId;
|
||||
}
|
||||
|
||||
public @Nullable ResourceLocation getCameraOverlay() {
|
||||
return this.cameraOverlay;
|
||||
}
|
||||
|
||||
public void setCameraOverlay(@Nullable ResourceLocation cameraOverlay) {
|
||||
this.cameraOverlay = cameraOverlay;
|
||||
}
|
||||
|
||||
public @Nullable MappedEntitySet<EntityType> getAllowedEntities() {
|
||||
return this.allowedEntities;
|
||||
}
|
||||
|
||||
public void setAllowedEntities(@Nullable MappedEntitySet<EntityType> allowedEntities) {
|
||||
this.allowedEntities = allowedEntities;
|
||||
}
|
||||
|
||||
public boolean isDispensable() {
|
||||
return this.dispensable;
|
||||
}
|
||||
|
||||
public void setDispensable(boolean dispensable) {
|
||||
this.dispensable = dispensable;
|
||||
}
|
||||
|
||||
public boolean isSwappable() {
|
||||
return this.swappable;
|
||||
}
|
||||
|
||||
public void setSwappable(boolean swappable) {
|
||||
this.swappable = swappable;
|
||||
}
|
||||
|
||||
public boolean isDamageOnHurt() {
|
||||
return this.damageOnHurt;
|
||||
}
|
||||
|
||||
public void setDamageOnHurt(boolean damageOnHurt) {
|
||||
this.damageOnHurt = damageOnHurt;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public @Nullable ResourceLocation getModel() {
|
||||
return this.assetId;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setModel(@Nullable ResourceLocation assetId) {
|
||||
this.assetId = assetId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof ItemEquippable)) return false;
|
||||
ItemEquippable that = (ItemEquippable) obj;
|
||||
if (this.dispensable != that.dispensable) return false;
|
||||
if (this.swappable != that.swappable) return false;
|
||||
if (this.damageOnHurt != that.damageOnHurt) return false;
|
||||
if (this.slot != that.slot) return false;
|
||||
if (!Objects.equals(this.equipSound, that.equipSound)) return false;
|
||||
if (!Objects.equals(this.assetId, that.assetId)) return false;
|
||||
if (!Objects.equals(this.cameraOverlay, that.cameraOverlay)) return false;
|
||||
return Objects.equals(this.allowedEntities, that.allowedEntities);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.slot, this.equipSound, this.assetId, this.cameraOverlay, this.allowedEntities, this.dispensable, this.swappable, this.damageOnHurt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ItemEquippable{slot=" + this.slot + ", equipSound=" + this.equipSound + ", model=" + this.assetId + ", cameraOverlay=" + this.cameraOverlay + ", allowedEntities=" + this.allowedEntities + ", dispensable=" + this.dispensable + ", swappable=" + this.swappable + ", damageOnHurt=" + this.damageOnHurt + '}';
|
||||
}
|
||||
}
|
||||
+30
-5
@@ -18,6 +18,7 @@
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.component.builtin.item;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.item.jukebox.IJukeboxSong;
|
||||
import com.github.retrooper.packetevents.protocol.item.jukebox.JukeboxSong;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
@@ -27,7 +28,7 @@ import java.util.Objects;
|
||||
|
||||
public class ItemJukeboxPlayable {
|
||||
|
||||
private @Nullable JukeboxSong song;
|
||||
private @Nullable IJukeboxSong song;
|
||||
private @Nullable ResourceLocation songKey;
|
||||
private boolean showInTooltip;
|
||||
|
||||
@@ -35,6 +36,14 @@ public class ItemJukeboxPlayable {
|
||||
@Nullable JukeboxSong song,
|
||||
@Nullable ResourceLocation songKey,
|
||||
boolean showInTooltip
|
||||
) {
|
||||
this((IJukeboxSong) song, songKey, showInTooltip);
|
||||
}
|
||||
|
||||
public ItemJukeboxPlayable(
|
||||
@Nullable IJukeboxSong song,
|
||||
@Nullable ResourceLocation songKey,
|
||||
boolean showInTooltip
|
||||
) {
|
||||
if ((song == null) == (songKey == null)) {
|
||||
throw new IllegalStateException("Illegal state of both song and "
|
||||
@@ -47,10 +56,10 @@ public class ItemJukeboxPlayable {
|
||||
}
|
||||
|
||||
public static ItemJukeboxPlayable read(PacketWrapper<?> wrapper) {
|
||||
JukeboxSong song;
|
||||
IJukeboxSong song;
|
||||
ResourceLocation songKey;
|
||||
if (wrapper.readBoolean()) {
|
||||
song = JukeboxSong.read(wrapper);
|
||||
song = IJukeboxSong.read(wrapper);
|
||||
songKey = null;
|
||||
} else {
|
||||
song = null;
|
||||
@@ -63,7 +72,7 @@ public class ItemJukeboxPlayable {
|
||||
public static void write(PacketWrapper<?> wrapper, ItemJukeboxPlayable jukeboxPlayable) {
|
||||
if (jukeboxPlayable.song != null) {
|
||||
wrapper.writeBoolean(true);
|
||||
JukeboxSong.write(wrapper, jukeboxPlayable.song);
|
||||
IJukeboxSong.write(wrapper, jukeboxPlayable.song);
|
||||
} else {
|
||||
assert jukeboxPlayable.songKey != null;
|
||||
wrapper.writeBoolean(false);
|
||||
@@ -72,10 +81,26 @@ public class ItemJukeboxPlayable {
|
||||
wrapper.writeBoolean(jukeboxPlayable.showInTooltip);
|
||||
}
|
||||
|
||||
public @Nullable JukeboxSong getSong() {
|
||||
public @Nullable IJukeboxSong getJukeboxSong() {
|
||||
return this.song;
|
||||
}
|
||||
|
||||
public void setJukeboxSong(@Nullable JukeboxSong song) {
|
||||
this.song = song;
|
||||
this.songKey = null;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public @Nullable JukeboxSong getSong() {
|
||||
if (this.song == null) {
|
||||
return null;
|
||||
} else if (this.song instanceof JukeboxSong) {
|
||||
return (JukeboxSong) this.song;
|
||||
}
|
||||
return (JukeboxSong) this.song.copy(null);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setSong(JukeboxSong song) {
|
||||
this.song = song;
|
||||
this.songKey = null;
|
||||
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.component.builtin.item;
|
||||
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class ItemModel {
|
||||
|
||||
private ResourceLocation modelLocation;
|
||||
|
||||
public ItemModel(ResourceLocation modelLocation) {
|
||||
this.modelLocation = modelLocation;
|
||||
}
|
||||
|
||||
public static ItemModel read(PacketWrapper<?> wrapper) {
|
||||
return new ItemModel(wrapper.readIdentifier());
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, ItemModel model) {
|
||||
wrapper.writeIdentifier(model.modelLocation);
|
||||
}
|
||||
|
||||
public ResourceLocation getModelLocation() {
|
||||
return this.modelLocation;
|
||||
}
|
||||
|
||||
public void setModelLocation(ResourceLocation modelLocation) {
|
||||
this.modelLocation = modelLocation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof ItemModel)) return false;
|
||||
ItemModel itemModel = (ItemModel) obj;
|
||||
return this.modelLocation.equals(itemModel.modelLocation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(this.modelLocation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ItemModel{modelLocation=" + this.modelLocation + '}';
|
||||
}
|
||||
}
|
||||
+29
-3
@@ -18,6 +18,7 @@
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.component.builtin.item;
|
||||
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.protocol.potion.Potion;
|
||||
import com.github.retrooper.packetevents.protocol.potion.PotionEffect;
|
||||
import com.github.retrooper.packetevents.protocol.potion.Potions;
|
||||
@@ -32,28 +33,44 @@ public class ItemPotionContents {
|
||||
private @Nullable Potion potion;
|
||||
private @Nullable Integer customColor;
|
||||
private List<PotionEffect> customEffects;
|
||||
private @Nullable String customName;
|
||||
|
||||
public ItemPotionContents(
|
||||
@Nullable Potion potion,
|
||||
@Nullable Integer customColor,
|
||||
List<PotionEffect> customEffects
|
||||
) {
|
||||
this(potion, customColor, customEffects, null);
|
||||
}
|
||||
|
||||
public ItemPotionContents(
|
||||
@Nullable Potion potion,
|
||||
@Nullable Integer customColor,
|
||||
List<PotionEffect> customEffects,
|
||||
@Nullable String customName
|
||||
) {
|
||||
this.potion = potion;
|
||||
this.customColor = customColor;
|
||||
this.customEffects = customEffects;
|
||||
this.customName = customName;
|
||||
}
|
||||
|
||||
public static ItemPotionContents read(PacketWrapper<?> wrapper) {
|
||||
Potion potionId = wrapper.readOptional(ew -> ew.readMappedEntity(Potions::getById));
|
||||
Integer customColor = wrapper.readOptional(PacketWrapper::readInt);
|
||||
List<PotionEffect> customEffects = wrapper.readList(PotionEffect::read);
|
||||
return new ItemPotionContents(potionId, customColor, customEffects);
|
||||
String customName = wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_2)
|
||||
? wrapper.readOptional(PacketWrapper::readString) : null;
|
||||
return new ItemPotionContents(potionId, customColor, customEffects, customName);
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, ItemPotionContents contents) {
|
||||
wrapper.writeOptional(contents.potion, PacketWrapper::writeMappedEntity);
|
||||
wrapper.writeOptional(contents.customColor, PacketWrapper::writeInt);
|
||||
wrapper.writeList(contents.customEffects, PotionEffect::write);
|
||||
if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_2)) {
|
||||
wrapper.writeOptional(contents.customName, PacketWrapper::writeString);
|
||||
}
|
||||
}
|
||||
|
||||
public @Nullable Potion getPotion() {
|
||||
@@ -84,6 +101,14 @@ public class ItemPotionContents {
|
||||
this.customEffects = customEffects;
|
||||
}
|
||||
|
||||
public @Nullable String getCustomName() {
|
||||
return this.customName;
|
||||
}
|
||||
|
||||
public void setCustomName(@Nullable String customName) {
|
||||
this.customName = customName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
@@ -91,11 +116,12 @@ public class ItemPotionContents {
|
||||
ItemPotionContents that = (ItemPotionContents) obj;
|
||||
if (!Objects.equals(this.potion, that.potion)) return false;
|
||||
if (!Objects.equals(this.customColor, that.customColor)) return false;
|
||||
return this.customEffects.equals(that.customEffects);
|
||||
if (!this.customEffects.equals(that.customEffects)) return false;
|
||||
return Objects.equals(this.customName, that.customName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.potion, this.customColor, this.customEffects);
|
||||
return Objects.hash(this.potion, this.customColor, this.customEffects, this.customName);
|
||||
}
|
||||
}
|
||||
+15
-3
@@ -18,9 +18,12 @@
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.component.builtin.item;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTList;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -33,12 +36,21 @@ public class ItemRecipes {
|
||||
}
|
||||
|
||||
public static ItemRecipes read(PacketWrapper<?> wrapper) {
|
||||
List<ResourceLocation> recipes = wrapper.readList(PacketWrapper::readIdentifier);
|
||||
return new ItemRecipes(recipes);
|
||||
NBTList<?> recipes = (NBTList<?>) wrapper.readNBTRaw();
|
||||
List<ResourceLocation> recipeKeys = new ArrayList<>(recipes.size());
|
||||
for (int i = 0; i < recipes.size(); i++) {
|
||||
NBTString tag = (NBTString) recipes.getTag(i);
|
||||
recipeKeys.add(new ResourceLocation(tag.getValue()));
|
||||
}
|
||||
return new ItemRecipes(recipeKeys);
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, ItemRecipes recipes) {
|
||||
wrapper.writeList(recipes.recipes, PacketWrapper::writeIdentifier);
|
||||
NBTList<NBTString> recipesTag = NBTList.createStringList();
|
||||
for (ResourceLocation recipeKey : recipes.recipes) {
|
||||
recipesTag.addTag(new NBTString(recipeKey.toString()));
|
||||
}
|
||||
wrapper.writeNBTRaw(recipesTag);
|
||||
}
|
||||
|
||||
public void addRecipe(ResourceLocation recipeKey) {
|
||||
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.component.builtin.item;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.item.type.ItemType;
|
||||
import com.github.retrooper.packetevents.protocol.item.type.ItemTypes;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.MappedEntitySet;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class ItemRepairable {
|
||||
|
||||
private MappedEntitySet<ItemType> items;
|
||||
|
||||
public ItemRepairable(MappedEntitySet<ItemType> items) {
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
public static ItemRepairable read(PacketWrapper<?> wrapper) {
|
||||
MappedEntitySet<ItemType> items = MappedEntitySet.read(wrapper, ItemTypes.getRegistry());
|
||||
return new ItemRepairable(items);
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, ItemRepairable repairable) {
|
||||
MappedEntitySet.write(wrapper, repairable.items);
|
||||
}
|
||||
|
||||
public MappedEntitySet<ItemType> getItems() {
|
||||
return this.items;
|
||||
}
|
||||
|
||||
public void setItems(MappedEntitySet<ItemType> items) {
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof ItemRepairable)) return false;
|
||||
ItemRepairable that = (ItemRepairable) obj;
|
||||
return this.items.equals(that.items);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(this.items);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ItemRepairable{items=" + this.items + '}';
|
||||
}
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.component.builtin.item;
|
||||
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class ItemTooltipStyle {
|
||||
|
||||
private ResourceLocation tooltipLoc;
|
||||
|
||||
public ItemTooltipStyle(ResourceLocation tooltipLoc) {
|
||||
this.tooltipLoc = tooltipLoc;
|
||||
}
|
||||
|
||||
public static ItemTooltipStyle read(PacketWrapper<?> wrapper) {
|
||||
return new ItemTooltipStyle(wrapper.readIdentifier());
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, ItemTooltipStyle style) {
|
||||
wrapper.writeIdentifier(style.tooltipLoc);
|
||||
}
|
||||
|
||||
public ResourceLocation getTooltipLoc() {
|
||||
return this.tooltipLoc;
|
||||
}
|
||||
|
||||
public void setTooltipLoc(ResourceLocation tooltipLoc) {
|
||||
this.tooltipLoc = tooltipLoc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof ItemTooltipStyle)) return false;
|
||||
ItemTooltipStyle that = (ItemTooltipStyle) obj;
|
||||
return this.tooltipLoc.equals(that.tooltipLoc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(this.tooltipLoc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ItemTooltipStyle{tooltipLoc=" + this.tooltipLoc + '}';
|
||||
}
|
||||
}
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.component.builtin.item;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||
import com.github.retrooper.packetevents.protocol.item.type.ItemType;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSetCooldown;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
public class ItemUseCooldown {
|
||||
|
||||
private float seconds;
|
||||
private Optional<ResourceLocation> cooldownGroup;
|
||||
|
||||
public ItemUseCooldown(float seconds, @Nullable ResourceLocation cooldownGroup) {
|
||||
this(seconds, Optional.ofNullable(cooldownGroup));
|
||||
}
|
||||
|
||||
public ItemUseCooldown(float seconds, Optional<ResourceLocation> cooldownGroup) {
|
||||
this.seconds = seconds;
|
||||
this.cooldownGroup = cooldownGroup;
|
||||
}
|
||||
|
||||
public static ItemUseCooldown read(PacketWrapper<?> wrapper) {
|
||||
float seconds = wrapper.readFloat();
|
||||
ResourceLocation cooldownGroup = wrapper.readOptional(PacketWrapper::readIdentifier);
|
||||
return new ItemUseCooldown(seconds, cooldownGroup);
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, ItemUseCooldown cooldown) {
|
||||
wrapper.writeFloat(cooldown.seconds);
|
||||
wrapper.writeOptional(cooldown.cooldownGroup.orElse(null), PacketWrapper::writeIdentifier);
|
||||
}
|
||||
|
||||
public WrapperPlayServerSetCooldown buildWrapper(ItemStack fallbackStack) {
|
||||
return this.buildWrapper(fallbackStack.getType());
|
||||
}
|
||||
|
||||
public WrapperPlayServerSetCooldown buildWrapper(ItemType fallbackItem) {
|
||||
int ticks = (int) (this.seconds * 20f);
|
||||
return this.cooldownGroup
|
||||
.map(resourceLocation -> new WrapperPlayServerSetCooldown(resourceLocation, ticks))
|
||||
.orElseGet(() -> new WrapperPlayServerSetCooldown(fallbackItem, ticks));
|
||||
}
|
||||
|
||||
public float getSeconds() {
|
||||
return this.seconds;
|
||||
}
|
||||
|
||||
public void setSeconds(float seconds) {
|
||||
this.seconds = seconds;
|
||||
}
|
||||
|
||||
public Optional<ResourceLocation> getCooldownGroup() {
|
||||
return this.cooldownGroup;
|
||||
}
|
||||
|
||||
public void setCooldownGroup(Optional<ResourceLocation> cooldownGroup) {
|
||||
this.cooldownGroup = cooldownGroup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof ItemUseCooldown)) return false;
|
||||
ItemUseCooldown that = (ItemUseCooldown) obj;
|
||||
if (Float.compare(that.seconds, this.seconds) != 0) return false;
|
||||
return this.cooldownGroup.equals(that.cooldownGroup);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.seconds, this.cooldownGroup);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ItemUseCooldown{seconds=" + this.seconds + ", cooldownGroup=" + this.cooldownGroup + '}';
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.component.builtin.item;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class ItemUseRemainder {
|
||||
|
||||
private ItemStack target;
|
||||
|
||||
public ItemUseRemainder(ItemStack target) {
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public static ItemUseRemainder read(PacketWrapper<?> wrapper) {
|
||||
ItemStack target = wrapper.readItemStack();
|
||||
return new ItemUseRemainder(target);
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, ItemUseRemainder remainder) {
|
||||
wrapper.writeItemStack(remainder.target);
|
||||
}
|
||||
|
||||
public ItemStack getTarget() {
|
||||
return this.target;
|
||||
}
|
||||
|
||||
public void setTarget(ItemStack target) {
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof ItemUseRemainder)) return false;
|
||||
ItemUseRemainder that = (ItemUseRemainder) obj;
|
||||
return this.target.equals(that.target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(this.target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ItemUseRemainder{target=" + this.target + '}';
|
||||
}
|
||||
}
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.entity;
|
||||
// Created by booky10 in packetevents (02:12 21.10.2024)
|
||||
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityPositionSync;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public final class EntityPositionData {
|
||||
|
||||
private Vector3d position;
|
||||
private Vector3d deltaMovement;
|
||||
private float yaw;
|
||||
private float pitch;
|
||||
|
||||
public EntityPositionData(Vector3d position, Vector3d deltaMovement, float yaw, float pitch) {
|
||||
this.position = position;
|
||||
this.deltaMovement = deltaMovement;
|
||||
this.yaw = yaw;
|
||||
this.pitch = pitch;
|
||||
}
|
||||
|
||||
public static EntityPositionData read(PacketWrapper<?> wrapper) {
|
||||
Vector3d position = Vector3d.read(wrapper);
|
||||
Vector3d deltaMovement = Vector3d.read(wrapper);
|
||||
float yaw = wrapper.readFloat();
|
||||
float pitch = wrapper.readFloat();
|
||||
return new EntityPositionData(position, deltaMovement, yaw, pitch);
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, EntityPositionData positionData) {
|
||||
Vector3d.write(wrapper, positionData.position);
|
||||
Vector3d.write(wrapper, positionData.deltaMovement);
|
||||
wrapper.writeFloat(positionData.yaw);
|
||||
wrapper.writeFloat(positionData.pitch);
|
||||
}
|
||||
|
||||
public Vector3d getPosition() {
|
||||
return this.position;
|
||||
}
|
||||
|
||||
public void setPosition(Vector3d position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
public Vector3d getDeltaMovement() {
|
||||
return this.deltaMovement;
|
||||
}
|
||||
|
||||
public void setDeltaMovement(Vector3d deltaMovement) {
|
||||
this.deltaMovement = deltaMovement;
|
||||
}
|
||||
|
||||
public float getYaw() {
|
||||
return this.yaw;
|
||||
}
|
||||
|
||||
public void setYaw(float yaw) {
|
||||
this.yaw = yaw;
|
||||
}
|
||||
|
||||
public float getPitch() {
|
||||
return this.pitch;
|
||||
}
|
||||
|
||||
public void setPitch(float pitch) {
|
||||
this.pitch = pitch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof EntityPositionData)) return false;
|
||||
EntityPositionData that = (EntityPositionData) obj;
|
||||
if (Float.compare(that.yaw, this.yaw) != 0) return false;
|
||||
if (Float.compare(that.pitch, this.pitch) != 0) return false;
|
||||
if (!this.position.equals(that.position)) return false;
|
||||
return this.deltaMovement.equals(that.deltaMovement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.position, this.deltaMovement, this.yaw, this.pitch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "EntityPositionData{position=" + this.position + ", deltaMovement=" + this.deltaMovement + ", yaw=" + this.yaw + ", pitch=" + this.pitch + '}';
|
||||
}
|
||||
}
|
||||
+41
-1
@@ -22,9 +22,14 @@ import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilder;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class EntityTypes {
|
||||
private static final Map<String, EntityType> ENTITY_TYPE_MAP = new HashMap<>();
|
||||
@@ -151,7 +156,13 @@ public class EntityTypes {
|
||||
public static final EntityType BAT = define("bat", ABSTRACT_AMBIENT);
|
||||
public static final EntityType BEE = define("bee", ABSTRACT_INSENTIENT);
|
||||
public static final EntityType BLAZE = define("blaze", ABSTRACT_MONSTER);
|
||||
/**
|
||||
* <strong>WARNING:</strong> Does not exist itself anymore since 1.21.2
|
||||
*/
|
||||
public static final EntityType BOAT = define("boat", ENTITY);
|
||||
/**
|
||||
* <strong>WARNING:</strong> Does not exist itself anymore since 1.21.2
|
||||
*/
|
||||
public static final EntityType CHEST_BOAT = define("chest_boat", BOAT);
|
||||
public static final EntityType CAT = define("cat", ABSTRACT_TAMEABLE_ANIMAL);
|
||||
public static final EntityType CAMEL = define("camel", ABSTRACT_HORSE);
|
||||
@@ -295,8 +306,37 @@ public class EntityTypes {
|
||||
public static final EntityType BREEZE_WIND_CHARGE = define("breeze_wind_charge", ABSTRACT_WIND_CHARGE);
|
||||
public static final EntityType OMINOUS_ITEM_SPAWNER = define("ominous_item_spawner", ENTITY);
|
||||
|
||||
// added with 1.21.2
|
||||
public static final EntityType ACACIA_BOAT = define("acacia_boat", BOAT);
|
||||
public static final EntityType ACACIA_CHEST_BOAT = define("acacia_chest_boat", CHEST_BOAT);
|
||||
public static final EntityType BAMBOO_CHEST_RAFT = define("bamboo_chest_raft", CHEST_BOAT);
|
||||
public static final EntityType BAMBOO_RAFT = define("bamboo_raft", BOAT);
|
||||
public static final EntityType BIRCH_BOAT = define("birch_boat", BOAT);
|
||||
public static final EntityType BIRCH_CHEST_BOAT = define("birch_chest_boat", CHEST_BOAT);
|
||||
public static final EntityType CHERRY_BOAT = define("cherry_boat", BOAT);
|
||||
public static final EntityType CHERRY_CHEST_BOAT = define("cherry_chest_boat", CHEST_BOAT);
|
||||
public static final EntityType CREAKING = define("creaking", ABSTRACT_MONSTER);
|
||||
/**
|
||||
* Removed with 1.21.4
|
||||
*/
|
||||
@ApiStatus.Obsolete
|
||||
public static final EntityType CREAKING_TRANSIENT = define("creaking_transient", CREAKING);
|
||||
public static final EntityType DARK_OAK_BOAT = define("dark_oak_boat", BOAT);
|
||||
public static final EntityType DARK_OAK_CHEST_BOAT = define("dark_oak_chest_boat", CHEST_BOAT);
|
||||
public static final EntityType JUNGLE_BOAT = define("jungle_boat", BOAT);
|
||||
public static final EntityType JUNGLE_CHEST_BOAT = define("jungle_chest_boat", CHEST_BOAT);
|
||||
public static final EntityType MANGROVE_BOAT = define("mangrove_boat", BOAT);
|
||||
public static final EntityType MANGROVE_CHEST_BOAT = define("mangrove_chest_boat", CHEST_BOAT);
|
||||
public static final EntityType OAK_BOAT = define("oak_boat", BOAT);
|
||||
public static final EntityType OAK_CHEST_BOAT = define("oak_chest_boat", CHEST_BOAT);
|
||||
public static final EntityType PALE_OAK_BOAT = define("pale_oak_boat", BOAT);
|
||||
public static final EntityType PALE_OAK_CHEST_BOAT = define("pale_oak_chest_boat", CHEST_BOAT);
|
||||
public static final EntityType SPRUCE_BOAT = define("spruce_boat", BOAT);
|
||||
public static final EntityType SPRUCE_CHEST_BOAT = define("spruce_chest_boat", CHEST_BOAT);
|
||||
|
||||
/**
|
||||
* Returns an immutable view of the entity types.
|
||||
*
|
||||
* @return Entity Types
|
||||
*/
|
||||
public static Collection<EntityType> values() {
|
||||
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.entity.wolfvariant;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.mapper.AbstractMappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.MappedEntitySet;
|
||||
import com.github.retrooper.packetevents.protocol.world.biome.Biome;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class StaticWolfVariant extends AbstractMappedEntity implements WolfVariant {
|
||||
|
||||
private final ResourceLocation wildTexture;
|
||||
private final ResourceLocation tameTexture;
|
||||
private final ResourceLocation angryTexture;
|
||||
private final MappedEntitySet<Biome> biomes;
|
||||
|
||||
public StaticWolfVariant(
|
||||
ResourceLocation wildTexture,
|
||||
ResourceLocation tameTexture,
|
||||
ResourceLocation angryTexture,
|
||||
MappedEntitySet<Biome> biomes
|
||||
) {
|
||||
this(null, wildTexture, tameTexture, angryTexture, biomes);
|
||||
}
|
||||
|
||||
public StaticWolfVariant(
|
||||
@Nullable TypesBuilderData data,
|
||||
ResourceLocation wildTexture,
|
||||
ResourceLocation tameTexture,
|
||||
ResourceLocation angryTexture,
|
||||
MappedEntitySet<Biome> biomes
|
||||
) {
|
||||
super(data);
|
||||
this.wildTexture = wildTexture;
|
||||
this.tameTexture = tameTexture;
|
||||
this.angryTexture = angryTexture;
|
||||
this.biomes = biomes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WolfVariant copy(@Nullable TypesBuilderData newData) {
|
||||
return new StaticWolfVariant(newData, this.wildTexture, this.tameTexture, this.angryTexture, this.biomes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getWildTexture() {
|
||||
return this.wildTexture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getTameTexture() {
|
||||
return this.tameTexture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getAngryTexture() {
|
||||
return this.angryTexture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappedEntitySet<Biome> getBiomes() {
|
||||
return this.biomes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deepEquals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof StaticWolfVariant)) return false;
|
||||
if (!super.equals(obj)) return false;
|
||||
StaticWolfVariant that = (StaticWolfVariant) obj;
|
||||
if (!this.wildTexture.equals(that.wildTexture)) return false;
|
||||
if (!this.tameTexture.equals(that.tameTexture)) return false;
|
||||
if (!this.angryTexture.equals(that.angryTexture)) return false;
|
||||
return this.biomes.equals(that.biomes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deepHashCode() {
|
||||
return Objects.hash(super.hashCode(), this.wildTexture, this.tameTexture, this.angryTexture, this.biomes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "StaticWolfVariant{wildTexture=" + this.wildTexture + ", tameTexture=" + this.tameTexture + ", angryTexture=" + this.angryTexture + ", biomes=" + this.biomes + '}';
|
||||
}
|
||||
}
|
||||
+54
-5
@@ -1,14 +1,63 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.entity.wolfvariant;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.mapper.CopyableEntity;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.DeepComparableEntity;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.MappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.MappedEntitySet;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.world.biome.Biome;
|
||||
import com.github.retrooper.packetevents.protocol.world.biome.Biomes;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Set;
|
||||
public interface WolfVariant extends MappedEntity, CopyableEntity<WolfVariant>, DeepComparableEntity {
|
||||
|
||||
//TODO Finish Wolf-Variant class
|
||||
public class WolfVariant {
|
||||
private ResourceLocation wildId, tameId, angryId;
|
||||
ResourceLocation getWildTexture();
|
||||
|
||||
public WolfVariant(ResourceLocation wildId, ResourceLocation tameId, ResourceLocation angryId) {
|
||||
ResourceLocation getTameTexture();
|
||||
|
||||
ResourceLocation getAngryTexture();
|
||||
|
||||
MappedEntitySet<Biome> getBiomes();
|
||||
|
||||
static WolfVariant decode(NBT nbt, ClientVersion version, @Nullable TypesBuilderData data) {
|
||||
NBTCompound compound = (NBTCompound) nbt;
|
||||
ResourceLocation wildTexture = new ResourceLocation(compound.getStringTagValueOrThrow("wild_texture"));
|
||||
ResourceLocation tameTexture = new ResourceLocation(compound.getStringTagValueOrThrow("tame_texture"));
|
||||
ResourceLocation angryTexture = new ResourceLocation(compound.getStringTagValueOrThrow("angry_texture"));
|
||||
MappedEntitySet<Biome> biomes = MappedEntitySet.decode(
|
||||
compound.getTagOrThrow("biomes"), version, Biomes.getRegistry());
|
||||
return new StaticWolfVariant(data, wildTexture, tameTexture, angryTexture, biomes);
|
||||
}
|
||||
|
||||
static NBT encode(WolfVariant variant, ClientVersion version) {
|
||||
NBTCompound compound = new NBTCompound();
|
||||
compound.setTag("wild_texture", new NBTString(variant.getWildTexture().toString()));
|
||||
compound.setTag("tame_texture", new NBTString(variant.getTameTexture().toString()));
|
||||
compound.setTag("angry_texture", new NBTString(variant.getAngryTexture().toString()));
|
||||
compound.setTag("biomes", MappedEntitySet.encode(variant.getBiomes(), version));
|
||||
return compound;
|
||||
}
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.entity.wolfvariant;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.mapper.MappedEntitySet;
|
||||
import com.github.retrooper.packetevents.protocol.world.biome.Biome;
|
||||
import com.github.retrooper.packetevents.protocol.world.biome.Biomes;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.util.mappings.VersionedRegistry;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public final class WolfVariants {
|
||||
|
||||
private static final VersionedRegistry<WolfVariant> REGISTRY = new VersionedRegistry<>(
|
||||
"wolf_variant", "entity/wolf_variant_mappings");
|
||||
|
||||
private WolfVariants() {
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static WolfVariant define(String key, MappedEntitySet<Biome> biomes) {
|
||||
return define(key, "wolf_" + key, biomes);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static WolfVariant define(String key, String assetId, MappedEntitySet<Biome> biomes) {
|
||||
return define(key, ResourceLocation.minecraft("entity/wolf/" + assetId),
|
||||
ResourceLocation.minecraft("entity/wolf/" + assetId + "_tame"),
|
||||
ResourceLocation.minecraft("entity/wolf/" + assetId + "_angry"), biomes);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static WolfVariant define(
|
||||
String key,
|
||||
ResourceLocation wildTexture,
|
||||
ResourceLocation tameTexture,
|
||||
ResourceLocation angryTexture,
|
||||
MappedEntitySet<Biome> biomes
|
||||
) {
|
||||
return REGISTRY.define(key, data -> new StaticWolfVariant(
|
||||
data, wildTexture, tameTexture, angryTexture, biomes));
|
||||
}
|
||||
|
||||
public static VersionedRegistry<WolfVariant> getRegistry() {
|
||||
return REGISTRY;
|
||||
}
|
||||
|
||||
public static final WolfVariant PALE = define("pale", "wolf",
|
||||
new MappedEntitySet<>(Arrays.asList(Biomes.TAIGA)));
|
||||
public static final WolfVariant SPOTTED = define("spotted",
|
||||
new MappedEntitySet<>(ResourceLocation.minecraft("is_savanna")));
|
||||
public static final WolfVariant SNOWY = define("snowy",
|
||||
new MappedEntitySet<>(Arrays.asList(Biomes.GROVE)));
|
||||
public static final WolfVariant BLACK = define("black",
|
||||
new MappedEntitySet<>(Arrays.asList(Biomes.OLD_GROWTH_PINE_TAIGA)));
|
||||
public static final WolfVariant ASHEN = define("ashen",
|
||||
new MappedEntitySet<>(Arrays.asList(Biomes.SNOWY_TAIGA)));
|
||||
public static final WolfVariant RUSTY = define("rusty",
|
||||
new MappedEntitySet<>(ResourceLocation.minecraft("is_jungle")));
|
||||
public static final WolfVariant WOODS = define("woods",
|
||||
new MappedEntitySet<>(Arrays.asList(Biomes.FOREST)));
|
||||
public static final WolfVariant CHESTNUT = define("chestnut",
|
||||
new MappedEntitySet<>(Arrays.asList(Biomes.OLD_GROWTH_SPRUCE_TAIGA)));
|
||||
public static final WolfVariant STRIPED = define("striped",
|
||||
new MappedEntitySet<>(ResourceLocation.minecraft("is_badlands")));
|
||||
|
||||
static {
|
||||
REGISTRY.unloadMappings();
|
||||
}
|
||||
}
|
||||
@@ -32,10 +32,12 @@ import com.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTInt;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTList;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTNumber;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTShort;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTType;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -82,6 +84,54 @@ public class ItemStack {
|
||||
updateCachedEmptyStatus();
|
||||
}
|
||||
|
||||
public static ItemStack decode(NBT nbt, ClientVersion version) {
|
||||
if (nbt instanceof NBTString) {
|
||||
ResourceLocation itemName = new ResourceLocation(((NBTString) nbt).getValue());
|
||||
return ItemStack.builder().type(ItemTypes.getByName(itemName.toString())).build();
|
||||
}
|
||||
NBTCompound compound = (NBTCompound) nbt;
|
||||
ItemStack.Builder builder = ItemStack.builder();
|
||||
|
||||
ResourceLocation itemName = Optional.ofNullable(compound.getStringTagValueOrNull("id")).map(Optional::of)
|
||||
.orElseGet(() -> Optional.ofNullable(compound.getStringTagValueOrNull("item")))
|
||||
.map(ResourceLocation::new).orElseThrow(() -> new IllegalArgumentException(
|
||||
"No item type specified: " + compound.getTags().keySet()));
|
||||
builder.type(ItemTypes.getByName(itemName.toString()));
|
||||
builder.nbt(compound.getCompoundTagOrNull("tag"));
|
||||
|
||||
Optional.ofNullable(compound.getNumberTagOrNull("Count")).map(Optional::of)
|
||||
.orElseGet(() -> Optional.ofNullable(compound.getNumberTagOrNull("count")))
|
||||
.map(NBTNumber::getAsInt).ifPresent(builder::amount);
|
||||
|
||||
// TODO components
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public static NBT encodeForParticle(ItemStack itemStack, ClientVersion version) {
|
||||
if (version.isNewerThanOrEquals(ClientVersion.V_1_20_5)) {
|
||||
boolean simple = itemStack.isEmpty()
|
||||
|| itemStack.components == null
|
||||
|| itemStack.components.getPatches().isEmpty();
|
||||
if (simple) {
|
||||
return new NBTString(itemStack.type.getName().toString());
|
||||
}
|
||||
}
|
||||
|
||||
NBTCompound compound = new NBTCompound();
|
||||
compound.setTag("id", new NBTString(itemStack.type.getName().toString()));
|
||||
if (version.isOlderThan(ClientVersion.V_1_20_5)) {
|
||||
compound.setTag("Count", new NBTInt(itemStack.amount));
|
||||
if (itemStack.nbt != null) {
|
||||
compound.setTag("tag", itemStack.nbt);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO components
|
||||
|
||||
return compound;
|
||||
}
|
||||
|
||||
public int getMaxStackSize() {
|
||||
return this.getComponentOr(MAX_STACK_SIZE,
|
||||
// fallback to legacy specified max stack size
|
||||
@@ -462,7 +512,7 @@ public class ItemStack {
|
||||
int maxAmount = getType().getMaxAmount();
|
||||
return "ItemStack[type=" + identifier + ", amount=" + amount + "/" + maxAmount
|
||||
+ ", nbt tag names: " + (nbt != null ? nbt.getTagNames() : "[null]")
|
||||
+ ", legacyData=" + legacyData + ", components=" + components + "]";
|
||||
+ ", legacyData=" + legacyData + ", components=" + (components != null ? components.getPatches() : null) + "]";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+124
-42
@@ -19,54 +19,47 @@
|
||||
package com.github.retrooper.packetevents.protocol.item.armormaterial;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.util.mappings.MappingHelper;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilder;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import com.github.retrooper.packetevents.util.mappings.VersionedRegistry;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ArmorMaterials {
|
||||
/**
|
||||
* This is named "equipment asset" in vanilla since 1.21.4,
|
||||
* before this was also called "armor material" in vanilla.
|
||||
*/
|
||||
public final class ArmorMaterials {
|
||||
|
||||
private static final Map<String, ArmorMaterial> MATERIAL_MAP = new HashMap<>();
|
||||
private static final Map<Byte, Map<Integer, ArmorMaterial>> MATERIAL_ID_MAP = new HashMap<>();
|
||||
private static final TypesBuilder TYPES_BUILDER = new TypesBuilder("item/item_armor_material_mappings");
|
||||
// this isn't great, but it works
|
||||
private static final Map<String, String> DFU = new HashMap<>();
|
||||
|
||||
public static ArmorMaterial define(String key) {
|
||||
TypesBuilderData data = TYPES_BUILDER.define(key);
|
||||
ArmorMaterial instrument = new ArmorMaterial() {
|
||||
@Override
|
||||
public ResourceLocation getName() {
|
||||
return data.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId(ClientVersion version) {
|
||||
return MappingHelper.getId(version, TYPES_BUILDER, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof ArmorMaterial) {
|
||||
return getName().equals(((ArmorMaterial) obj).getName());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
MappingHelper.registerMapping(TYPES_BUILDER, MATERIAL_MAP, MATERIAL_ID_MAP, instrument);
|
||||
return instrument;
|
||||
static {
|
||||
DFU.put("turtle", "minecraft:turtle_scute");
|
||||
DFU.put("minecraft:turtle", "minecraft:turtle_scute");
|
||||
DFU.put("armadillo", "minecraft:armadillo_scute");
|
||||
DFU.put("minecraft:armadillo", "minecraft:armadillo_scute");
|
||||
}
|
||||
|
||||
private static final VersionedRegistry<ArmorMaterial> REGISTRY = new VersionedRegistry<>(
|
||||
"equipment_asset", "item/equipment_asset_mappings");
|
||||
|
||||
private ArmorMaterials() {
|
||||
}
|
||||
|
||||
private static ArmorMaterial define(String name) {
|
||||
return REGISTRY.define(name, StaticArmorMaterial::new);
|
||||
}
|
||||
|
||||
public static VersionedRegistry<ArmorMaterial> getRegistry() {
|
||||
return REGISTRY;
|
||||
}
|
||||
|
||||
// with key
|
||||
public static ArmorMaterial getByName(String name) {
|
||||
return MATERIAL_MAP.get(name);
|
||||
return REGISTRY.getByName(DFU.getOrDefault(name, name));
|
||||
}
|
||||
|
||||
public static ArmorMaterial getById(ClientVersion version, int id) {
|
||||
int index = TYPES_BUILDER.getDataIndex(version);
|
||||
Map<Integer, ArmorMaterial> idMap = MATERIAL_ID_MAP.get((byte) index);
|
||||
return idMap.get(id);
|
||||
return REGISTRY.getById(version, id);
|
||||
}
|
||||
|
||||
public static final ArmorMaterial LEATHER = define("leather");
|
||||
@@ -75,16 +68,105 @@ public class ArmorMaterials {
|
||||
public static final ArmorMaterial GOLD = define("gold");
|
||||
public static final ArmorMaterial DIAMOND = define("diamond");
|
||||
|
||||
// Added with 1.13
|
||||
public static final ArmorMaterial TURTLE = define("turtle");
|
||||
/**
|
||||
* Renamed from {@link #TURTLE} in 1.21.4
|
||||
*/
|
||||
public static final ArmorMaterial TURTLE_SCUTE = define("turtle_scute");
|
||||
/**
|
||||
* Added with 1.13, renamed to {@link #TURTLE_SCUTE} in 1.21.4
|
||||
*/
|
||||
@Deprecated
|
||||
public static final ArmorMaterial TURTLE = TURTLE_SCUTE;
|
||||
|
||||
// Added with 1.16
|
||||
/**
|
||||
* Added with 1.16
|
||||
*/
|
||||
public static final ArmorMaterial NETHERITE = define("netherite");
|
||||
|
||||
// Added with 1.20.5
|
||||
public static final ArmorMaterial ARMADILLO = define("armadillo");
|
||||
/**
|
||||
* Renamed from {@link #ARMADILLO} in 1.21.4
|
||||
*/
|
||||
public static final ArmorMaterial ARMADILLO_SCUTE = define("armadillo_scute");
|
||||
/**
|
||||
* Added with 1.20.5, renamed to {@link #ARMADILLO_SCUTE} in 1.21.4
|
||||
*/
|
||||
@Deprecated
|
||||
public static final ArmorMaterial ARMADILLO = ARMADILLO_SCUTE;
|
||||
|
||||
/**
|
||||
* Added with 1.21.4
|
||||
*/
|
||||
public static final ArmorMaterial ELYTRA = define("elytra");
|
||||
/**
|
||||
* Added with 1.21.4
|
||||
*/
|
||||
public static final ArmorMaterial WHITE_CARPET = define("white_carpet");
|
||||
/**
|
||||
* Added with 1.21.4
|
||||
*/
|
||||
public static final ArmorMaterial ORANGE_CARPET = define("orange_carpet");
|
||||
/**
|
||||
* Added with 1.21.4
|
||||
*/
|
||||
public static final ArmorMaterial MAGENTA_CARPET = define("magenta_carpet");
|
||||
/**
|
||||
* Added with 1.21.4
|
||||
*/
|
||||
public static final ArmorMaterial LIGHT_BLUE_CARPET = define("light_blue_carpet");
|
||||
/**
|
||||
* Added with 1.21.4
|
||||
*/
|
||||
public static final ArmorMaterial YELLOW_CARPET = define("yellow_carpet");
|
||||
/**
|
||||
* Added with 1.21.4
|
||||
*/
|
||||
public static final ArmorMaterial LIME_CARPET = define("lime_carpet");
|
||||
/**
|
||||
* Added with 1.21.4
|
||||
*/
|
||||
public static final ArmorMaterial PINK_CARPET = define("pink_carpet");
|
||||
/**
|
||||
* Added with 1.21.4
|
||||
*/
|
||||
public static final ArmorMaterial GRAY_CARPET = define("gray_carpet");
|
||||
/**
|
||||
* Added with 1.21.4
|
||||
*/
|
||||
public static final ArmorMaterial LIGHT_GRAY_CARPET = define("light_gray_carpet");
|
||||
/**
|
||||
* Added with 1.21.4
|
||||
*/
|
||||
public static final ArmorMaterial CYAN_CARPET = define("cyan_carpet");
|
||||
/**
|
||||
* Added with 1.21.4
|
||||
*/
|
||||
public static final ArmorMaterial PURPLE_CARPET = define("purple_carpet");
|
||||
/**
|
||||
* Added with 1.21.4
|
||||
*/
|
||||
public static final ArmorMaterial BLUE_CARPET = define("blue_carpet");
|
||||
/**
|
||||
* Added with 1.21.4
|
||||
*/
|
||||
public static final ArmorMaterial BROWN_CARPET = define("brown_carpet");
|
||||
/**
|
||||
* Added with 1.21.4
|
||||
*/
|
||||
public static final ArmorMaterial GREEN_CARPET = define("green_carpet");
|
||||
/**
|
||||
* Added with 1.21.4
|
||||
*/
|
||||
public static final ArmorMaterial RED_CARPET = define("red_carpet");
|
||||
/**
|
||||
* Added with 1.21.4
|
||||
*/
|
||||
public static final ArmorMaterial BLACK_CARPET = define("black_carpet");
|
||||
/**
|
||||
* Added with 1.21.4
|
||||
*/
|
||||
public static final ArmorMaterial TRADER_LLAMA = define("trader_llama");
|
||||
|
||||
static {
|
||||
TYPES_BUILDER.unloadFileMappings();
|
||||
REGISTRY.unloadMappings();
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.item.armormaterial;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.mapper.AbstractMappedEntity;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class StaticArmorMaterial extends AbstractMappedEntity implements ArmorMaterial {
|
||||
|
||||
public StaticArmorMaterial(@Nullable TypesBuilderData data) {
|
||||
super(data);
|
||||
}
|
||||
}
|
||||
+23
-1
@@ -18,11 +18,19 @@
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.item.banner;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.mapper.CopyableEntity;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.DeepComparableEntity;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.MappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface BannerPattern extends MappedEntity {
|
||||
public interface BannerPattern extends MappedEntity, CopyableEntity<BannerPattern>, DeepComparableEntity {
|
||||
|
||||
ResourceLocation getAssetId();
|
||||
|
||||
@@ -38,4 +46,18 @@ public interface BannerPattern extends MappedEntity {
|
||||
wrapper.writeIdentifier(pattern.getAssetId());
|
||||
wrapper.writeString(pattern.getTranslationKey());
|
||||
}
|
||||
|
||||
static BannerPattern decode(NBT nbt, ClientVersion version, @Nullable TypesBuilderData data) {
|
||||
NBTCompound compound = (NBTCompound) nbt;
|
||||
ResourceLocation assetId = new ResourceLocation(compound.getStringTagValueOrThrow("asset_id"));
|
||||
String translationKey = compound.getStringTagValueOrThrow("translation_key");
|
||||
return new StaticBannerPattern(data, assetId, translationKey);
|
||||
}
|
||||
|
||||
static NBT encode(BannerPattern bannerPattern, ClientVersion version) {
|
||||
NBTCompound compound = new NBTCompound();
|
||||
compound.setTag("asset_id", new NBTString(bannerPattern.getAssetId().toString()));
|
||||
compound.setTag("translation_key", new NBTString(bannerPattern.getTranslationKey()));
|
||||
return compound;
|
||||
}
|
||||
}
|
||||
+21
-49
@@ -20,71 +20,42 @@ package com.github.retrooper.packetevents.protocol.item.banner;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.util.mappings.MappingHelper;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilder;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import com.github.retrooper.packetevents.util.mappings.VersionedRegistry;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class BannerPatterns {
|
||||
public final class BannerPatterns {
|
||||
|
||||
private static final Map<String, BannerPattern> PATTERN_TYPE_MAP = new HashMap<>();
|
||||
private static final Map<Byte, Map<Integer, BannerPattern>> PATTERN_TYPE_ID_MAP = new HashMap<>();
|
||||
private static final TypesBuilder TYPES_BUILDER = new TypesBuilder("item/item_banner_pattern_mappings");
|
||||
private static final VersionedRegistry<BannerPattern> REGISTRY = new VersionedRegistry<>(
|
||||
"banner_pattern", "item/item_banner_pattern_mappings");
|
||||
|
||||
private BannerPatterns() {
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static BannerPattern define(String key) {
|
||||
ResourceLocation assetId = ResourceLocation.minecraft(key);
|
||||
String translationKey = "block.minecraft.banner." + key;
|
||||
return define(key, assetId, translationKey);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static BannerPattern define(String key, ResourceLocation assetId, String translationKey) {
|
||||
TypesBuilderData data = TYPES_BUILDER.define(key);
|
||||
BannerPattern pattern = new BannerPattern() {
|
||||
@Override
|
||||
public ResourceLocation getAssetId() {
|
||||
return assetId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTranslationKey() {
|
||||
return translationKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getName() {
|
||||
return data.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId(ClientVersion version) {
|
||||
return MappingHelper.getId(version, TYPES_BUILDER, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof BannerPattern) {
|
||||
return getName().equals(((BannerPattern) obj).getName());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
MappingHelper.registerMapping(TYPES_BUILDER, PATTERN_TYPE_MAP, PATTERN_TYPE_ID_MAP, pattern);
|
||||
return pattern;
|
||||
return REGISTRY.define(key, data ->
|
||||
new StaticBannerPattern(data, assetId, translationKey));
|
||||
}
|
||||
|
||||
public static VersionedRegistry<BannerPattern> getRegistry() {
|
||||
return REGISTRY;
|
||||
}
|
||||
|
||||
// with key
|
||||
public static BannerPattern getByName(String name) {
|
||||
return PATTERN_TYPE_MAP.get(name);
|
||||
return REGISTRY.getByName(name);
|
||||
}
|
||||
|
||||
public static BannerPattern getById(ClientVersion version, int id) {
|
||||
int index = TYPES_BUILDER.getDataIndex(version);
|
||||
Map<Integer, BannerPattern> idMap = PATTERN_TYPE_ID_MAP.get((byte) index);
|
||||
return idMap.get(id);
|
||||
return REGISTRY.getById(version, id);
|
||||
}
|
||||
|
||||
public static final BannerPattern SQUARE_BOTTOM_LEFT = define("square_bottom_left");
|
||||
@@ -135,13 +106,14 @@ public class BannerPatterns {
|
||||
|
||||
/**
|
||||
* Returns an immutable view of the banner patterns.
|
||||
*
|
||||
* @return Banner Patterns
|
||||
*/
|
||||
public static Collection<BannerPattern> values() {
|
||||
return Collections.unmodifiableCollection(PATTERN_TYPE_MAP.values());
|
||||
return REGISTRY.getEntries();
|
||||
}
|
||||
|
||||
static {
|
||||
TYPES_BUILDER.unloadFileMappings();
|
||||
REGISTRY.unloadMappings();
|
||||
}
|
||||
}
|
||||
+23
-20
@@ -18,21 +18,33 @@
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.item.banner;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.AbstractMappedEntity;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class StaticBannerPattern implements BannerPattern {
|
||||
public class StaticBannerPattern extends AbstractMappedEntity implements BannerPattern {
|
||||
|
||||
private final ResourceLocation assetId;
|
||||
private final String translationKey;
|
||||
|
||||
public StaticBannerPattern(ResourceLocation assetId, String translationKey) {
|
||||
this(null, assetId, translationKey);
|
||||
}
|
||||
|
||||
public StaticBannerPattern(@Nullable TypesBuilderData data, ResourceLocation assetId, String translationKey) {
|
||||
super(data);
|
||||
this.assetId = assetId;
|
||||
this.translationKey = translationKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BannerPattern copy(@Nullable TypesBuilderData newData) {
|
||||
return new StaticBannerPattern(newData, this.assetId, this.translationKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getAssetId() {
|
||||
return this.assetId;
|
||||
@@ -44,31 +56,22 @@ public class StaticBannerPattern implements BannerPattern {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getName() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId(ClientVersion version) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRegistered() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
public boolean deepEquals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof StaticBannerPattern)) return false;
|
||||
if (!super.equals(obj)) return false;
|
||||
StaticBannerPattern that = (StaticBannerPattern) obj;
|
||||
if (!this.assetId.equals(that.assetId)) return false;
|
||||
return this.translationKey.equals(that.translationKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.assetId, this.translationKey);
|
||||
public int deepHashCode() {
|
||||
return Objects.hash(super.hashCode(), this.assetId, this.translationKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "StaticBannerPattern{assetId=" + this.assetId + ", translationKey='" + this.translationKey + '\'' + '}';
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.item.consumables;
|
||||
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
|
||||
public abstract class ConsumeEffect<T extends ConsumeEffect<?>> {
|
||||
|
||||
protected final ConsumeEffectType<T> type;
|
||||
|
||||
protected ConsumeEffect(ConsumeEffectType<T> type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public static ConsumeEffect<?> readFull(PacketWrapper<?> wrapper) {
|
||||
ConsumeEffectType<?> type = wrapper.readMappedEntity(ConsumeEffectTypes.getRegistry());
|
||||
return type.read(wrapper);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked") // I hate generics
|
||||
public static <T extends ConsumeEffect<?>> void writeFull(PacketWrapper<?> wrapper, ConsumeEffect<T> effect) {
|
||||
wrapper.writeMappedEntity(effect.getType());
|
||||
((ConsumeEffectType<ConsumeEffect<?>>) effect.getType()).write(wrapper, effect);
|
||||
}
|
||||
|
||||
public ConsumeEffectType<T> getType() {
|
||||
return this.type;
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.item.consumables;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.mapper.MappedEntity;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
|
||||
public interface ConsumeEffectType<T extends ConsumeEffect<?>> extends MappedEntity {
|
||||
|
||||
T read(PacketWrapper<?> wrapper);
|
||||
|
||||
void write(PacketWrapper<?> wrapper, T effect);
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.item.consumables;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.item.consumables.builtin.ApplyEffectsConsumeEffect;
|
||||
import com.github.retrooper.packetevents.protocol.item.consumables.builtin.ClearAllEffectsConsumeEffect;
|
||||
import com.github.retrooper.packetevents.protocol.item.consumables.builtin.PlaySoundConsumeEffect;
|
||||
import com.github.retrooper.packetevents.protocol.item.consumables.builtin.RemoveEffectsConsumeEffect;
|
||||
import com.github.retrooper.packetevents.protocol.item.consumables.builtin.TeleportRandomlyConsumeEffect;
|
||||
import com.github.retrooper.packetevents.util.mappings.VersionedRegistry;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper.Reader;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper.Writer;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
public final class ConsumeEffectTypes {
|
||||
|
||||
private static final VersionedRegistry<ConsumeEffectType<?>> REGISTRY = new VersionedRegistry<>(
|
||||
"consume_effect_type", "item/consume_effect_type_mappings");
|
||||
|
||||
private ConsumeEffectTypes() {
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static <T extends ConsumeEffect<?>> ConsumeEffectType<T> define(
|
||||
String name, Reader<T> reader, Writer<T> writer) {
|
||||
return REGISTRY.define(name, data ->
|
||||
new StaticConsumeEffectType<>(data, reader, writer));
|
||||
}
|
||||
|
||||
public static final ConsumeEffectType<ApplyEffectsConsumeEffect> APPLY_EFFECTS = define(
|
||||
"apply_effects", ApplyEffectsConsumeEffect::read, ApplyEffectsConsumeEffect::write);
|
||||
public static final ConsumeEffectType<RemoveEffectsConsumeEffect> REMOVE_EFFECTS = define(
|
||||
"remove_effects", RemoveEffectsConsumeEffect::read, RemoveEffectsConsumeEffect::write);
|
||||
public static final ConsumeEffectType<ClearAllEffectsConsumeEffect> CLEAR_ALL_EFFECTS = define(
|
||||
"clear_all_effects", ClearAllEffectsConsumeEffect::read, ClearAllEffectsConsumeEffect::write);
|
||||
public static final ConsumeEffectType<TeleportRandomlyConsumeEffect> TELEPORT_RANDOMLY = define(
|
||||
"teleport_randomly", TeleportRandomlyConsumeEffect::read, TeleportRandomlyConsumeEffect::write);
|
||||
public static final ConsumeEffectType<PlaySoundConsumeEffect> PLAY_SOUND = define(
|
||||
"play_sound", PlaySoundConsumeEffect::read, PlaySoundConsumeEffect::write);
|
||||
|
||||
public static VersionedRegistry<ConsumeEffectType<?>> getRegistry() {
|
||||
return REGISTRY;
|
||||
}
|
||||
|
||||
static {
|
||||
REGISTRY.unloadMappings();
|
||||
}
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.item.consumables;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.mapper.AbstractMappedEntity;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper.Reader;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper.Writer;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class StaticConsumeEffectType<T extends ConsumeEffect<?>> extends AbstractMappedEntity implements ConsumeEffectType<T> {
|
||||
|
||||
private final Reader<T> reader;
|
||||
private final Writer<T> writer;
|
||||
|
||||
public StaticConsumeEffectType(
|
||||
@Nullable TypesBuilderData data,
|
||||
Reader<T> reader,
|
||||
Writer<T> writer
|
||||
) {
|
||||
super(data);
|
||||
this.reader = reader;
|
||||
this.writer = writer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T read(PacketWrapper<?> wrapper) {
|
||||
return this.reader.apply(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(PacketWrapper<?> wrapper, T effect) {
|
||||
this.writer.accept(wrapper, effect);
|
||||
}
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.item.consumables.builtin;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.item.consumables.ConsumeEffect;
|
||||
import com.github.retrooper.packetevents.protocol.item.consumables.ConsumeEffectTypes;
|
||||
import com.github.retrooper.packetevents.protocol.potion.PotionEffect;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ApplyEffectsConsumeEffect extends ConsumeEffect<ApplyEffectsConsumeEffect> {
|
||||
|
||||
private final List<PotionEffect> effects;
|
||||
private final float probability;
|
||||
|
||||
public ApplyEffectsConsumeEffect(List<PotionEffect> effects, float probability) {
|
||||
super(ConsumeEffectTypes.APPLY_EFFECTS);
|
||||
this.effects = effects;
|
||||
this.probability = probability;
|
||||
}
|
||||
|
||||
public static ApplyEffectsConsumeEffect read(PacketWrapper<?> wrapper) {
|
||||
List<PotionEffect> effects = wrapper.readList(PotionEffect::read);
|
||||
float probability = wrapper.readFloat();
|
||||
return new ApplyEffectsConsumeEffect(effects, probability);
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, ApplyEffectsConsumeEffect effect) {
|
||||
wrapper.writeList(effect.effects, PotionEffect::write);
|
||||
wrapper.writeFloat(effect.probability);
|
||||
}
|
||||
|
||||
public List<PotionEffect> getEffects() {
|
||||
return this.effects;
|
||||
}
|
||||
|
||||
public float getProbability() {
|
||||
return this.probability;
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.item.consumables.builtin;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.item.consumables.ConsumeEffect;
|
||||
import com.github.retrooper.packetevents.protocol.item.consumables.ConsumeEffectType;
|
||||
import com.github.retrooper.packetevents.protocol.item.consumables.ConsumeEffectTypes;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
|
||||
public class ClearAllEffectsConsumeEffect extends ConsumeEffect<ClearAllEffectsConsumeEffect> {
|
||||
|
||||
public static final ClearAllEffectsConsumeEffect INSTANCE = new ClearAllEffectsConsumeEffect();
|
||||
|
||||
private ClearAllEffectsConsumeEffect() {
|
||||
super(ConsumeEffectTypes.CLEAR_ALL_EFFECTS);
|
||||
}
|
||||
|
||||
public static ClearAllEffectsConsumeEffect read(PacketWrapper<?> ignoredWrapper) {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> ignoredWrapper, ClearAllEffectsConsumeEffect ignoredEffect) {
|
||||
// NO-OP
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.item.consumables.builtin;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.item.consumables.ConsumeEffect;
|
||||
import com.github.retrooper.packetevents.protocol.item.consumables.ConsumeEffectTypes;
|
||||
import com.github.retrooper.packetevents.protocol.sound.Sound;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
|
||||
public class PlaySoundConsumeEffect extends ConsumeEffect<PlaySoundConsumeEffect> {
|
||||
|
||||
private final Sound sound;
|
||||
|
||||
public PlaySoundConsumeEffect(Sound sound) {
|
||||
super(ConsumeEffectTypes.PLAY_SOUND);
|
||||
this.sound = sound;
|
||||
}
|
||||
|
||||
public static PlaySoundConsumeEffect read(PacketWrapper<?> wrapper) {
|
||||
Sound sound = Sound.read(wrapper);
|
||||
return new PlaySoundConsumeEffect(sound);
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, PlaySoundConsumeEffect effect) {
|
||||
Sound.write(wrapper, effect.sound);
|
||||
}
|
||||
|
||||
public Sound getSound() {
|
||||
return this.sound;
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.item.consumables.builtin;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.item.consumables.ConsumeEffect;
|
||||
import com.github.retrooper.packetevents.protocol.item.consumables.ConsumeEffectTypes;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.MappedEntitySet;
|
||||
import com.github.retrooper.packetevents.protocol.potion.PotionType;
|
||||
import com.github.retrooper.packetevents.protocol.potion.PotionTypes;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
|
||||
public class RemoveEffectsConsumeEffect extends ConsumeEffect<RemoveEffectsConsumeEffect> {
|
||||
|
||||
private final MappedEntitySet<PotionType> effects;
|
||||
|
||||
public RemoveEffectsConsumeEffect(MappedEntitySet<PotionType> effects) {
|
||||
super(ConsumeEffectTypes.REMOVE_EFFECTS);
|
||||
this.effects = effects;
|
||||
}
|
||||
|
||||
public static RemoveEffectsConsumeEffect read(PacketWrapper<?> wrapper) {
|
||||
MappedEntitySet<PotionType> effects = MappedEntitySet.read(wrapper, PotionTypes::getById);
|
||||
return new RemoveEffectsConsumeEffect(effects);
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, RemoveEffectsConsumeEffect effect) {
|
||||
MappedEntitySet.write(wrapper, effect.effects);
|
||||
}
|
||||
|
||||
public MappedEntitySet<PotionType> getEffects() {
|
||||
return this.effects;
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.item.consumables.builtin;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.item.consumables.ConsumeEffect;
|
||||
import com.github.retrooper.packetevents.protocol.item.consumables.ConsumeEffectTypes;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
|
||||
public class TeleportRandomlyConsumeEffect extends ConsumeEffect<TeleportRandomlyConsumeEffect> {
|
||||
|
||||
private final float diameter;
|
||||
|
||||
public TeleportRandomlyConsumeEffect(float diameter) {
|
||||
super(ConsumeEffectTypes.TELEPORT_RANDOMLY);
|
||||
this.diameter = diameter;
|
||||
}
|
||||
|
||||
public static TeleportRandomlyConsumeEffect read(PacketWrapper<?> wrapper) {
|
||||
float diameter = wrapper.readFloat();
|
||||
return new TeleportRandomlyConsumeEffect(diameter);
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, TeleportRandomlyConsumeEffect effect) {
|
||||
wrapper.writeFloat(effect.diameter);
|
||||
}
|
||||
|
||||
public float getDiameter() {
|
||||
return this.diameter;
|
||||
}
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.item.enchantment;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTInt;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public final class EnchantmentCost {
|
||||
|
||||
private final int base;
|
||||
private final int perLevelAboveFirst;
|
||||
|
||||
public EnchantmentCost(int base, int perLevelAboveFirst) {
|
||||
this.base = base;
|
||||
this.perLevelAboveFirst = perLevelAboveFirst;
|
||||
}
|
||||
|
||||
public static EnchantmentCost decode(NBT nbt, ClientVersion version) {
|
||||
NBTCompound compound = (NBTCompound) nbt;
|
||||
int base = compound.getNumberTagOrThrow("base").getAsInt();
|
||||
int perLevelAboveFirst = compound.getNumberTagOrThrow("per_level_above_first").getAsInt();
|
||||
return new EnchantmentCost(base, perLevelAboveFirst);
|
||||
}
|
||||
|
||||
public static NBT encode(EnchantmentCost cost, ClientVersion version) {
|
||||
NBTCompound compound = new NBTCompound();
|
||||
compound.setTag("base", new NBTInt(cost.base));
|
||||
compound.setTag("per_level_above_first", new NBTInt(cost.perLevelAboveFirst));
|
||||
return compound;
|
||||
}
|
||||
|
||||
public int getBase() {
|
||||
return this.base;
|
||||
}
|
||||
|
||||
public int getPerLevelAboveFirst() {
|
||||
return this.perLevelAboveFirst;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof EnchantmentCost)) return false;
|
||||
EnchantmentCost that = (EnchantmentCost) obj;
|
||||
if (this.base != that.base) return false;
|
||||
return this.perLevelAboveFirst == that.perLevelAboveFirst;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.base, this.perLevelAboveFirst);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "EnchantmentCost{base=" + this.base + ", perLevelAboveFirst=" + this.perLevelAboveFirst + '}';
|
||||
}
|
||||
}
|
||||
+175
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.item.enchantment;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemAttributeModifiers.EquipmentSlotGroup;
|
||||
import com.github.retrooper.packetevents.protocol.item.type.ItemType;
|
||||
import com.github.retrooper.packetevents.protocol.item.type.ItemTypes;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.MappedEntitySet;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTInt;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTList;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import static com.github.retrooper.packetevents.util.adventure.AdventureIndexUtil.indexValueOrThrow;
|
||||
|
||||
public final class EnchantmentDefinition {
|
||||
|
||||
private final MappedEntitySet<ItemType> supportedItems;
|
||||
private final Optional<MappedEntitySet<ItemType>> primaryItems;
|
||||
private final int weight;
|
||||
private final int maxLevel;
|
||||
private final EnchantmentCost minCost;
|
||||
private final EnchantmentCost maxCost;
|
||||
private final int anvilCost;
|
||||
private final List<EquipmentSlotGroup> slots;
|
||||
|
||||
public EnchantmentDefinition(
|
||||
MappedEntitySet<ItemType> supportedItems,
|
||||
Optional<MappedEntitySet<ItemType>> primaryItems,
|
||||
int weight, int maxLevel,
|
||||
EnchantmentCost minCost, EnchantmentCost maxCost,
|
||||
int anvilCost, List<EquipmentSlotGroup> slots
|
||||
) {
|
||||
this.supportedItems = supportedItems;
|
||||
this.primaryItems = primaryItems;
|
||||
this.weight = weight;
|
||||
this.maxLevel = maxLevel;
|
||||
this.minCost = minCost;
|
||||
this.maxCost = maxCost;
|
||||
this.anvilCost = anvilCost;
|
||||
this.slots = slots;
|
||||
}
|
||||
|
||||
public static EnchantmentDefinition decode(NBT nbt, ClientVersion version) {
|
||||
NBTCompound compound = (NBTCompound) nbt;
|
||||
MappedEntitySet<ItemType> supportedItems = MappedEntitySet.decode(
|
||||
compound.getTagOrThrow("supported_items"), version, ItemTypes.getRegistry());
|
||||
Optional<MappedEntitySet<ItemType>> primaryItems = Optional.ofNullable(compound.getTagOrNull("primary_items"))
|
||||
.map(items -> MappedEntitySet.decode(items, version, ItemTypes.getRegistry()));
|
||||
int weight = compound.getNumberTagOrThrow("weight").getAsInt();
|
||||
int maxLevel = compound.getNumberTagOrThrow("max_level").getAsInt();
|
||||
EnchantmentCost minCost = EnchantmentCost.decode(compound.getTagOrThrow("min_cost"), version);
|
||||
EnchantmentCost maxCost = EnchantmentCost.decode(compound.getTagOrThrow("max_cost"), version);
|
||||
int anvilCost = compound.getNumberTagOrThrow("anvil_cost").getAsInt();
|
||||
|
||||
NBT slotsTag = compound.getTagOrThrow("slots");
|
||||
List<EquipmentSlotGroup> slots;
|
||||
if (slotsTag instanceof NBTList<?>) {
|
||||
NBTList<?> slotsTagList = (NBTList<?>) slotsTag;
|
||||
slots = new ArrayList<>(slotsTagList.size());
|
||||
for (NBT tag : slotsTagList.getTags()) {
|
||||
String slotGroupId = ((NBTString) tag).getValue();
|
||||
slots.add(indexValueOrThrow(EquipmentSlotGroup.ID_INDEX, slotGroupId));
|
||||
}
|
||||
} else {
|
||||
String slotGroupId = ((NBTString) slotsTag).getValue();
|
||||
EquipmentSlotGroup slotGroup = indexValueOrThrow(EquipmentSlotGroup.ID_INDEX, slotGroupId);
|
||||
slots = Collections.singletonList(slotGroup);
|
||||
}
|
||||
|
||||
return new EnchantmentDefinition(supportedItems, primaryItems, weight,
|
||||
maxLevel, minCost, maxCost, anvilCost, slots);
|
||||
}
|
||||
|
||||
public static NBT encode(EnchantmentDefinition definition, ClientVersion version) {
|
||||
NBTList<NBTString> slotsTag = NBTList.createStringList();
|
||||
for (EquipmentSlotGroup slot : definition.slots) {
|
||||
slotsTag.addTag(new NBTString(slot.getId()));
|
||||
}
|
||||
|
||||
NBTCompound compound = new NBTCompound();
|
||||
compound.setTag("supported_items", MappedEntitySet.encode(
|
||||
definition.supportedItems, version));
|
||||
definition.primaryItems.ifPresent(set -> compound.setTag(
|
||||
"primary_items", MappedEntitySet.encode(set, version)));
|
||||
compound.setTag("weight", new NBTInt(definition.weight));
|
||||
compound.setTag("max_level", new NBTInt(definition.maxLevel));
|
||||
compound.setTag("min_cost", EnchantmentCost.encode(definition.minCost, version));
|
||||
compound.setTag("max_cost", EnchantmentCost.encode(definition.maxCost, version));
|
||||
compound.setTag("anvil_cost", new NBTInt(definition.anvilCost));
|
||||
compound.setTag("slots", slotsTag);
|
||||
return compound;
|
||||
}
|
||||
|
||||
public MappedEntitySet<ItemType> getSupportedItems() {
|
||||
return this.supportedItems;
|
||||
}
|
||||
|
||||
public Optional<MappedEntitySet<ItemType>> getPrimaryItems() {
|
||||
return this.primaryItems;
|
||||
}
|
||||
|
||||
public int getWeight() {
|
||||
return this.weight;
|
||||
}
|
||||
|
||||
public int getMaxLevel() {
|
||||
return this.maxLevel;
|
||||
}
|
||||
|
||||
public EnchantmentCost getMinCost() {
|
||||
return this.minCost;
|
||||
}
|
||||
|
||||
public EnchantmentCost getMaxCost() {
|
||||
return this.maxCost;
|
||||
}
|
||||
|
||||
public int getAnvilCost() {
|
||||
return this.anvilCost;
|
||||
}
|
||||
|
||||
public List<EquipmentSlotGroup> getSlots() {
|
||||
return this.slots;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof EnchantmentDefinition)) return false;
|
||||
EnchantmentDefinition that = (EnchantmentDefinition) obj;
|
||||
if (this.weight != that.weight) return false;
|
||||
if (this.maxLevel != that.maxLevel) return false;
|
||||
if (this.anvilCost != that.anvilCost) return false;
|
||||
if (!this.supportedItems.equals(that.supportedItems)) return false;
|
||||
if (!this.primaryItems.equals(that.primaryItems)) return false;
|
||||
if (!this.minCost.equals(that.minCost)) return false;
|
||||
if (!this.maxCost.equals(that.maxCost)) return false;
|
||||
return this.slots.equals(that.slots);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.supportedItems, this.primaryItems, this.weight, this.maxLevel, this.minCost, this.maxCost, this.anvilCost, this.slots);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "EnchantmentDefinition{supportedItems=" + this.supportedItems + ", primaryItems=" + this.primaryItems + ", weight=" + this.weight + ", maxLevel=" + this.maxLevel + ", minCost=" + this.minCost + ", maxCost=" + this.maxCost + ", anvilCost=" + this.anvilCost + ", slots=" + this.slots + '}';
|
||||
}
|
||||
}
|
||||
+51
-1
@@ -18,7 +18,57 @@
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.item.enchantment.type;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.component.EnchantEffectComponentTypes;
|
||||
import com.github.retrooper.packetevents.protocol.component.IComponentMap;
|
||||
import com.github.retrooper.packetevents.protocol.component.StaticComponentMap;
|
||||
import com.github.retrooper.packetevents.protocol.item.enchantment.EnchantmentDefinition;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.CopyableEntity;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.DeepComparableEntity;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.MappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.MappedEntitySet;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.util.adventure.AdventureSerializer;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface EnchantmentType extends MappedEntity {
|
||||
import java.util.Optional;
|
||||
|
||||
public interface EnchantmentType extends MappedEntity, CopyableEntity<EnchantmentType>, DeepComparableEntity {
|
||||
|
||||
Component getDescription();
|
||||
|
||||
EnchantmentDefinition getDefinition();
|
||||
|
||||
MappedEntitySet<EnchantmentType> getExclusiveSet();
|
||||
|
||||
StaticComponentMap getEffects();
|
||||
|
||||
static EnchantmentType decode(NBT nbt, ClientVersion version, @Nullable TypesBuilderData data) {
|
||||
NBTCompound compound = (NBTCompound) nbt;
|
||||
Component description = AdventureSerializer.fromNbt(compound.getTagOrThrow("description"));
|
||||
EnchantmentDefinition definition = EnchantmentDefinition.decode(compound, version);
|
||||
MappedEntitySet<EnchantmentType> exclusiveSet = Optional.ofNullable(compound.getTagOrNull("exclusive_set"))
|
||||
.map(tag -> MappedEntitySet.decode(tag, version, EnchantmentTypes.getRegistry()))
|
||||
.orElseGet(MappedEntitySet::createEmpty);
|
||||
StaticComponentMap effects = Optional.ofNullable(compound.getTagOrNull("effects"))
|
||||
.map(tag -> IComponentMap.decode(tag, version,
|
||||
EnchantEffectComponentTypes.getRegistry()))
|
||||
.orElse(StaticComponentMap.EMPTY);
|
||||
return new StaticEnchantmentType(data, description, definition, exclusiveSet, effects);
|
||||
}
|
||||
|
||||
static NBT encode(EnchantmentType type, ClientVersion version) {
|
||||
NBTCompound compound = (NBTCompound) EnchantmentDefinition.encode(type.getDefinition(), version);
|
||||
compound.setTag("description", AdventureSerializer.toNbt(type.getDescription()));
|
||||
if (!type.getExclusiveSet().isEmpty()) {
|
||||
compound.setTag("exclusive_set", MappedEntitySet.encode(type.getExclusiveSet(), version));
|
||||
}
|
||||
if (!type.getEffects().isEmpty()) {
|
||||
compound.setTag("effects", IComponentMap.encode(type.getEffects(), version));
|
||||
}
|
||||
return compound;
|
||||
}
|
||||
}
|
||||
+45
-37
@@ -18,17 +18,21 @@
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.item.enchantment.type;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.serializer.SequentialNBTReader;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.util.mappings.MappingHelper;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilder;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import com.github.retrooper.packetevents.util.mappings.VersionedRegistry;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class EnchantmentTypes {
|
||||
public final class EnchantmentTypes {
|
||||
|
||||
private static final Map<String, String> STRING_UPDATER = new HashMap<>();
|
||||
|
||||
@@ -37,47 +41,50 @@ public class EnchantmentTypes {
|
||||
STRING_UPDATER.put("minecraft:sweeping", "minecraft:sweeping_edge");
|
||||
}
|
||||
|
||||
private static final Map<String, EnchantmentType> ENCHANTMENT_TYPE_MAPPINGS = new HashMap<>();
|
||||
private static final Map<Byte, Map<Integer, EnchantmentType>> ENCHANTMENT_TYPE_ID_MAPPINGS = new HashMap<>();
|
||||
private static final TypesBuilder TYPES_BUILDER = new TypesBuilder("enchantment/enchantment_type_mappings");
|
||||
// load data from file, enchantment types are too complex to define in code here
|
||||
private static final Map<ResourceLocation, NBTCompound> ENCHANTMENT_DATA;
|
||||
|
||||
public static EnchantmentType define(String key) {
|
||||
TypesBuilderData data = TYPES_BUILDER.define(key);
|
||||
EnchantmentType enchantmentType = new EnchantmentType() {
|
||||
@Override
|
||||
public ResourceLocation getName() {
|
||||
return data.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId(ClientVersion version) {
|
||||
return MappingHelper.getId(version, TYPES_BUILDER, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof EnchantmentType) {
|
||||
return getName() == ((EnchantmentType) obj).getName();
|
||||
static {
|
||||
ENCHANTMENT_DATA = new HashMap<>();
|
||||
try (SequentialNBTReader.Compound dataTag = MappingHelper.decompress("mappings/enchantment/enchantment_type_data")) {
|
||||
while (dataTag.hasNext()) {
|
||||
Map.Entry<String, NBT> entry = dataTag.next();
|
||||
if (entry.getKey().equals("version")) {
|
||||
continue; // skip version field
|
||||
}
|
||||
return false;
|
||||
ResourceLocation enchantKey = new ResourceLocation(entry.getKey());
|
||||
ENCHANTMENT_DATA.put(enchantKey, ((SequentialNBTReader.Compound) entry.getValue()).readFully());
|
||||
}
|
||||
};
|
||||
|
||||
MappingHelper.registerMapping(TYPES_BUILDER, ENCHANTMENT_TYPE_MAPPINGS, ENCHANTMENT_TYPE_ID_MAPPINGS, enchantmentType);
|
||||
return enchantmentType;
|
||||
} catch (IOException exception) {
|
||||
throw new RuntimeException("Error while reading enchantment type data", exception);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static EnchantmentType getByName(String name) {
|
||||
private static final VersionedRegistry<EnchantmentType> REGISTRY = new VersionedRegistry<>(
|
||||
"enchantment", "enchantment/enchantment_type_mappings");
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static EnchantmentType define(String key) {
|
||||
return REGISTRY.define(key, data -> {
|
||||
NBTCompound dataTag = ENCHANTMENT_DATA.get(data.getName());
|
||||
if (dataTag == null) {
|
||||
throw new IllegalArgumentException("Can't define enchantment " + data.getName() + ", no data found");
|
||||
}
|
||||
return EnchantmentType.decode(dataTag, ClientVersion.getLatest(), data);
|
||||
});
|
||||
}
|
||||
|
||||
public static VersionedRegistry<EnchantmentType> getRegistry() {
|
||||
return REGISTRY;
|
||||
}
|
||||
|
||||
public static @Nullable EnchantmentType getByName(String name) {
|
||||
String fixedName = STRING_UPDATER.getOrDefault(name, name);
|
||||
return ENCHANTMENT_TYPE_MAPPINGS.get(fixedName);
|
||||
return REGISTRY.getByName(fixedName);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static EnchantmentType getById(ClientVersion version, int id) {
|
||||
int index = TYPES_BUILDER.getDataIndex(version);
|
||||
Map<Integer, EnchantmentType> typeIdMap = ENCHANTMENT_TYPE_ID_MAPPINGS.get((byte) index);
|
||||
return typeIdMap.get(id);
|
||||
public static @Nullable EnchantmentType getById(ClientVersion version, int id) {
|
||||
return REGISTRY.getById(version, id);
|
||||
}
|
||||
|
||||
public static final EnchantmentType ALL_DAMAGE_PROTECTION = define("protection");
|
||||
@@ -126,6 +133,7 @@ public class EnchantmentTypes {
|
||||
public static final EnchantmentType WIND_BURST = define("wind_burst");
|
||||
|
||||
static {
|
||||
TYPES_BUILDER.unloadFileMappings();
|
||||
ENCHANTMENT_DATA.clear();
|
||||
REGISTRY.unloadMappings();
|
||||
}
|
||||
}
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.item.enchantment.type;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.component.StaticComponentMap;
|
||||
import com.github.retrooper.packetevents.protocol.item.enchantment.EnchantmentDefinition;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.AbstractMappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.MappedEntitySet;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class StaticEnchantmentType extends AbstractMappedEntity implements EnchantmentType {
|
||||
|
||||
private final Component description;
|
||||
private final EnchantmentDefinition definition;
|
||||
private final MappedEntitySet<EnchantmentType> exclusiveSet;
|
||||
private final StaticComponentMap effects;
|
||||
|
||||
public StaticEnchantmentType(
|
||||
Component description,
|
||||
EnchantmentDefinition definition,
|
||||
MappedEntitySet<EnchantmentType> exclusiveSet,
|
||||
StaticComponentMap effects
|
||||
) {
|
||||
this(null, description, definition, exclusiveSet, effects);
|
||||
}
|
||||
|
||||
public StaticEnchantmentType(
|
||||
@Nullable TypesBuilderData data,
|
||||
Component description,
|
||||
EnchantmentDefinition definition,
|
||||
MappedEntitySet<EnchantmentType> exclusiveSet,
|
||||
StaticComponentMap effects
|
||||
) {
|
||||
super(data);
|
||||
this.description = description;
|
||||
this.definition = definition;
|
||||
this.exclusiveSet = exclusiveSet;
|
||||
this.effects = effects;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnchantmentType copy(@Nullable TypesBuilderData newData) {
|
||||
return new StaticEnchantmentType(newData, this.description,
|
||||
this.definition, this.exclusiveSet, this.effects);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getDescription() {
|
||||
return this.description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnchantmentDefinition getDefinition() {
|
||||
return this.definition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappedEntitySet<EnchantmentType> getExclusiveSet() {
|
||||
return this.exclusiveSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StaticComponentMap getEffects() {
|
||||
return this.effects;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deepEquals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof StaticEnchantmentType)) return false;
|
||||
if (!super.equals(obj)) return false;
|
||||
StaticEnchantmentType that = (StaticEnchantmentType) obj;
|
||||
if (!this.description.equals(that.description)) return false;
|
||||
if (!this.definition.equals(that.definition)) return false;
|
||||
if (!this.exclusiveSet.equals(that.exclusiveSet)) return false;
|
||||
return this.effects.equals(that.effects);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deepHashCode() {
|
||||
return Objects.hash(super.hashCode(), this.description, this.definition, this.exclusiveSet, this.effects);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "StaticEnchantmentType{description=" + this.description + ", definition=" + this.definition + ", exclusiveSet=" + this.exclusiveSet + ", effects=" + this.effects + "}";
|
||||
}
|
||||
}
|
||||
+55
-6
@@ -18,27 +18,51 @@
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.item.instrument;
|
||||
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.CopyableEntity;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.DeepComparableEntity;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.MappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTFloat;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.sound.Sound;
|
||||
import com.github.retrooper.packetevents.util.MathUtil;
|
||||
import com.github.retrooper.packetevents.util.adventure.AdventureSerializer;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface Instrument extends MappedEntity {
|
||||
public interface Instrument extends MappedEntity, CopyableEntity<Instrument>, DeepComparableEntity {
|
||||
|
||||
Sound getSound();
|
||||
|
||||
int getUseDuration();
|
||||
float getUseSeconds();
|
||||
|
||||
/**
|
||||
* Use duration measured in ticks
|
||||
*/
|
||||
default int getUseDuration() {
|
||||
return MathUtil.floor(this.getUseSeconds() * 20);
|
||||
}
|
||||
|
||||
float getRange();
|
||||
|
||||
Component getDescription();
|
||||
|
||||
static Instrument read(PacketWrapper<?> wrapper) {
|
||||
return wrapper.readMappedEntityOrDirect(Instruments::getById, Instrument::readDirect);
|
||||
return wrapper.readMappedEntityOrDirect(Instruments.getRegistry(), Instrument::readDirect);
|
||||
}
|
||||
|
||||
static Instrument readDirect(PacketWrapper<?> wrapper) {
|
||||
Sound sound = Sound.read(wrapper);
|
||||
int useDuration = wrapper.readVarInt();
|
||||
float useSeconds = wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_2)
|
||||
? wrapper.readFloat() : wrapper.readVarInt() * 20f;
|
||||
float range = wrapper.readFloat();
|
||||
return new StaticInstrument(sound, useDuration, range);
|
||||
Component description = wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_2)
|
||||
? wrapper.readComponent() : Component.empty();
|
||||
return new StaticInstrument(sound, useSeconds, range, description);
|
||||
}
|
||||
|
||||
static void write(PacketWrapper<?> wrapper, Instrument instrument) {
|
||||
@@ -47,7 +71,32 @@ public interface Instrument extends MappedEntity {
|
||||
|
||||
static void writeDirect(PacketWrapper<?> wrapper, Instrument instrument) {
|
||||
Sound.write(wrapper, instrument.getSound());
|
||||
wrapper.writeVarInt(instrument.getUseDuration());
|
||||
if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_2)) {
|
||||
wrapper.writeFloat(instrument.getUseSeconds());
|
||||
} else {
|
||||
wrapper.writeVarInt(instrument.getUseDuration());
|
||||
}
|
||||
wrapper.writeFloat(instrument.getRange());
|
||||
if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_2)) {
|
||||
wrapper.writeComponent(instrument.getDescription());
|
||||
}
|
||||
}
|
||||
|
||||
static Instrument decode(NBT nbt, ClientVersion version, @Nullable TypesBuilderData data) {
|
||||
NBTCompound compound = (NBTCompound) nbt;
|
||||
Sound sound = Sound.decode(compound.getTagOrThrow("sound_event"), version);
|
||||
float useSeconds = compound.getNumberTagOrThrow("use_duration").getAsFloat();
|
||||
float range = compound.getNumberTagOrThrow("range").getAsFloat();
|
||||
Component description = AdventureSerializer.fromNbt(compound.getTagOrThrow("description"));
|
||||
return new StaticInstrument(data, sound, useSeconds, range, description);
|
||||
}
|
||||
|
||||
static NBT encode(Instrument instrument, ClientVersion version) {
|
||||
NBTCompound compound = new NBTCompound();
|
||||
compound.setTag("sound_event", Sound.encode(instrument.getSound(), version));
|
||||
compound.setTag("use_duration", new NBTFloat(instrument.getUseSeconds()));
|
||||
compound.setTag("range", new NBTFloat(instrument.getRange()));
|
||||
compound.setTag("description", AdventureSerializer.toNbt(instrument.getDescription()));
|
||||
return compound;
|
||||
}
|
||||
}
|
||||
+20
-54
@@ -21,74 +21,40 @@ package com.github.retrooper.packetevents.protocol.item.instrument;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.sound.Sound;
|
||||
import com.github.retrooper.packetevents.protocol.sound.Sounds;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.util.mappings.MappingHelper;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilder;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import com.github.retrooper.packetevents.util.mappings.VersionedRegistry;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
public final class Instruments {
|
||||
|
||||
public class Instruments {
|
||||
private static final VersionedRegistry<Instrument> REGISTRY = new VersionedRegistry<>(
|
||||
"instrument", "item/item_instrument_mappings");
|
||||
|
||||
private static final Map<String, Instrument> INSTRUMENT_MAP = new HashMap<>();
|
||||
private static final Map<Byte, Map<Integer, Instrument>> INSTRUMENT_ID_MAP = new HashMap<>();
|
||||
private static final TypesBuilder TYPES_BUILDER = new TypesBuilder("item/item_instrument_mappings");
|
||||
private Instruments() {
|
||||
}
|
||||
|
||||
public static Instrument define(String key, Sound sound) {
|
||||
// vanilla defaults for goat horns
|
||||
return define(key, sound, 140, 256f);
|
||||
return define(key, sound, 20 * 7, 256f);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static Instrument define(String key, Sound sound, int useDuration, float range) {
|
||||
TypesBuilderData data = TYPES_BUILDER.define(key);
|
||||
Instrument instrument = new Instrument() {
|
||||
@Override
|
||||
public Sound getSound() {
|
||||
return sound;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUseDuration() {
|
||||
return useDuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getRange() {
|
||||
return range;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getName() {
|
||||
return data.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId(ClientVersion version) {
|
||||
return MappingHelper.getId(version, TYPES_BUILDER, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof Instrument) {
|
||||
return getName().equals(((Instrument) obj).getName());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
MappingHelper.registerMapping(TYPES_BUILDER, INSTRUMENT_MAP, INSTRUMENT_ID_MAP, instrument);
|
||||
return instrument;
|
||||
return REGISTRY.define(key, data -> new StaticInstrument(
|
||||
data, sound, useDuration, range,
|
||||
Component.translatable("instrument.minecraft." + key)));
|
||||
}
|
||||
|
||||
public static VersionedRegistry<Instrument> getRegistry() {
|
||||
return REGISTRY;
|
||||
}
|
||||
|
||||
// with key
|
||||
public static Instrument getByName(String name) {
|
||||
return INSTRUMENT_MAP.get(name);
|
||||
return REGISTRY.getByName(name);
|
||||
}
|
||||
|
||||
public static Instrument getById(ClientVersion version, int id) {
|
||||
int index = TYPES_BUILDER.getDataIndex(version);
|
||||
Map<Integer, Instrument> idMap = INSTRUMENT_ID_MAP.get((byte) index);
|
||||
return idMap.get(id);
|
||||
return REGISTRY.getById(version, id);
|
||||
}
|
||||
|
||||
public static final Instrument PONDER_GOAT_HORN = define("ponder_goat_horn", Sounds.ITEM_GOAT_HORN_SOUND_0);
|
||||
@@ -101,6 +67,6 @@ public class Instruments {
|
||||
public static final Instrument DREAM_GOAT_HORN = define("dream_goat_horn", Sounds.ITEM_GOAT_HORN_SOUND_7);
|
||||
|
||||
static {
|
||||
TYPES_BUILDER.unloadFileMappings();
|
||||
REGISTRY.unloadMappings();
|
||||
}
|
||||
}
|
||||
+35
-24
@@ -18,22 +18,41 @@
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.item.instrument;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.AbstractMappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.sound.Sound;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class StaticInstrument implements Instrument {
|
||||
public class StaticInstrument extends AbstractMappedEntity implements Instrument {
|
||||
|
||||
private final Sound sound;
|
||||
private final int useDuration;
|
||||
private final float useSeconds;
|
||||
private final float range;
|
||||
private final Component description;
|
||||
|
||||
@Deprecated // useDuration changed from ticks to seconds in 1.21.2
|
||||
public StaticInstrument(Sound sound, int useDuration, float range) {
|
||||
this(sound, useDuration * 20f, range, Component.empty());
|
||||
}
|
||||
|
||||
public StaticInstrument(Sound sound, float useSeconds, float range, Component description) {
|
||||
this(null, sound, useSeconds, range, description);
|
||||
}
|
||||
|
||||
public StaticInstrument(@Nullable TypesBuilderData data, Sound sound, float useSeconds, float range, Component description) {
|
||||
super(data);
|
||||
this.sound = sound;
|
||||
this.useDuration = useDuration;
|
||||
this.useSeconds = useSeconds;
|
||||
this.range = range;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instrument copy(@Nullable TypesBuilderData newData) {
|
||||
return new StaticInstrument(newData, this.sound, this.useSeconds, this.range, this.description);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -42,8 +61,8 @@ public class StaticInstrument implements Instrument {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUseDuration() {
|
||||
return this.useDuration;
|
||||
public float getUseSeconds() {
|
||||
return this.useSeconds;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -52,32 +71,24 @@ public class StaticInstrument implements Instrument {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getName() {
|
||||
throw new UnsupportedOperationException();
|
||||
public Component getDescription() {
|
||||
return this.description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId(ClientVersion version) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRegistered() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
public boolean deepEquals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof StaticInstrument)) return false;
|
||||
if (!super.equals(obj)) return false;
|
||||
StaticInstrument that = (StaticInstrument) obj;
|
||||
if (this.useDuration != that.useDuration) return false;
|
||||
if (this.useSeconds != that.useSeconds) return false;
|
||||
if (Float.compare(that.range, this.range) != 0) return false;
|
||||
return this.sound.equals(that.sound);
|
||||
if (!this.sound.equals(that.sound)) return false;
|
||||
return this.description.equals(that.description);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.sound, this.useDuration, this.range);
|
||||
public int deepHashCode() {
|
||||
return Objects.hash(super.hashCode(), this.sound, this.useSeconds, this.range, this.description);
|
||||
}
|
||||
}
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.item.jukebox;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.mapper.CopyableEntity;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.DeepComparableEntity;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.MappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTFloat;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTInt;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.sound.Sound;
|
||||
import com.github.retrooper.packetevents.util.adventure.AdventureSerializer;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface IJukeboxSong extends MappedEntity, CopyableEntity<IJukeboxSong>, DeepComparableEntity {
|
||||
|
||||
Sound getSound();
|
||||
|
||||
Component getDescription();
|
||||
|
||||
float getLengthInSeconds();
|
||||
|
||||
int getComparatorOutput();
|
||||
|
||||
static IJukeboxSong decode(NBT nbt, ClientVersion version, @Nullable TypesBuilderData data) {
|
||||
NBTCompound compound = (NBTCompound) nbt;
|
||||
Sound sound = Sound.decode(compound.getTagOrThrow("sound_event"), version);
|
||||
Component description = AdventureSerializer.fromNbt(compound.getTagOrThrow("description"));
|
||||
float length = compound.getNumberTagOrThrow("length_in_seconds").getAsFloat();
|
||||
int comparator_output = compound.getNumberTagOrThrow("comparator_output").getAsInt();
|
||||
return new JukeboxSong(data, sound, description, length, comparator_output);
|
||||
}
|
||||
|
||||
static NBT encode(IJukeboxSong jukeboxSong, ClientVersion version) {
|
||||
NBTCompound compound = new NBTCompound();
|
||||
|
||||
compound.setTag("sound_event", Sound.encode(jukeboxSong.getSound(), version));
|
||||
compound.setTag("description", AdventureSerializer.toNbt(jukeboxSong.getDescription()));
|
||||
compound.setTag("length_in_seconds", new NBTFloat(jukeboxSong.getLengthInSeconds()));
|
||||
compound.setTag("comparator_output", new NBTInt(jukeboxSong.getComparatorOutput()));
|
||||
|
||||
return compound;
|
||||
}
|
||||
|
||||
static IJukeboxSong read(PacketWrapper<?> wrapper) {
|
||||
Sound sound = Sound.read(wrapper);
|
||||
Component description = wrapper.readComponent();
|
||||
float lengthInSeconds = wrapper.readFloat();
|
||||
int comparatorOutput = wrapper.readVarInt();
|
||||
|
||||
return new JukeboxSong(null, sound, description, lengthInSeconds, comparatorOutput);
|
||||
}
|
||||
|
||||
static void write(PacketWrapper<?> wrapper, IJukeboxSong song) {
|
||||
Sound.write(wrapper, song.getSound());
|
||||
wrapper.writeComponent(song.getDescription());
|
||||
wrapper.writeFloat(song.getLengthInSeconds());
|
||||
wrapper.writeVarInt(song.getComparatorOutput());
|
||||
}
|
||||
}
|
||||
+36
-14
@@ -18,77 +18,94 @@
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.item.jukebox;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.mapper.AbstractMappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.sound.Sound;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class JukeboxSong {
|
||||
|
||||
public class JukeboxSong extends AbstractMappedEntity implements IJukeboxSong {
|
||||
private Sound sound;
|
||||
private Component description;
|
||||
private float lengthInSeconds;
|
||||
private int comparatorOutput;
|
||||
|
||||
public JukeboxSong(Sound sound, Component description, float lengthInSeconds, int comparatorOutput) {
|
||||
this(null, sound, description, lengthInSeconds, comparatorOutput);
|
||||
}
|
||||
|
||||
public JukeboxSong(@Nullable TypesBuilderData data, Sound sound, Component description, float lengthInSeconds,
|
||||
int comparatorOutput) {
|
||||
super(data);
|
||||
this.sound = sound;
|
||||
this.description = description;
|
||||
this.lengthInSeconds = lengthInSeconds;
|
||||
this.comparatorOutput = comparatorOutput;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static JukeboxSong read(PacketWrapper<?> wrapper) {
|
||||
Sound sound = Sound.read(wrapper);
|
||||
Component description = wrapper.readComponent();
|
||||
float lengthInSeconds = wrapper.readFloat();
|
||||
int comparatorOutput = wrapper.readVarInt();
|
||||
return new JukeboxSong(sound, description, lengthInSeconds, comparatorOutput);
|
||||
return (JukeboxSong) IJukeboxSong.read(wrapper);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void write(PacketWrapper<?> wrapper, JukeboxSong song) {
|
||||
Sound.write(wrapper, song.sound);
|
||||
wrapper.writeComponent(song.description);
|
||||
wrapper.writeFloat(song.lengthInSeconds);
|
||||
wrapper.writeVarInt(song.comparatorOutput);
|
||||
IJukeboxSong.write(wrapper, song);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IJukeboxSong copy(@Nullable TypesBuilderData newData) {
|
||||
return new JukeboxSong(newData, sound, description, lengthInSeconds, comparatorOutput);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sound getSound() {
|
||||
return this.sound;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setSound(Sound sound) {
|
||||
this.sound = sound;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getDescription() {
|
||||
return this.description;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setDescription(Component description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getLengthInSeconds() {
|
||||
return this.lengthInSeconds;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setLengthInSeconds(float lengthInSeconds) {
|
||||
this.lengthInSeconds = lengthInSeconds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getComparatorOutput() {
|
||||
return this.comparatorOutput;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setComparatorOutput(int comparatorOutput) {
|
||||
this.comparatorOutput = comparatorOutput;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
public boolean deepEquals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof JukeboxSong)) return false;
|
||||
if (!super.equals(obj)) return false;
|
||||
JukeboxSong that = (JukeboxSong) obj;
|
||||
if (Float.compare(that.lengthInSeconds, this.lengthInSeconds) != 0) return false;
|
||||
if (this.comparatorOutput != that.comparatorOutput) return false;
|
||||
@@ -97,7 +114,12 @@ public class JukeboxSong {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.sound, this.description, this.lengthInSeconds, this.comparatorOutput);
|
||||
public int deepHashCode() {
|
||||
return Objects.hash(super.hashCode(), this.sound, this.description, this.lengthInSeconds, this.comparatorOutput);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "JukeboxSong{sound=" + this.sound + ", description=" + this.description + ", lengthInSeconds=" + this.lengthInSeconds + ", comparatorOutput=" + this.comparatorOutput + '}';
|
||||
}
|
||||
}
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.item.jukebox;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.sound.Sound;
|
||||
import com.github.retrooper.packetevents.protocol.sound.Sounds;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.util.mappings.VersionedRegistry;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class JukeboxSongs {
|
||||
private static final VersionedRegistry<IJukeboxSong> REGISTRY = new VersionedRegistry<>("jukebox_song",
|
||||
"item/item_jukebox_song_mappings");
|
||||
|
||||
private JukeboxSongs() {
|
||||
}
|
||||
|
||||
private static String makeDescriptionId(String var0, @Nullable ResourceLocation var1) {
|
||||
return var1 == null ? var0 + ".unregistered_sadface" :
|
||||
var0 + "." + var1.getNamespace() + "." + var1.getKey().replace('/', '.');
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static IJukeboxSong define(String key, Sound sound, float lengthInSeconds, int comparatorOutput) {
|
||||
return REGISTRY.define(key, data -> new JukeboxSong(data, sound,
|
||||
Component.translatable(makeDescriptionId("jukebox_song", data.getName())), lengthInSeconds,
|
||||
comparatorOutput));
|
||||
}
|
||||
|
||||
public static VersionedRegistry<IJukeboxSong> getRegistry() {
|
||||
return REGISTRY;
|
||||
}
|
||||
|
||||
public static IJukeboxSong getByName(String name) {
|
||||
return REGISTRY.getByName(name);
|
||||
}
|
||||
|
||||
public static IJukeboxSong getById(ClientVersion version, int id) {
|
||||
return REGISTRY.getById(version, id);
|
||||
}
|
||||
|
||||
public static final IJukeboxSong THIRTEEN = define("13", Sounds.MUSIC_DISC_13, 178, 1);
|
||||
public static final IJukeboxSong CAT = define("cat", Sounds.MUSIC_DISC_CAT, 185, 2);
|
||||
public static final IJukeboxSong BLOCKS = define("blocks", Sounds.MUSIC_DISC_BLOCKS, 345, 3);
|
||||
public static final IJukeboxSong CHIRP = define("chirp", Sounds.MUSIC_DISC_CHIRP, 185, 4);
|
||||
public static final IJukeboxSong FAR = define("far", Sounds.MUSIC_DISC_FAR, 174, 5);
|
||||
public static final IJukeboxSong MALL = define("mall", Sounds.MUSIC_DISC_MALL, 197, 6);
|
||||
public static final IJukeboxSong MELLOHI = define("mellohi", Sounds.MUSIC_DISC_MELLOHI, 96, 7);
|
||||
public static final IJukeboxSong STAL = define("stal", Sounds.MUSIC_DISC_STAL, 150, 8);
|
||||
public static final IJukeboxSong STRAD = define("strad", Sounds.MUSIC_DISC_STRAD, 188, 9);
|
||||
public static final IJukeboxSong WARD = define("ward", Sounds.MUSIC_DISC_WARD, 251, 10);
|
||||
public static final IJukeboxSong ELEVEN = define("11", Sounds.MUSIC_DISC_11, 71, 11);
|
||||
public static final IJukeboxSong WAIT = define("wait", Sounds.MUSIC_DISC_WAIT, 238, 12);
|
||||
public static final IJukeboxSong PIGSTEP = define("pigstep", Sounds.MUSIC_DISC_PIGSTEP, 149, 13);
|
||||
public static final IJukeboxSong OTHERSIDE = define("otherside", Sounds.MUSIC_DISC_OTHERSIDE, 195, 14);
|
||||
public static final IJukeboxSong FIVE = define("5", Sounds.MUSIC_DISC_5, 178, 15);
|
||||
public static final IJukeboxSong RELIC = define("relic", Sounds.MUSIC_DISC_RELIC, 218, 14);
|
||||
public static final IJukeboxSong PRECIPICE = define("precipice", Sounds.MUSIC_DISC_PRECIPICE, 299, 13);
|
||||
public static final IJukeboxSong CREATOR = define("creator", Sounds.MUSIC_DISC_CREATOR, 176, 12);
|
||||
public static final IJukeboxSong CREATOR_MUSIC_BOX = define("creator_music_box", Sounds.MUSIC_DISC_CREATOR_MUSIC_BOX,
|
||||
73, 11);
|
||||
|
||||
/**
|
||||
* Returns an immutable view of the jukebox songs.
|
||||
*
|
||||
* @return Jukebox Songs
|
||||
*/
|
||||
public static Collection<IJukeboxSong> values() {
|
||||
return REGISTRY.getEntries();
|
||||
}
|
||||
|
||||
static {
|
||||
REGISTRY.unloadMappings();
|
||||
}
|
||||
}
|
||||
+12
-23
@@ -20,24 +20,17 @@ package com.github.retrooper.packetevents.protocol.item.mapdecoration;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.util.mappings.MappingHelper;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilder;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import com.github.retrooper.packetevents.util.mappings.VersionedRegistry;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.github.retrooper.packetevents.resources.ResourceLocation.minecraft;
|
||||
|
||||
public class MapDecorationTypes {
|
||||
|
||||
private static final Map<String, MapDecorationType> DECORATION_TYPE_MAP = new HashMap<>();
|
||||
private static final Map<Byte, Map<Integer, MapDecorationType>> DECORATION_TYPE_ID_MAP = new HashMap<>();
|
||||
|
||||
private static final TypesBuilder TYPES_BUILDER = new TypesBuilder("item/item_map_decoration_type_mappings");
|
||||
private static final VersionedRegistry<MapDecorationType> REGISTRY =
|
||||
new VersionedRegistry<>("map_decoration_type", "item/item_map_decoration_type_mappings");
|
||||
|
||||
public static MapDecorationType define(String key, boolean showOnItemFrame, boolean trackCount) {
|
||||
return define(key, minecraft(key), showOnItemFrame, trackCount);
|
||||
@@ -65,8 +58,7 @@ public class MapDecorationTypes {
|
||||
boolean showOnItemFrame, int mapColor,
|
||||
boolean explorationMapElement, boolean trackCount
|
||||
) {
|
||||
TypesBuilderData data = TYPES_BUILDER.define(key);
|
||||
MapDecorationType potionType = new MapDecorationType() {
|
||||
return REGISTRY.define(key, data -> new MapDecorationType() {
|
||||
@Override
|
||||
public ResourceLocation getAssetId() {
|
||||
return assetId;
|
||||
@@ -99,7 +91,7 @@ public class MapDecorationTypes {
|
||||
|
||||
@Override
|
||||
public int getId(ClientVersion version) {
|
||||
return MappingHelper.getId(version, TYPES_BUILDER, data);
|
||||
return data.getId(version);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -109,23 +101,19 @@ public class MapDecorationTypes {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
MappingHelper.registerMapping(TYPES_BUILDER, DECORATION_TYPE_MAP, DECORATION_TYPE_ID_MAP, potionType);
|
||||
return potionType;
|
||||
});
|
||||
}
|
||||
|
||||
public static @Nullable MapDecorationType getByName(String name) {
|
||||
return DECORATION_TYPE_MAP.get(name);
|
||||
return REGISTRY.getByName(name);
|
||||
}
|
||||
|
||||
public static @Nullable MapDecorationType getById(int id, ClientVersion version) {
|
||||
return getById(version, id);
|
||||
return REGISTRY.getById(version, id);
|
||||
}
|
||||
|
||||
public static @Nullable MapDecorationType getById(ClientVersion version, int id) {
|
||||
int index = TYPES_BUILDER.getDataIndex(version);
|
||||
Map<Integer, MapDecorationType> idMap = DECORATION_TYPE_ID_MAP.get((byte) index);
|
||||
return idMap.get(id);
|
||||
return REGISTRY.getById(version, id);
|
||||
}
|
||||
|
||||
// color constants used by vanilla
|
||||
@@ -209,13 +197,14 @@ public class MapDecorationTypes {
|
||||
|
||||
/**
|
||||
* Returns an immutable view of the map decoration types.
|
||||
*
|
||||
* @return Map Decoration Types
|
||||
*/
|
||||
public static Collection<MapDecorationType> values() {
|
||||
return Collections.unmodifiableCollection(DECORATION_TYPE_MAP.values());
|
||||
return REGISTRY.getEntries();
|
||||
}
|
||||
|
||||
static {
|
||||
TYPES_BUILDER.unloadFileMappings();
|
||||
REGISTRY.unloadMappings();
|
||||
}
|
||||
}
|
||||
+45
-24
@@ -20,15 +20,15 @@ package com.github.retrooper.packetevents.protocol.item.trimmaterial;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.item.armormaterial.ArmorMaterial;
|
||||
import com.github.retrooper.packetevents.protocol.item.type.ItemType;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.AbstractMappedEntity;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
public class StaticTrimMaterial implements TrimMaterial {
|
||||
public class StaticTrimMaterial extends AbstractMappedEntity implements TrimMaterial {
|
||||
|
||||
private final String assetName;
|
||||
private final ItemType ingredient;
|
||||
@@ -36,10 +36,34 @@ public class StaticTrimMaterial implements TrimMaterial {
|
||||
private final Map<ArmorMaterial, String> overrideArmorMaterials;
|
||||
private final Component description;
|
||||
|
||||
public StaticTrimMaterial(
|
||||
String assetName, ItemType ingredient,
|
||||
Map<ArmorMaterial, String> overrideArmorMaterials, Component description
|
||||
) {
|
||||
this(null, assetName, ingredient, FALLBACK_ITEM_MODEL_INDEX, overrideArmorMaterials, description);
|
||||
}
|
||||
|
||||
public StaticTrimMaterial(
|
||||
@Nullable TypesBuilderData data,
|
||||
String assetName, ItemType ingredient,
|
||||
Map<ArmorMaterial, String> overrideArmorMaterials, Component description
|
||||
) {
|
||||
this(data, assetName, ingredient, FALLBACK_ITEM_MODEL_INDEX, overrideArmorMaterials, description);
|
||||
}
|
||||
|
||||
public StaticTrimMaterial(
|
||||
String assetName, ItemType ingredient, float itemModelIndex,
|
||||
Map<ArmorMaterial, String> overrideArmorMaterials, Component description
|
||||
) {
|
||||
this(null, assetName, ingredient, itemModelIndex, overrideArmorMaterials, description);
|
||||
}
|
||||
|
||||
public StaticTrimMaterial(
|
||||
@Nullable TypesBuilderData data,
|
||||
String assetName, ItemType ingredient, float itemModelIndex,
|
||||
Map<ArmorMaterial, String> overrideArmorMaterials, Component description
|
||||
) {
|
||||
super(data);
|
||||
this.assetName = assetName;
|
||||
this.ingredient = ingredient;
|
||||
this.itemModelIndex = itemModelIndex;
|
||||
@@ -48,18 +72,9 @@ public class StaticTrimMaterial implements TrimMaterial {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getName() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId(ClientVersion version) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRegistered() {
|
||||
return false;
|
||||
public TrimMaterial copy(@Nullable TypesBuilderData newData) {
|
||||
return new StaticTrimMaterial(newData, this.assetName, this.ingredient, this.itemModelIndex,
|
||||
this.overrideArmorMaterials, this.description);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -88,19 +103,25 @@ public class StaticTrimMaterial implements TrimMaterial {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
public boolean deepEquals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof StaticTrimMaterial)) return false;
|
||||
StaticTrimMaterial material = (StaticTrimMaterial) obj;
|
||||
if (Float.compare(material.itemModelIndex, this.itemModelIndex) != 0) return false;
|
||||
if (!this.assetName.equals(material.assetName)) return false;
|
||||
if (!this.ingredient.equals(material.ingredient)) return false;
|
||||
if (!this.overrideArmorMaterials.equals(material.overrideArmorMaterials)) return false;
|
||||
return this.description.equals(material.description);
|
||||
if (!super.equals(obj)) return false;
|
||||
StaticTrimMaterial that = (StaticTrimMaterial) obj;
|
||||
if (Float.compare(that.itemModelIndex, this.itemModelIndex) != 0) return false;
|
||||
if (!this.assetName.equals(that.assetName)) return false;
|
||||
if (!this.ingredient.equals(that.ingredient)) return false;
|
||||
if (!this.overrideArmorMaterials.equals(that.overrideArmorMaterials)) return false;
|
||||
return this.description.equals(that.description);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.assetName, this.ingredient, this.itemModelIndex, this.overrideArmorMaterials, this.description);
|
||||
public int deepHashCode() {
|
||||
return Objects.hash(super.hashCode(), this.assetName, this.ingredient, this.itemModelIndex, this.overrideArmorMaterials, this.description);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "StaticTrimMaterial{assetName='" + this.assetName + '\'' + ", ingredient=" + this.ingredient + ", itemModelIndex=" + this.itemModelIndex + ", overrideArmorMaterials=" + this.overrideArmorMaterials + ", description=" + this.description + '}';
|
||||
}
|
||||
}
|
||||
+74
-4
@@ -18,23 +18,42 @@
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.item.trimmaterial;
|
||||
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.protocol.item.armormaterial.ArmorMaterial;
|
||||
import com.github.retrooper.packetevents.protocol.item.armormaterial.ArmorMaterials;
|
||||
import com.github.retrooper.packetevents.protocol.item.type.ItemType;
|
||||
import com.github.retrooper.packetevents.protocol.item.type.ItemTypes;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.CopyableEntity;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.DeepComparableEntity;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.MappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTFloat;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.util.adventure.AdventureSerializer;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public interface TrimMaterial extends MappedEntity {
|
||||
public interface TrimMaterial extends MappedEntity, CopyableEntity<TrimMaterial>, DeepComparableEntity {
|
||||
|
||||
float FALLBACK_ITEM_MODEL_INDEX = 0f;
|
||||
|
||||
String getAssetName();
|
||||
|
||||
ItemType getIngredient();
|
||||
|
||||
/**
|
||||
* Removed in 1.21.4
|
||||
*/
|
||||
@ApiStatus.Obsolete
|
||||
float getItemModelIndex();
|
||||
|
||||
default @Nullable String getArmorMaterialOverride(ArmorMaterial armorMaterial) {
|
||||
@@ -46,13 +65,14 @@ public interface TrimMaterial extends MappedEntity {
|
||||
Component getDescription();
|
||||
|
||||
static TrimMaterial read(PacketWrapper<?> wrapper) {
|
||||
return wrapper.readMappedEntityOrDirect(TrimMaterials::getById, TrimMaterial::readDirect);
|
||||
return wrapper.readMappedEntityOrDirect(TrimMaterials.getRegistry(), TrimMaterial::readDirect);
|
||||
}
|
||||
|
||||
static TrimMaterial readDirect(PacketWrapper<?> wrapper) {
|
||||
String assetName = wrapper.readString();
|
||||
ItemType ingredient = wrapper.readMappedEntity(ItemTypes::getById);
|
||||
float itemModelIndex = wrapper.readFloat();
|
||||
float itemModelIndex = wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_4)
|
||||
? FALLBACK_ITEM_MODEL_INDEX : wrapper.readFloat();
|
||||
Map<ArmorMaterial, String> overrideArmorMaterials = wrapper.readMap(
|
||||
ew -> ew.readMappedEntity(ArmorMaterials::getById),
|
||||
PacketWrapper::readString);
|
||||
@@ -67,9 +87,59 @@ public interface TrimMaterial extends MappedEntity {
|
||||
static void writeDirect(PacketWrapper<?> wrapper, TrimMaterial material) {
|
||||
wrapper.writeString(material.getAssetName());
|
||||
wrapper.writeMappedEntity(material.getIngredient());
|
||||
wrapper.writeFloat(material.getItemModelIndex());
|
||||
if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_4)) {
|
||||
wrapper.writeFloat(material.getItemModelIndex());
|
||||
}
|
||||
wrapper.writeMap(material.getOverrideArmorMaterials(),
|
||||
PacketWrapper::writeMappedEntity, PacketWrapper::writeString);
|
||||
wrapper.writeComponent(material.getDescription());
|
||||
}
|
||||
|
||||
static TrimMaterial decode(NBT nbt, ClientVersion version, @Nullable TypesBuilderData data) {
|
||||
NBTCompound compound = (NBTCompound) nbt;
|
||||
String assetName = compound.getStringTagValueOrThrow("asset_name");
|
||||
ItemType ingredient = ItemTypes.getByName(compound.getStringTagValueOrThrow("ingredient"));
|
||||
float itemModelIndex = version.isNewerThanOrEquals(ClientVersion.V_1_21_4)
|
||||
? FALLBACK_ITEM_MODEL_INDEX : compound.getNumberTagOrThrow("item_model_index").getAsFloat();
|
||||
NBTCompound overrideArmorMaterialsTag = compound.getCompoundTagOrNull("override_armor_materials");
|
||||
Map<ArmorMaterial, String> overrideArmorMaterials;
|
||||
if (overrideArmorMaterialsTag != null) {
|
||||
overrideArmorMaterials = new HashMap<>();
|
||||
for (Map.Entry<String, NBT> entry : overrideArmorMaterialsTag.getTags().entrySet()) {
|
||||
ArmorMaterial material = ArmorMaterials.getByName(entry.getKey());
|
||||
String override = ((NBTString) entry.getValue()).getValue();
|
||||
overrideArmorMaterials.put(material, override);
|
||||
}
|
||||
} else {
|
||||
overrideArmorMaterials = Collections.emptyMap();
|
||||
}
|
||||
Component description = AdventureSerializer.fromNbt(((NBTCompound) nbt).getTagOrThrow("description"));
|
||||
return new StaticTrimMaterial(data, assetName, ingredient, itemModelIndex, overrideArmorMaterials, description);
|
||||
}
|
||||
|
||||
static NBT encode(TrimMaterial material, ClientVersion version) {
|
||||
NBTCompound overrideArmorMaterialsTag;
|
||||
if (!material.getOverrideArmorMaterials().isEmpty()) {
|
||||
overrideArmorMaterialsTag = new NBTCompound();
|
||||
for (Map.Entry<ArmorMaterial, String> entry : material.getOverrideArmorMaterials().entrySet()) {
|
||||
String materialName = entry.getKey().getName().toString();
|
||||
NBTString overrideTag = new NBTString(entry.getValue());
|
||||
overrideArmorMaterialsTag.setTag(materialName, overrideTag);
|
||||
}
|
||||
} else {
|
||||
overrideArmorMaterialsTag = null;
|
||||
}
|
||||
|
||||
NBTCompound compound = new NBTCompound();
|
||||
compound.setTag("asset_name", new NBTString(material.getAssetName()));
|
||||
compound.setTag("ingredient", new NBTString(material.getIngredient().getName().toString()));
|
||||
if (version.isNewerThanOrEquals(ClientVersion.V_1_21_4)) {
|
||||
compound.setTag("item_model_index", new NBTFloat(material.getItemModelIndex()));
|
||||
}
|
||||
if (overrideArmorMaterialsTag != null) {
|
||||
compound.setTag("override_armor_materials", overrideArmorMaterialsTag);
|
||||
}
|
||||
compound.setTag("description", AdventureSerializer.toNbt(material.getDescription()));
|
||||
return compound;
|
||||
}
|
||||
}
|
||||
+24
-62
@@ -24,25 +24,26 @@ import com.github.retrooper.packetevents.protocol.item.type.ItemType;
|
||||
import com.github.retrooper.packetevents.protocol.item.type.ItemTypes;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.util.mappings.MappingHelper;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilder;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import com.github.retrooper.packetevents.util.mappings.VersionedRegistry;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static net.kyori.adventure.text.Component.translatable;
|
||||
import static net.kyori.adventure.text.format.TextColor.color;
|
||||
|
||||
public class TrimMaterials {
|
||||
public final class TrimMaterials {
|
||||
|
||||
private static final Map<String, TrimMaterial> TRIM_MATERIAL_MAP = new HashMap<>();
|
||||
private static final Map<Byte, Map<Integer, TrimMaterial>> TRIM_MATERIAL_ID_MAP = new HashMap<>();
|
||||
private static final TypesBuilder TYPES_BUILDER = new TypesBuilder("item/item_trim_material_mappings");
|
||||
private static final VersionedRegistry<TrimMaterial> REGISTRY = new VersionedRegistry<>(
|
||||
"trim_material", "item/item_trim_material_mappings");
|
||||
|
||||
private TrimMaterials() {
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static TrimMaterial define(String key, ItemType ingredient, float itemModelIndex, int color) {
|
||||
// darken own armor material - if present
|
||||
Map<ArmorMaterial, String> overrideArmorMaterials = new HashMap<>(2);
|
||||
@@ -56,68 +57,25 @@ public class TrimMaterials {
|
||||
return define(key, key, ingredient, itemModelIndex, overrideArmorMaterials, description);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static TrimMaterial define(
|
||||
String key, String assetName, ItemType ingredient, float itemModelIndex,
|
||||
Map<ArmorMaterial, String> overrideArmorMaterials, Component description
|
||||
) {
|
||||
TypesBuilderData data = TYPES_BUILDER.define(key);
|
||||
TrimMaterial material = new TrimMaterial() {
|
||||
@Override
|
||||
public String getAssetName() {
|
||||
return assetName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemType getIngredient() {
|
||||
return ingredient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getItemModelIndex() {
|
||||
return itemModelIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<ArmorMaterial, String> getOverrideArmorMaterials() {
|
||||
return overrideArmorMaterials;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getName() {
|
||||
return data.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId(ClientVersion version) {
|
||||
return MappingHelper.getId(version, TYPES_BUILDER, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof TrimMaterial) {
|
||||
return this.getName().equals(((TrimMaterial) obj).getName());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
MappingHelper.registerMapping(TYPES_BUILDER, TRIM_MATERIAL_MAP, TRIM_MATERIAL_ID_MAP, material);
|
||||
return material;
|
||||
return REGISTRY.define(key, data ->
|
||||
new StaticTrimMaterial(data, assetName, ingredient, itemModelIndex, overrideArmorMaterials, description));
|
||||
}
|
||||
|
||||
public static VersionedRegistry<TrimMaterial> getRegistry() {
|
||||
return REGISTRY;
|
||||
}
|
||||
|
||||
// with key
|
||||
public static TrimMaterial getByName(String name) {
|
||||
return TRIM_MATERIAL_MAP.get(name);
|
||||
return REGISTRY.getByName(name);
|
||||
}
|
||||
|
||||
public static TrimMaterial getById(ClientVersion version, int id) {
|
||||
int index = TYPES_BUILDER.getDataIndex(version);
|
||||
Map<Integer, TrimMaterial> idMap = TRIM_MATERIAL_ID_MAP.get((byte) index);
|
||||
return idMap.get(id);
|
||||
return REGISTRY.getById(version, id);
|
||||
}
|
||||
|
||||
// Added in 1.19.4
|
||||
@@ -132,15 +90,19 @@ public class TrimMaterials {
|
||||
public static final TrimMaterial QUARTZ = define("quartz", ItemTypes.QUARTZ, 0.1f, 0xE3D4C4);
|
||||
public static final TrimMaterial REDSTONE = define("redstone", ItemTypes.REDSTONE, 0.4f, 0x971607);
|
||||
|
||||
// added with 1.21.4
|
||||
public static final TrimMaterial RESIN = define("resin", ItemTypes.RESIN_BRICK, 0.11f, 0xFC7812);
|
||||
|
||||
/**
|
||||
* Returns an immutable view of the trim materials.
|
||||
*
|
||||
* @return Trim Materials
|
||||
*/
|
||||
public static Collection<TrimMaterial> values() {
|
||||
return Collections.unmodifiableCollection(TRIM_MATERIAL_MAP.values());
|
||||
return REGISTRY.getEntries();
|
||||
}
|
||||
|
||||
static {
|
||||
TYPES_BUILDER.unloadFileMappings();
|
||||
REGISTRY.unloadMappings();
|
||||
}
|
||||
}
|
||||
+30
-22
@@ -19,13 +19,15 @@
|
||||
package com.github.retrooper.packetevents.protocol.item.trimpattern;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.item.type.ItemType;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.AbstractMappedEntity;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class StaticTrimPattern implements TrimPattern {
|
||||
public class StaticTrimPattern extends AbstractMappedEntity implements TrimPattern {
|
||||
|
||||
private final ResourceLocation assetId;
|
||||
private final ItemType templateItem;
|
||||
@@ -36,6 +38,15 @@ public class StaticTrimPattern implements TrimPattern {
|
||||
ResourceLocation assetId, ItemType templateItem,
|
||||
Component description, boolean decal
|
||||
) {
|
||||
this(null, assetId, templateItem, description, decal);
|
||||
}
|
||||
|
||||
public StaticTrimPattern(
|
||||
@Nullable TypesBuilderData data,
|
||||
ResourceLocation assetId, ItemType templateItem,
|
||||
Component description, boolean decal
|
||||
) {
|
||||
super(data);
|
||||
this.assetId = assetId;
|
||||
this.templateItem = templateItem;
|
||||
this.description = description;
|
||||
@@ -43,18 +54,9 @@ public class StaticTrimPattern implements TrimPattern {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getName() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId(ClientVersion version) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRegistered() {
|
||||
return false;
|
||||
public TrimPattern copy(@Nullable TypesBuilderData newData) {
|
||||
return new StaticTrimPattern(newData, this.assetId,
|
||||
this.templateItem, this.description, this.decal);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -78,18 +80,24 @@ public class StaticTrimPattern implements TrimPattern {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
public boolean deepEquals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof StaticTrimPattern)) return false;
|
||||
StaticTrimPattern pattern = (StaticTrimPattern) obj;
|
||||
if (this.decal != pattern.decal) return false;
|
||||
if (!this.assetId.equals(pattern.assetId)) return false;
|
||||
if (!this.templateItem.equals(pattern.templateItem)) return false;
|
||||
return this.description.equals(pattern.description);
|
||||
if (!super.equals(obj)) return false;
|
||||
StaticTrimPattern that = (StaticTrimPattern) obj;
|
||||
if (this.decal != that.decal) return false;
|
||||
if (!this.assetId.equals(that.assetId)) return false;
|
||||
if (!this.templateItem.equals(that.templateItem)) return false;
|
||||
return this.description.equals(that.description);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.assetId, this.templateItem, this.description, this.decal);
|
||||
public int deepHashCode() {
|
||||
return Objects.hash(super.hashCode(), this.assetId, this.templateItem, this.description, this.decal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "StaticTrimPattern{assetId=" + this.assetId + ", templateItem=" + this.templateItem + ", description=" + this.description + ", decal=" + this.decal + '}';
|
||||
}
|
||||
}
|
||||
+32
-2
@@ -20,12 +20,22 @@ package com.github.retrooper.packetevents.protocol.item.trimpattern;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.item.type.ItemType;
|
||||
import com.github.retrooper.packetevents.protocol.item.type.ItemTypes;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.CopyableEntity;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.DeepComparableEntity;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.MappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTByte;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.util.adventure.AdventureSerializer;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface TrimPattern extends MappedEntity {
|
||||
public interface TrimPattern extends MappedEntity, CopyableEntity<TrimPattern>, DeepComparableEntity {
|
||||
|
||||
ResourceLocation getAssetId();
|
||||
|
||||
@@ -36,7 +46,7 @@ public interface TrimPattern extends MappedEntity {
|
||||
boolean isDecal();
|
||||
|
||||
static TrimPattern read(PacketWrapper<?> wrapper) {
|
||||
return wrapper.readMappedEntityOrDirect(TrimPatterns::getById, TrimPattern::readDirect);
|
||||
return wrapper.readMappedEntityOrDirect(TrimPatterns.getRegistry(), TrimPattern::readDirect);
|
||||
}
|
||||
|
||||
static TrimPattern readDirect(PacketWrapper<?> wrapper) {
|
||||
@@ -57,4 +67,24 @@ public interface TrimPattern extends MappedEntity {
|
||||
wrapper.writeComponent(pattern.getDescription());
|
||||
wrapper.writeBoolean(pattern.isDecal());
|
||||
}
|
||||
|
||||
static TrimPattern decode(NBT nbt, ClientVersion version, @Nullable TypesBuilderData data) {
|
||||
NBTCompound compound = (NBTCompound) nbt;
|
||||
ResourceLocation assetId = new ResourceLocation(compound.getStringTagValueOrThrow("asset_id"));
|
||||
ItemType templateItem = ItemTypes.getByName(compound.getStringTagValueOrThrow("template_item"));
|
||||
Component description = AdventureSerializer.fromNbt(compound.getTagOrThrow("description"));
|
||||
boolean decal = version.isNewerThanOrEquals(ClientVersion.V_1_20_2) && compound.getBoolean("decal");
|
||||
return new StaticTrimPattern(data, assetId, templateItem, description, decal);
|
||||
}
|
||||
|
||||
static NBT encode(TrimPattern pattern, ClientVersion version) {
|
||||
NBTCompound compound = new NBTCompound();
|
||||
compound.setTag("asset_id", new NBTString(pattern.getAssetId().toString()));
|
||||
compound.setTag("template_item", new NBTString(pattern.getTemplateItem().getName().toString()));
|
||||
compound.setTag("description", AdventureSerializer.toNbt(pattern.getDescription()));
|
||||
if (version.isNewerThanOrEquals(ClientVersion.V_1_20_2)) {
|
||||
compound.setTag("decal", new NBTByte(pattern.isDecal()));
|
||||
}
|
||||
return compound;
|
||||
}
|
||||
}
|
||||
+18
-57
@@ -22,20 +22,19 @@ import com.github.retrooper.packetevents.protocol.item.type.ItemType;
|
||||
import com.github.retrooper.packetevents.protocol.item.type.ItemTypes;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.util.mappings.MappingHelper;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilder;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import com.github.retrooper.packetevents.util.mappings.VersionedRegistry;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
public final class TrimPatterns {
|
||||
|
||||
public class TrimPatterns {
|
||||
private static final VersionedRegistry<TrimPattern> REGISTRY = new VersionedRegistry<>(
|
||||
"trim_pattern", "item/item_trim_pattern_mappings");
|
||||
|
||||
private static final Map<String, TrimPattern> PATTERN_TYPE_MAP = new HashMap<>();
|
||||
private static final Map<Byte, Map<Integer, TrimPattern>> PATTERN_TYPE_ID_MAP = new HashMap<>();
|
||||
private static final TypesBuilder TYPES_BUILDER = new TypesBuilder("item/item_trim_pattern_mappings");
|
||||
private TrimPatterns() {
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static TrimPattern define(String key) {
|
||||
ResourceLocation assetId = ResourceLocation.minecraft(key);
|
||||
ItemType templateItem = ItemTypes.getByName(assetId + "_armor_trim_smithing_template");
|
||||
@@ -44,63 +43,25 @@ public class TrimPatterns {
|
||||
return define(key, assetId, templateItem, description, decal);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static TrimPattern define(
|
||||
String key, ResourceLocation assetId, ItemType templateItem,
|
||||
Component description, boolean decal
|
||||
) {
|
||||
TypesBuilderData data = TYPES_BUILDER.define(key);
|
||||
TrimPattern pattern = new TrimPattern() {
|
||||
@Override
|
||||
public ResourceLocation getAssetId() {
|
||||
return assetId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemType getTemplateItem() {
|
||||
return templateItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDecal() {
|
||||
return decal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getName() {
|
||||
return data.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId(ClientVersion version) {
|
||||
return MappingHelper.getId(version, TYPES_BUILDER, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof TrimPattern) {
|
||||
return this.getName().equals(((TrimPattern) obj).getName());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
MappingHelper.registerMapping(TYPES_BUILDER, PATTERN_TYPE_MAP, PATTERN_TYPE_ID_MAP, pattern);
|
||||
return pattern;
|
||||
return REGISTRY.define(key, data ->
|
||||
new StaticTrimPattern(data, assetId, templateItem, description, decal));
|
||||
}
|
||||
|
||||
public static VersionedRegistry<TrimPattern> getRegistry() {
|
||||
return REGISTRY;
|
||||
}
|
||||
|
||||
// with key
|
||||
public static TrimPattern getByName(String name) {
|
||||
return PATTERN_TYPE_MAP.get(name);
|
||||
return REGISTRY.getByName(name);
|
||||
}
|
||||
|
||||
public static TrimPattern getById(ClientVersion version, int id) {
|
||||
int index = TYPES_BUILDER.getDataIndex(version);
|
||||
Map<Integer, TrimPattern> idMap = PATTERN_TYPE_ID_MAP.get((byte) index);
|
||||
return idMap.get(id);
|
||||
return REGISTRY.getById(version, id);
|
||||
}
|
||||
|
||||
// Added in 1.19.4
|
||||
@@ -128,6 +89,6 @@ public class TrimPatterns {
|
||||
public static final TrimPattern FLOW = define("flow");
|
||||
|
||||
static {
|
||||
TYPES_BUILDER.unloadFileMappings();
|
||||
REGISTRY.unloadMappings();
|
||||
}
|
||||
}
|
||||
+15
-3
@@ -18,30 +18,42 @@
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.item.type;
|
||||
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.protocol.component.StaticComponentMap;
|
||||
import com.github.retrooper.packetevents.protocol.item.type.ItemTypes.ItemAttribute;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.MappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public interface ItemType extends MappedEntity {
|
||||
|
||||
int getMaxAmount();
|
||||
|
||||
int getMaxDurability();
|
||||
|
||||
boolean isMusicDisc();
|
||||
default boolean isMusicDisc() {
|
||||
return this.hasAttribute(ItemAttribute.MUSIC_DISC);
|
||||
}
|
||||
|
||||
ItemType getCraftRemainder();
|
||||
|
||||
@Nullable
|
||||
StateType getPlacedType();
|
||||
|
||||
Set<ItemTypes.ItemAttribute> getAttributes();
|
||||
Set<ItemAttribute> getAttributes();
|
||||
|
||||
boolean hasAttribute(ItemTypes.ItemAttribute attribute);
|
||||
default boolean hasAttribute(ItemAttribute attribute) {
|
||||
return this.getAttributes().contains(attribute);
|
||||
}
|
||||
|
||||
default StaticComponentMap getComponents() {
|
||||
return this.getComponents(PacketEvents.getAPI().getServerManager().getVersion().toClientVersion());
|
||||
}
|
||||
|
||||
default StaticComponentMap getComponents(ClientVersion clientVersion) {
|
||||
return StaticComponentMap.EMPTY;
|
||||
}
|
||||
}
|
||||
+393
-387
File diff suppressed because it is too large.
Load diff
+136
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.item.type;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.component.StaticComponentMap;
|
||||
import com.github.retrooper.packetevents.protocol.item.type.ItemTypes.ItemAttribute;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.AbstractMappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class StaticItemType extends AbstractMappedEntity implements ItemType {
|
||||
|
||||
private final int maxAmount;
|
||||
private final int maxDurability;
|
||||
private final ItemType craftRemainder;
|
||||
private final @Nullable StateType placedType;
|
||||
private final Set<ItemAttribute> attributes;
|
||||
private final Map<ClientVersion, StaticComponentMap> components;
|
||||
|
||||
StaticItemType(
|
||||
TypesBuilderData data,
|
||||
int maxAmount,
|
||||
int maxDurability,
|
||||
ItemType craftRemainder,
|
||||
@Nullable StateType placedType,
|
||||
Set<ItemAttribute> attributes
|
||||
) {
|
||||
super(data);
|
||||
this.maxAmount = maxAmount;
|
||||
this.maxDurability = maxDurability;
|
||||
this.craftRemainder = craftRemainder;
|
||||
this.placedType = placedType;
|
||||
this.attributes = attributes;
|
||||
this.components = new EnumMap<>(ClientVersion.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxAmount() {
|
||||
return this.maxAmount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxDurability() {
|
||||
return this.maxDurability;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemType getCraftRemainder() {
|
||||
return this.craftRemainder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable StateType getPlacedType() {
|
||||
return this.placedType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<ItemAttribute> getAttributes() {
|
||||
return this.attributes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StaticComponentMap getComponents(ClientVersion version) {
|
||||
if (!version.isRelease()) {
|
||||
throw new IllegalArgumentException("Unsupported version for "
|
||||
+ "getting components of " + this.getName() + ": " + version);
|
||||
}
|
||||
return this.components.getOrDefault(version, StaticComponentMap.SHARED_ITEM_COMPONENTS);
|
||||
}
|
||||
|
||||
void setComponents(ClientVersion version, StaticComponentMap components) {
|
||||
if (this.components.containsKey(version)) {
|
||||
throw new IllegalStateException("Components are already defined for "
|
||||
+ this.getName() + " in version " + version);
|
||||
} else if (!version.isRelease()) {
|
||||
throw new IllegalArgumentException("Unsupported version for "
|
||||
+ "setting components of " + this.getName() + ": " + version);
|
||||
}
|
||||
this.components.put(version, components);
|
||||
}
|
||||
|
||||
// internal, only used for checking wether
|
||||
// component definition is present during startup
|
||||
boolean hasComponents(ClientVersion version) {
|
||||
return this.components.containsKey(version);
|
||||
}
|
||||
|
||||
// fills holes in the base component mappings
|
||||
void fillComponents() {
|
||||
StaticComponentMap lastComponents = null;
|
||||
for (ClientVersion version : ClientVersion.values()) {
|
||||
if (!version.isRelease()) {
|
||||
continue;
|
||||
}
|
||||
StaticComponentMap components = this.components.get(version);
|
||||
if (components == null) {
|
||||
if (lastComponents != null) {
|
||||
this.components.put(version, lastComponents);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (lastComponents == null) {
|
||||
// also fill backwards
|
||||
for (ClientVersion beforeVersion : ClientVersion.values()) {
|
||||
if (beforeVersion == version) {
|
||||
break;
|
||||
}
|
||||
this.components.put(beforeVersion, components);
|
||||
}
|
||||
}
|
||||
lastComponents = components;
|
||||
}
|
||||
}
|
||||
}
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.mapper;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public abstract class AbstractMappedEntity implements MappedEntity {
|
||||
|
||||
protected final @Nullable TypesBuilderData data;
|
||||
|
||||
protected AbstractMappedEntity(@Nullable TypesBuilderData data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public @Nullable TypesBuilderData getRegistryData() {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getName() {
|
||||
if (this.data != null) {
|
||||
return this.data.getName();
|
||||
}
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId(ClientVersion version) {
|
||||
if (this.data != null) {
|
||||
return this.data.getId(version);
|
||||
}
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRegistered() {
|
||||
return this.data != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof AbstractMappedEntity)) return false;
|
||||
AbstractMappedEntity that = (AbstractMappedEntity) obj;
|
||||
if (this.data != null && that.data != null) {
|
||||
return this.data.getName().equals(that.data.getName());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
if (this.data != null) {
|
||||
return Objects.hashCode(this.data.getName());
|
||||
}
|
||||
return super.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getClass().getSimpleName() + "[" + (this.data == null ? this.hashCode() : this.data.getName()) + ']';
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.mapper;
|
||||
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface CopyableEntity<T extends MappedEntity> {
|
||||
|
||||
T copy(@Nullable TypesBuilderData newData);
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 retrooper and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.mapper;
|
||||
|
||||
public interface DeepComparableEntity {
|
||||
|
||||
boolean deepEquals(Object obj);
|
||||
|
||||
int deepHashCode();
|
||||
}
|
||||
Loaded 100 of 436 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user