Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ccfb6b422c | ||
|
|
2c8143ddb0 | ||
|
|
f9892c598c | ||
|
|
3eb79fd6d2 | ||
|
|
8ddceada42 | ||
|
|
a1c355d4c9 | ||
|
|
5c23459e1e | ||
|
|
af3dbc928b | ||
|
|
bd1bc7f06a | ||
|
|
7f16b992eb | ||
|
|
460884cbd8 | ||
|
|
24bf010d98 | ||
|
|
e74adedf88 | ||
|
|
a34d03f422 | ||
|
|
c0a9be3c7d | ||
|
|
8f352d9115 | ||
|
|
6ca306405c | ||
|
|
d4190b2fde | ||
|
|
30ed0bdcf3 | ||
|
|
c3e2c3ee9e | ||
|
|
155f8520d4 | ||
|
|
55b548d3ca | ||
|
|
8eff09ff6e | ||
|
|
59596653a2 | ||
|
|
4df76391cb | ||
|
|
822f1d26b8 | ||
|
|
55a42ab0e2 | ||
|
|
cdf3521154 | ||
|
|
820b530240 | ||
|
|
1823f61748 | ||
|
|
d27d8ffd6a | ||
|
|
7a57012822 | ||
|
|
0a10f4d861 | ||
|
|
d1a3145483 | ||
|
|
08096106f8 | ||
|
|
a3fbccc454 | ||
|
|
9ea931d58d | ||
|
|
364be4e34d | ||
|
|
b22394c288 | ||
|
|
208dfbc3f3 | ||
|
|
cfb054b8b2 | ||
|
|
f47e6880fd | ||
|
|
f55f791f8a | ||
|
|
ba389ddb57 | ||
|
|
2ce143d466 | ||
|
|
b7f99503d9 | ||
|
|
52adfbae8a | ||
|
|
a861066cab | ||
|
|
1acec02bfb | ||
|
|
b88857386a | ||
|
|
4c48d4c1df | ||
|
|
68f8fd3d03 | ||
|
|
2d625c6e7a | ||
|
|
83fe2cce0d | ||
|
|
73bfaebab6 | ||
|
|
2ac61fd5cb | ||
|
|
7d31150b35 | ||
|
|
11e4033ec6 | ||
|
|
a6a8866727 | ||
|
|
ce61c3ef52 | ||
|
|
4602ea8107 | ||
|
|
5fb1a6c85e | ||
|
|
7e2ac525ac | ||
|
|
7590d6f7de | ||
|
|
d7c2284ccb | ||
|
|
84a0759288 | ||
|
|
0ca8e27fc8 | ||
|
|
5e30aef0a1 | ||
|
|
9e53791fef | ||
|
|
8346918e86 | ||
|
|
7714c6253a | ||
|
|
0a00e970d7 | ||
|
|
d0dd8dc4cd | ||
|
|
bc01609828 | ||
|
|
c6e7bcb980 | ||
|
|
8987194030 | ||
|
|
4495db796d | ||
|
|
e1a29a20a7 | ||
|
|
bd5ef7cb30 | ||
|
|
36363c885c | ||
|
|
a198f0e8d6 | ||
|
|
69cbe1e405 | ||
|
|
2b0ec87da6 | ||
|
|
08f95b8036 | ||
|
|
a15ad3a8d7 | ||
|
|
fef7f983b0 | ||
|
|
71eae683fb | ||
|
|
f692f41025 | ||
|
|
3b4acde6f8 | ||
|
|
6b14595582 | ||
|
|
50c2a69449 | ||
|
|
b62fc6922c | ||
|
|
1b5479f04f | ||
|
|
ac0041ff52 | ||
|
|
c6f129cdd3 | ||
|
|
21226e6ac9 | ||
|
|
b14f5f5031 | ||
|
|
6ff9f8c401 | ||
|
|
22b28b7b35 | ||
|
|
9e7de426c0 | ||
|
|
77abb65bab | ||
|
|
a5188e5d78 | ||
|
|
cce0ac2d7b | ||
|
|
001f6b9fd7 | ||
|
|
0395378726 | ||
|
|
31fe7a89d9 | ||
|
|
d8b47495e4 | ||
|
|
cba4603ad8 | ||
|
|
f37c74d0d9 | ||
|
|
2085dfb84b | ||
|
|
cdad13d5c5 | ||
|
|
95b50a44e9 | ||
|
|
78f630b5c1 | ||
|
|
08d000ea82 | ||
|
|
28c4fdc7ce | ||
|
|
96c81a69ae | ||
|
|
83720c6a81 | ||
|
|
c95acffab6 | ||
|
|
c2beb331f1 | ||
|
|
2667431ec9 | ||
|
|
21ce0f4d34 | ||
|
|
21c1a7dfa8 | ||
|
|
518a995e8e | ||
|
|
e20e0854ab | ||
|
|
7c3cde51f0 | ||
|
|
cc18a7ad08 | ||
|
|
35fa135e9e | ||
|
|
c68fe76156 | ||
|
|
80846cfea2 | ||
|
|
1a1b03c1f5 | ||
|
|
c411a1925b | ||
|
|
d8b4f5b1b6 | ||
|
|
486c9a493a | ||
|
|
b1ed98f53d | ||
|
|
ca8ca782fc | ||
|
|
c75f039c99 | ||
|
|
c1324fe7fe | ||
|
|
781d4a7c82 | ||
|
|
590479adda | ||
|
|
df2c50ccfc | ||
|
|
f5b60ea3f2 | ||
|
|
c95194f147 | ||
|
|
56a643f8d0 | ||
|
|
7daed688e0 | ||
|
|
f3782dffe1 | ||
|
|
b06063ebf7 | ||
|
|
6cb3d301d8 | ||
|
|
1aab738dd5 | ||
|
|
0aafad8b58 | ||
|
|
910d77252e | ||
|
|
524e6ca16d | ||
|
|
1aa88d05bf | ||
|
|
70271f3694 | ||
|
|
62201ae3fa | ||
|
|
8ce56fc346 | ||
|
|
8029fd1b4e | ||
|
|
de19712dbb | ||
|
|
1d41037bdd | ||
|
|
a98b8c5604 | ||
|
|
7d5d2682b7 | ||
|
|
2b5f8027f0 | ||
|
|
1e37351b48 | ||
|
|
70c8aad74e | ||
|
|
5527546f05 | ||
|
|
56671341ae | ||
|
|
41ea688ff3 | ||
|
|
004195144d | ||
|
|
962aefba17 | ||
|
|
88ec7a583d | ||
|
|
2303d362d7 | ||
|
|
da0e95fa03 | ||
|
|
c98bfad8b8 | ||
|
|
3dfb8389dc | ||
|
|
7c74dd2e05 | ||
|
|
05eabbf667 | ||
|
|
d1cafe2bcc | ||
|
|
26078fcb59 | ||
|
|
3d602b9f96 | ||
|
|
df4f9e425e | ||
|
|
efb9766388 | ||
|
|
ab0ad68d43 | ||
|
|
1be8db5ff4 | ||
|
|
1f68ee1f46 | ||
|
|
e7c6ae4726 | ||
|
|
5db1671895 | ||
|
|
023a0da619 | ||
|
|
51863fa435 |
No files matched your search
@@ -13,7 +13,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Validate gradle wrapper
|
||||
uses: gradle/actions/wrapper-validation@v3
|
||||
uses: gradle/actions/wrapper-validation@v4
|
||||
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v4
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
name: Release
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: Publish Release
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Validate gradle wrapper
|
||||
uses: gradle/actions/wrapper-validation@v4
|
||||
|
||||
- name: Setup java 21
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: 21
|
||||
distribution: temurin
|
||||
|
||||
- name: Prepare gradle
|
||||
run: ./gradlew printVersion --no-daemon
|
||||
|
||||
- name: Extract changelog
|
||||
id: changelog
|
||||
run: |
|
||||
OUTPUT_DELIMITER="$(uuidgen)"
|
||||
echo "changelog<<$OUTPUT_DELIMITER" >> "$GITHUB_OUTPUT"
|
||||
|
||||
# extract tag name and use it to get changelog section
|
||||
TAG_NAME="v$(./gradlew -q --no-daemon printVersion)"
|
||||
awk -v tag="${TAG_NAME}" '
|
||||
$1 == "!!!!!" && $2 == tag {found=1; next}
|
||||
$1 == "!!!!!" && found {exit}
|
||||
found
|
||||
' CHANGELOG.md >> "$GITHUB_OUTPUT"
|
||||
|
||||
# end output
|
||||
echo "$OUTPUT_DELIMITER" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Publish plugin
|
||||
env:
|
||||
GITHUB_API_TOKEN: ${{ github.token }}
|
||||
MODRINTH_API_TOKEN: ${{ secrets.MODRINTH_PUBLISH_TOKEN }}
|
||||
CHANGELOG: ${{ steps.changelog.outputs.changelog }}
|
||||
run: ./gradlew publishMods --no-daemon -PnoDryPublish
|
||||
+294
@@ -0,0 +1,294 @@
|
||||
!!!!! v2.9.5
|
||||
|
||||
# PacketEvents 2.9.5 is out now! 🎉
|
||||
|
||||
This update includes critical bug fixes & minor additions to the API.
|
||||
|
||||
# Brief Announcement 📢⚠️
|
||||
|
||||
### We have our very own website: https://packetevents.com
|
||||
|
||||
### Documentation: https://docs.packetevents.com
|
||||
|
||||
### JavaDocs: https://javadocs.packetevents.com
|
||||
|
||||
## What's Changed (Summary)
|
||||
|
||||
* Injector bug fix (for Spigot)
|
||||
* WolfVariant issue fixed
|
||||
* Chunk Data error fixed
|
||||
* NBT tag issues fixed
|
||||
* Direction Y/Z axis being swapped fixed
|
||||
* Added WrappedBlockState to constructor of WrapperPlayServerBlockChange
|
||||
|
||||
**View Full Changelog**: https://github.com/retrooper/packetevents/compare/v2.9.4...v2.9.5
|
||||
|
||||
## If you want to support PacketEvents, consider sponsoring us on [GitHub Sponsors](https://github.com/sponsors/retrooper)
|
||||
|
||||
## Maven/Gradle Dependency
|
||||
|
||||
### **Check out**: https://docs.packetevents.com/getting-started
|
||||
|
||||
!!!!! v2.9.4
|
||||
|
||||
# PacketEvents 2.9.4 is out now! 🎉
|
||||
|
||||
This update includes minor bug fixes & minor additions to the API.
|
||||
|
||||
# Brief Announcement 📢⚠️
|
||||
|
||||
### We have our very own website: https://packetevents.com
|
||||
|
||||
### Documentation: https://docs.packetevents.com
|
||||
|
||||
### JavaDocs: https://javadocs.packetevents.com
|
||||
|
||||
## What's Changed (Summary)
|
||||
|
||||
* Added SpigotConversionUtil#getEntityMetadata to retrieve metadata from a Bukkit entity.
|
||||
* Fixed outdated 1.8 Spigot forks from being unable to load on PacketEvents.
|
||||
* Fixed WrapperPlayServerWorldBorder for versions lower than 1.12.
|
||||
|
||||
**View Full Changelog**: https://github.com/retrooper/packetevents/compare/v2.9.3...v2.9.4
|
||||
|
||||
## If you want to support PacketEvents, consider sponsoring us on [GitHub Sponsors](https://github.com/sponsors/retrooper)
|
||||
|
||||
## Maven/Gradle Dependency
|
||||
|
||||
### **Check out**: https://docs.packetevents.com/getting-started
|
||||
|
||||
!!!!! v2.9.3
|
||||
|
||||
# PacketEvents 2.9.3 is out now! 🎉
|
||||
|
||||
This is an update that adds support for Minecraft 1.21.8 server builds.
|
||||
|
||||
# Brief Announcement 📢⚠️
|
||||
|
||||
### We have our very own website: https://packetevents.com
|
||||
|
||||
### Documentation: https://docs.packetevents.com
|
||||
|
||||
### JavaDocs: https://javadocs.packetevents.com
|
||||
|
||||
## What's Changed (Summary)
|
||||
|
||||
* Added support for 1.21.8 Minecraft server builds.
|
||||
|
||||
**View Full Changelog**: https://github.com/retrooper/packetevents/compare/v2.9.2...v2.9.3
|
||||
|
||||
## If you want to support PacketEvents, consider sponsoring us on [GitHub Sponsors](https://github.com/sponsors/retrooper)
|
||||
|
||||
## Maven/Gradle Dependency
|
||||
|
||||
### **Check out**: https://docs.packetevents.com/getting-started
|
||||
|
||||
!!!!! v2.9.2
|
||||
|
||||
# PacketEvents 2.9.2 is out now! 🎉
|
||||
|
||||
This is a patch update that fixes issues with UserLoginEvent (which previously contained null user data) and with importing Adventure serializers.
|
||||
|
||||
# Brief Announcement 📢⚠️
|
||||
|
||||
### We have our very own website: https://packetevents.com
|
||||
|
||||
### Documentation: https://docs.packetevents.com
|
||||
|
||||
### JavaDocs: https://javadocs.packetevents.com
|
||||
|
||||
## What's Changed (Summary)
|
||||
|
||||
* Added support for 1.7.2+ Minecraft protocol (useful for proxies)
|
||||
* Fixed UserLoginEvent. It is now (always) triggered by PlayerJoinEvent to prevent User instances from containing null data.
|
||||
* Fixed importing Adventure serializers.
|
||||
|
||||
**View Full Changelog**: https://github.com/retrooper/packetevents/compare/v2.9.1...v2.9.2
|
||||
|
||||
## If you want to support PacketEvents, consider sponsoring us on [GitHub Sponsors](https://github.com/sponsors/retrooper)
|
||||
|
||||
## Maven/Gradle Dependency
|
||||
|
||||
### **Check out**: https://docs.packetevents.com/getting-started
|
||||
|
||||
!!!!! v2.9.1
|
||||
|
||||
# PacketEvents 2.9.1 is out now! 🎉
|
||||
|
||||
This is a hotfix patch update to fix issues with 2.9.0 release assets. See below for the 2.9.0 changelog.
|
||||
|
||||
### New update now supports Minecraft version 1.21.6 & 1.21.7. We suggest that you update, as numerous bugs have been fixed.
|
||||
|
||||
# Brief Announcement 📢⚠️
|
||||
|
||||
### We have our very own website: https://packetevents.com
|
||||
|
||||
### Documentation: https://docs.packetevents.com
|
||||
|
||||
### JavaDocs: https://javadocs.packetevents.com
|
||||
|
||||
## What's Changed? (Summary)
|
||||
|
||||
* Added 1.21.6 support
|
||||
* Added 1.21.7 support
|
||||
* Bug fixes
|
||||
|
||||
**View Full Changelog**: https://github.com/retrooper/packetevents/compare/v2.8.0...v2.9.1
|
||||
|
||||
## If you want to support PacketEvents, consider sponsoring us on [GitHub Sponsors](https://github.com/sponsors/retrooper)
|
||||
|
||||
## Maven/Gradle Dependency
|
||||
|
||||
### **Check out**: https://docs.packetevents.com/getting-started
|
||||
|
||||
!!!!! v2.9.0
|
||||
|
||||
# PacketEvents 2.9.0 is out now! 🎉
|
||||
|
||||
### New update now supports Minecraft version 1.21.6 & 1.21.7. We suggest that you update, as numerous bugs have been fixed.
|
||||
|
||||
# Brief Announcement 📢⚠️
|
||||
|
||||
### We have our very own website: https://packetevents.com
|
||||
|
||||
### Documentation: https://docs.packetevents.com
|
||||
|
||||
### JavaDocs: https://javadocs.packetevents.com
|
||||
|
||||
## What's Changed? (Summary)
|
||||
|
||||
* Added 1.21.6 support
|
||||
* Added 1.21.7 support
|
||||
* Bug fixes
|
||||
|
||||
**View Full Changelog**: https://github.com/retrooper/packetevents/compare/v2.8.0...v2.9.0
|
||||
|
||||
## If you want to support PacketEvents, consider sponsoring us on [GitHub Sponsors](https://github.com/sponsors/retrooper)
|
||||
|
||||
## Maven/Gradle Dependency
|
||||
|
||||
### **Check out**: https://docs.packetevents.com/getting-started
|
||||
|
||||
!!!!! v2.8.0
|
||||
|
||||
# PacketEvents 2.8.0 is out now! 🎉
|
||||
|
||||
### New update now supports Minecraft version 1.21.5. Please update, as numerous bugs have been fixed.
|
||||
|
||||
# Brief Announcement 📢⚠️
|
||||
|
||||
### We have our very own website: https://packetevents.com
|
||||
|
||||
### Documentation: https://docs.packetevents.com
|
||||
|
||||
### JavaDocs: https://javadocs.packetevents.com
|
||||
|
||||
## What's Changed? (Summary)
|
||||
|
||||
* Added 1.21.5 support
|
||||
* Various bugs fixed
|
||||
|
||||
**View Full Changelog**: https://github.com/retrooper/packetevents/compare/v2.7.0...v2.8.0
|
||||
|
||||
## Contributors 🏅
|
||||
|
||||
This update wouldn't be possible without these contributors ❤️: @booky10, @Axionize, @Bram1903, @ManInMyVan, @ytnoos,
|
||||
@AoElite, @HaHaWTH, @divinepablo, @scienziatopazzo, @bridgelol, @MachineBreaker, @Luuzzi, @Beaness, @Rubenicos, @Loyisa
|
||||
|
||||
## New Contributors
|
||||
|
||||
* @HaHaWTH made their first contribution in https://github.com/retrooper/packetevents/pull/1097
|
||||
* @divinepablo made their first contribution in https://github.com/retrooper/packetevents/pull/1098
|
||||
* @scienziatopazzo made their first contribution in https://github.com/retrooper/packetevents/pull/1105
|
||||
* @bridgelol made their first contribution in https://github.com/retrooper/packetevents/pull/1199
|
||||
* @Luuzzi made their first contribution in https://github.com/retrooper/packetevents/pull/1197
|
||||
* @Beaness made their first contribution in https://github.com/retrooper/packetevents/pull/1212
|
||||
* @Rubenicos made their first contribution in https://github.com/retrooper/packetevents/pull/1162
|
||||
* @Loyisa made their first contribution in https://github.com/retrooper/packetevents/pull/1220
|
||||
|
||||
## If you want to support PacketEvents, consider sponsoring us on [GitHub Sponsors](https://github.com/sponsors/retrooper)
|
||||
|
||||
## Maven/Gradle Dependency
|
||||
|
||||
### **Check out**: https://docs.packetevents.com/getting-started
|
||||
|
||||
!!!!! v2.7.0
|
||||
|
||||
# PacketEvents v2.7.0 is out now! 🎉
|
||||
|
||||
### New update with support of the latest Minecraft version. In addition to that, countless bugs were fixed.
|
||||
|
||||
# Brief Announcement 📢⚠️
|
||||
|
||||
### We have our own website: https://packetevents.com
|
||||
|
||||
### Documentation: https://docs.packetevents.com
|
||||
|
||||
### JavaDocs: https://javadocs.packetevents.com
|
||||
|
||||
## What's Changed? (Summary)
|
||||
|
||||
* Added 1.21.4 support
|
||||
* Fix: Potion contents item component for 1.21.2/1.21.3
|
||||
* Fix: NPC objects to have unique server team names
|
||||
* Add missing ServerVersion#V_1_9_1
|
||||
* Validation checks added for window click type
|
||||
|
||||
**Full Changelog**: https://github.com/retrooper/packetevents/compare/v2.6.0...v2.7.0
|
||||
|
||||
## New Contributors
|
||||
|
||||
* @Axionize made their first contribution in https://github.com/retrooper/packetevents/pull/1048
|
||||
* @ShreyasAyyengar made their first contribution in https://github.com/retrooper/packetevents/pull/1044
|
||||
* @mfnalex made their first contribution in https://github.com/retrooper/packetevents/pull/1076
|
||||
|
||||
## Contributors 🏅
|
||||
|
||||
This update wouldn't be possible without these contributors ❤️: @booky10, @rafi67000, @ShreyasAyyengar, @AoElite,
|
||||
@Tecnio, @Axionize, @mfnalex
|
||||
|
||||
### If you want to support PacketEvents, and any upcoming events we plan for the future, consider sponsoring us on [GitHub Sponsors](https://github.com/sponsors/retrooper)
|
||||
|
||||
## Maven/Gradle Dependency
|
||||
|
||||
### **Check out**: https://docs.packetevents.com/getting-started
|
||||
|
||||
!!!!! v2.6.0
|
||||
|
||||
# PacketEvents v2.6.0 is out now! 🎉
|
||||
|
||||
### New update with support of new platforms & the latest Minecraft version. In addition to that, countless bugs were fixed.
|
||||
|
||||
# Brief Announcement 📢⚠️
|
||||
|
||||
### We have our own website: https://packetevents.com
|
||||
|
||||
### Documentation: https://docs.packetevents.com
|
||||
|
||||
### JavaDocs: https://javadocs.packetevents.com
|
||||
|
||||
## What's Changed? (Summary)
|
||||
|
||||
* 1.21.2 and 1.21.3 Minecraft support
|
||||
* Sponge support added
|
||||
* Fabric support added (also server-side)
|
||||
* Utilizing the proper bStats API
|
||||
* Registry element issues fixed
|
||||
* Mappings issues fixed
|
||||
* AdvancedSlimePaper issues fixed
|
||||
* BungeeCord issues fixed
|
||||
|
||||
### **Full Changelog**: https://github.com/retrooper/packetevents/compare/v2.5.0...v2.6.0
|
||||
|
||||
## Contributors 🏅
|
||||
|
||||
This update wouldn't be possible without these contributors ❤️: @booky10, @ManInMyVan, @SamB440, @rafi67000, @Bram1903,
|
||||
@AbhigyaKrishna
|
||||
|
||||
### If you want to support PacketEvents, and any upcoming events we plan for the future, consider sponsoring us on [GitHub Sponsors](https://github.com/sponsors/retrooper)
|
||||
|
||||
## Maven/Gradle Dependency
|
||||
|
||||
### **Check out**: https://docs.packetevents.com/getting-started
|
||||
|
||||
!!!!!
|
||||
@@ -14,8 +14,8 @@
|
||||
- [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)
|
||||
- [GitHub](https://github.com/retrooper/packetevents/releases/)
|
||||
- [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)
|
||||
@@ -28,8 +28,6 @@
|
||||
|
||||
<a href="https://www.ej-technologies.com"><img src="https://www.ej-technologies.com/images/product_banners/jprofiler_small.png"><br>
|
||||
|
||||
<a href="https://github.com/radstevee"><img src="https://github.com/radstevee.png" width="50px" alt="radstevee"/></a><br>
|
||||
|
||||
<h3>Credits</h3>
|
||||
|
||||
<i>Here are some projects that we are heavily inspired by, thus we have integrated</i>\
|
||||
|
||||
@@ -32,6 +32,7 @@ import com.github.retrooper.packetevents.protocol.packettype.PacketTypeCommon;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.player.User;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -44,7 +45,7 @@ public abstract class ProtocolPacketEvent extends PacketEvent implements PlayerE
|
||||
private final Object channel;
|
||||
private final ConnectionState connectionState;
|
||||
private final User user;
|
||||
private final Object player;
|
||||
private Object player;
|
||||
private Object byteBuf;
|
||||
private final int packetID;
|
||||
private final PacketTypeCommon packetType;
|
||||
@@ -145,6 +146,12 @@ public abstract class ProtocolPacketEvent extends PacketEvent implements PlayerE
|
||||
return (T) player;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@ApiStatus.Internal
|
||||
public void setPlayer(Object player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the connection state this packet has been sent/received in.
|
||||
*/
|
||||
|
||||
+5
@@ -2,4 +2,9 @@ package com.github.retrooper.packetevents.exception;
|
||||
|
||||
public class CancelPacketException extends RuntimeException {
|
||||
public static final CancelPacketException INSTANCE = new CancelPacketException();
|
||||
|
||||
@Override
|
||||
public synchronized Throwable fillInStackTrace() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
+8
-5
@@ -37,7 +37,9 @@ import com.github.retrooper.packetevents.wrapper.handshaking.client.WrapperHands
|
||||
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 org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public class InternalPacketListener extends PacketListenerAbstract {
|
||||
|
||||
public InternalPacketListener() {
|
||||
@@ -68,7 +70,9 @@ public class InternalPacketListener extends PacketListenerAbstract {
|
||||
PacketEvents.getAPI().getProtocolManager().setChannel(profile.getUUID(), channel);
|
||||
}
|
||||
|
||||
PacketEvents.getAPI().getLogManager().debug("Mapped player UUID with their channel.");
|
||||
if (PacketEvents.getAPI().getLogManager().isDebug()) {
|
||||
PacketEvents.getAPI().getLogManager().debug("Mapped player UUID with their channel " + profile.getUUID() + " " + channel);
|
||||
}
|
||||
|
||||
// Switch the user's connection state to new state, but the variable event.getConnectionState() remains LOGIN
|
||||
// We switch user state immediately to remain in sync with vanilla, allowing you to encode packets immediately
|
||||
@@ -86,12 +90,11 @@ public class InternalPacketListener extends PacketListenerAbstract {
|
||||
WrapperConfigServerRegistryData packet = new WrapperConfigServerRegistryData(event);
|
||||
|
||||
if (packet.getElements() != null) { // 1.20.2 to 1.20.5
|
||||
SynchronizedRegistriesHandler.handleRegistry(user, packet.getServerVersion().toClientVersion(),
|
||||
SynchronizedRegistriesHandler.handleRegistry(user, packet,
|
||||
packet.getRegistryKey(), packet.getElements());
|
||||
}
|
||||
if (packet.getRegistryData() != null) { // since 1.20.5
|
||||
SynchronizedRegistriesHandler.handleLegacyRegistries(user, packet.getServerVersion()
|
||||
.toClientVersion(), packet.getRegistryData());
|
||||
SynchronizedRegistriesHandler.handleLegacyRegistries(user, packet, packet.getRegistryData());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,7 +104,7 @@ public class InternalPacketListener extends PacketListenerAbstract {
|
||||
user.setEntityId(joinGame.getEntityId());
|
||||
|
||||
if (joinGame.getDimensionCodec() != null) { // 1.16 to 1.20.1
|
||||
SynchronizedRegistriesHandler.handleLegacyRegistries(user, joinGame.getServerVersion().toClientVersion(),
|
||||
SynchronizedRegistriesHandler.handleLegacyRegistries(user, joinGame,
|
||||
joinGame.getDimensionCodec());
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -32,7 +32,8 @@ import org.jetbrains.annotations.NotNull;
|
||||
*/
|
||||
public enum ServerVersion {
|
||||
//TODO Rename to MinecraftVersion?
|
||||
V_1_7_10(5),
|
||||
V_1_7_2(4), V_1_7_4(4), V_1_7_5(4),
|
||||
V_1_7_6(5), V_1_7_7(5), V_1_7_8(5), V_1_7_9(5), 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_1(108), V_1_9_2(109), V_1_9_4(110),
|
||||
//1.10 and 1.10.1 are redundant
|
||||
@@ -50,7 +51,7 @@ public enum ServerVersion {
|
||||
//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),
|
||||
//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), V_1_21_5(770),
|
||||
V_1_21(767), V_1_21_1(767), V_1_21_2(768), V_1_21_3(768), V_1_21_4(769), V_1_21_5(770), V_1_21_6(771), V_1_21_7(772), V_1_21_8(772),
|
||||
//TODO UPDATE Add server version constant
|
||||
ERROR(-1, true);
|
||||
|
||||
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.advancements;
|
||||
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
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;
|
||||
|
||||
public class Advancement {
|
||||
|
||||
private @Nullable ResourceLocation parent;
|
||||
private @Nullable AdvancementDisplay display;
|
||||
/**
|
||||
* Removed with 1.20.2
|
||||
*/
|
||||
private List<String> criteria;
|
||||
private List<List<String>> requirements;
|
||||
/**
|
||||
* Added with 1.20
|
||||
*/
|
||||
private boolean sendsTelemetryData;
|
||||
|
||||
public Advancement(
|
||||
@Nullable ResourceLocation parent,
|
||||
@Nullable AdvancementDisplay display,
|
||||
List<List<String>> requirements,
|
||||
boolean sendsTelemetryData
|
||||
) {
|
||||
this(parent, display, Collections.emptyList(), requirements, sendsTelemetryData);
|
||||
}
|
||||
|
||||
@ApiStatus.Obsolete
|
||||
public Advancement(
|
||||
@Nullable ResourceLocation parent,
|
||||
@Nullable AdvancementDisplay display,
|
||||
List<String> criteria,
|
||||
List<List<String>> requirements,
|
||||
boolean sendsTelemetryData
|
||||
) {
|
||||
this.parent = parent;
|
||||
this.display = display;
|
||||
this.criteria = criteria;
|
||||
this.requirements = requirements;
|
||||
this.sendsTelemetryData = sendsTelemetryData;
|
||||
}
|
||||
|
||||
public static Advancement read(PacketWrapper<?> wrapper) {
|
||||
ResourceLocation parentId = wrapper.readOptional(ResourceLocation::read);
|
||||
AdvancementDisplay display = wrapper.readOptional(AdvancementDisplay::read);
|
||||
List<String> criteria = wrapper.getServerVersion().isOlderThan(ServerVersion.V_1_20_2)
|
||||
? wrapper.readList(PacketWrapper::readString) : null;
|
||||
List<List<String>> requirements = wrapper.readList(
|
||||
ew -> wrapper.readList(PacketWrapper::readString));
|
||||
boolean sendsTelemetryData = wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_20)
|
||||
&& wrapper.readBoolean();
|
||||
return new Advancement(parentId, display, criteria, requirements, sendsTelemetryData);
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, Advancement advancement) {
|
||||
wrapper.writeOptional(advancement.parent, ResourceLocation::write);
|
||||
wrapper.writeOptional(advancement.display, AdvancementDisplay::write);
|
||||
if (wrapper.getServerVersion().isOlderThan(ServerVersion.V_1_20_2)) {
|
||||
wrapper.writeList(advancement.criteria, PacketWrapper::writeString);
|
||||
}
|
||||
wrapper.writeList(advancement.getRequirements(), (ew, anyList) ->
|
||||
ew.writeList(anyList, PacketWrapper::writeString));
|
||||
if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_20)) {
|
||||
wrapper.writeBoolean(advancement.sendsTelemetryData);
|
||||
}
|
||||
}
|
||||
|
||||
public @Nullable ResourceLocation getParent() {
|
||||
return this.parent;
|
||||
}
|
||||
|
||||
public void setParent(@Nullable ResourceLocation parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public @Nullable AdvancementDisplay getDisplay() {
|
||||
return this.display;
|
||||
}
|
||||
|
||||
public void setDisplay(@Nullable AdvancementDisplay display) {
|
||||
this.display = display;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removed with 1.20.2
|
||||
*/
|
||||
public List<String> getCriteria() {
|
||||
return this.criteria;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removed with 1.20.2
|
||||
*/
|
||||
public void setCriteria(List<String> criteria) {
|
||||
this.criteria = criteria;
|
||||
}
|
||||
|
||||
public List<List<String>> getRequirements() {
|
||||
return this.requirements;
|
||||
}
|
||||
|
||||
public void setRequirements(List<List<String>> requirements) {
|
||||
this.requirements = requirements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Added with 1.20
|
||||
*/
|
||||
public boolean isSendsTelemetryData() {
|
||||
return this.sendsTelemetryData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Added with 1.20
|
||||
*/
|
||||
public void setSendsTelemetryData(boolean sendsTelemetryData) {
|
||||
this.sendsTelemetryData = sendsTelemetryData;
|
||||
}
|
||||
}
|
||||
+168
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.advancements;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public final class AdvancementDisplay {
|
||||
|
||||
public static final int FLAG_HAS_BACKGROUND = 0b001;
|
||||
public static final int FLAG_SHOW_TOAST = 0b010;
|
||||
public static final int FLAG_HIDDEN = 0b100;
|
||||
|
||||
private Component title;
|
||||
private Component description;
|
||||
private ItemStack icon;
|
||||
private AdvancementType type;
|
||||
private boolean showToast;
|
||||
private boolean hidden;
|
||||
private @Nullable ResourceLocation background;
|
||||
private float x;
|
||||
private float y;
|
||||
|
||||
public AdvancementDisplay(Component title, Component description, ItemStack icon, AdvancementType type, @Nullable ResourceLocation background, boolean showToast,
|
||||
boolean hidden, float x, float y) {
|
||||
this.title = title;
|
||||
this.description = description;
|
||||
this.icon = icon;
|
||||
this.type = type;
|
||||
this.showToast = showToast;
|
||||
this.hidden = hidden;
|
||||
this.background = background;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public static AdvancementDisplay read(PacketWrapper<?> wrapper) {
|
||||
Component title = wrapper.readComponent();
|
||||
Component description = wrapper.readComponent();
|
||||
ItemStack icon = wrapper.readItemStack();
|
||||
AdvancementType type = wrapper.readEnum(AdvancementType.class);
|
||||
int flags = wrapper.readInt();
|
||||
ResourceLocation background = (flags & FLAG_HAS_BACKGROUND) != 0 ? ResourceLocation.read(wrapper) : null;
|
||||
boolean showToast = (flags & FLAG_SHOW_TOAST) != 0;
|
||||
boolean hidden = (flags & FLAG_HIDDEN) != 0;
|
||||
float x = wrapper.readFloat();
|
||||
float y = wrapper.readFloat();
|
||||
return new AdvancementDisplay(title, description, icon, type, background, showToast, hidden, x, y);
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, AdvancementDisplay display) {
|
||||
wrapper.writeComponent(display.title);
|
||||
wrapper.writeComponent(display.description);
|
||||
wrapper.writeItemStack(display.icon);
|
||||
wrapper.writeEnum(display.type);
|
||||
wrapper.writeInt(display.packFlags());
|
||||
if (display.background != null) {
|
||||
ResourceLocation.write(wrapper, display.background);
|
||||
}
|
||||
wrapper.writeFloat(display.x);
|
||||
wrapper.writeFloat(display.y);
|
||||
}
|
||||
|
||||
public int packFlags() {
|
||||
int flags = 0;
|
||||
if (this.background != null) {
|
||||
flags |= FLAG_HAS_BACKGROUND;
|
||||
}
|
||||
if (this.showToast) {
|
||||
flags |= FLAG_SHOW_TOAST;
|
||||
}
|
||||
if (this.hidden) {
|
||||
flags |= FLAG_HIDDEN;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
public Component getTitle() {
|
||||
return this.title;
|
||||
}
|
||||
|
||||
public void setTitle(Component title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public Component getDescription() {
|
||||
return this.description;
|
||||
}
|
||||
|
||||
public void setDescription(Component description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public ItemStack getIcon() {
|
||||
return this.icon;
|
||||
}
|
||||
|
||||
public void setIcon(ItemStack icon) {
|
||||
this.icon = icon;
|
||||
}
|
||||
|
||||
public AdvancementType getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public void setType(AdvancementType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public boolean isShowToast() {
|
||||
return this.showToast;
|
||||
}
|
||||
|
||||
public void setShowToast(boolean showToast) {
|
||||
this.showToast = showToast;
|
||||
}
|
||||
|
||||
public boolean isHidden() {
|
||||
return this.hidden;
|
||||
}
|
||||
|
||||
public void setHidden(boolean hidden) {
|
||||
this.hidden = hidden;
|
||||
}
|
||||
|
||||
public @Nullable ResourceLocation getBackground() {
|
||||
return this.background;
|
||||
}
|
||||
|
||||
public void setBackground(@Nullable ResourceLocation background) {
|
||||
this.background = background;
|
||||
}
|
||||
|
||||
public float getX() {
|
||||
return this.x;
|
||||
}
|
||||
|
||||
public void setX(float x) {
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
public float getY() {
|
||||
return this.y;
|
||||
}
|
||||
|
||||
public void setY(float y) {
|
||||
this.y = y;
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.advancements;
|
||||
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
|
||||
public final class AdvancementHolder {
|
||||
|
||||
private ResourceLocation identifier;
|
||||
private Advancement advancement;
|
||||
|
||||
public AdvancementHolder(ResourceLocation identifier, Advancement advancement) {
|
||||
this.identifier = identifier;
|
||||
this.advancement = advancement;
|
||||
}
|
||||
|
||||
public static AdvancementHolder read(PacketWrapper<?> wrapper) {
|
||||
ResourceLocation identifier = wrapper.readIdentifier();
|
||||
Advancement advancement = Advancement.read(wrapper);
|
||||
return new AdvancementHolder(identifier, advancement);
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, AdvancementHolder holder) {
|
||||
wrapper.writeIdentifier(holder.identifier);
|
||||
Advancement.write(wrapper, holder.advancement);
|
||||
}
|
||||
|
||||
public ResourceLocation getIdentifier() {
|
||||
return this.identifier;
|
||||
}
|
||||
|
||||
public void setIdentifier(ResourceLocation identifier) {
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public Advancement getAdvancement() {
|
||||
return this.advancement;
|
||||
}
|
||||
|
||||
public void setAdvancement(Advancement advancement) {
|
||||
this.advancement = advancement;
|
||||
}
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.advancements;
|
||||
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public final class AdvancementProgress {
|
||||
|
||||
private Map<String, CriterionProgress> criteria;
|
||||
|
||||
public AdvancementProgress(Map<String, CriterionProgress> criteria) {
|
||||
this.criteria = criteria;
|
||||
}
|
||||
|
||||
public static AdvancementProgress read(PacketWrapper<?> wrapper) {
|
||||
Map<String, CriterionProgress> criteria = wrapper.readMap(PacketWrapper::readString, CriterionProgress::read);
|
||||
return new AdvancementProgress(criteria);
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, AdvancementProgress progress) {
|
||||
wrapper.writeMap(progress.getCriteria(), PacketWrapper::writeString, CriterionProgress::write);
|
||||
}
|
||||
|
||||
public Map<String, CriterionProgress> getCriteria() {
|
||||
return this.criteria;
|
||||
}
|
||||
|
||||
public void setCriteria(Map<String, CriterionProgress> criteria) {
|
||||
this.criteria = criteria;
|
||||
}
|
||||
|
||||
public static final class CriterionProgress {
|
||||
|
||||
private @Nullable Long obtainedTimestamp;
|
||||
|
||||
public CriterionProgress(@Nullable Long obtainedTimestamp) {
|
||||
this.obtainedTimestamp = obtainedTimestamp;
|
||||
}
|
||||
|
||||
public static CriterionProgress read(PacketWrapper<?> wrapper) {
|
||||
return new CriterionProgress(wrapper.readOptional(PacketWrapper::readLong));
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, CriterionProgress progress) {
|
||||
wrapper.writeOptional(progress.obtainedTimestamp, PacketWrapper::writeLong);
|
||||
}
|
||||
|
||||
public @Nullable Long getObtainedTimestamp() {
|
||||
return this.obtainedTimestamp;
|
||||
}
|
||||
|
||||
public void setObtainedTimestamp(@Nullable Long obtainedTimestamp) {
|
||||
this.obtainedTimestamp = obtainedTimestamp;
|
||||
}
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.advancements;
|
||||
|
||||
public enum AdvancementType {
|
||||
|
||||
TASK,
|
||||
CHALLENGE,
|
||||
GOAL,
|
||||
;
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.wrapper.PacketWrapper;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public interface AttributeDisplay {
|
||||
|
||||
static AttributeDisplay read(PacketWrapper<?> wrapper) {
|
||||
AttributeDisplayType<?> type = wrapper.readMappedEntity(AttributeDisplayTypes.getRegistry());
|
||||
return type.read(wrapper);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked") // not unchecked
|
||||
static void write(PacketWrapper<?> wrapper, AttributeDisplay display) {
|
||||
wrapper.writeMappedEntity(display.getType());
|
||||
((AttributeDisplayType<? super AttributeDisplay>) display.getType()).write(wrapper, display);
|
||||
}
|
||||
|
||||
AttributeDisplayType<?> getType();
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.MappedEntity;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public interface AttributeDisplayType<T extends AttributeDisplay> extends MappedEntity {
|
||||
|
||||
T read(PacketWrapper<?> wrapper);
|
||||
|
||||
void write(PacketWrapper<?> wrapper, T display);
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.util.mappings.VersionedRegistry;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public final class AttributeDisplayTypes {
|
||||
|
||||
private static final VersionedRegistry<AttributeDisplayType<?>> REGISTRY = new VersionedRegistry<>("attribute_display_type");
|
||||
|
||||
private AttributeDisplayTypes() {
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static <T extends AttributeDisplay> AttributeDisplayType<T> define(
|
||||
String name, PacketWrapper.Reader<T> reader, PacketWrapper.Writer<T> writer
|
||||
) {
|
||||
return REGISTRY.define(name, data ->
|
||||
new StaticAttributeDisplayType<>(data, reader, writer));
|
||||
}
|
||||
|
||||
public static VersionedRegistry<AttributeDisplayType<?>> getRegistry() {
|
||||
return REGISTRY;
|
||||
}
|
||||
|
||||
public static final AttributeDisplayType<DefaultAttributeDisplay> DEFAULT = define("default",
|
||||
DefaultAttributeDisplay::read, DefaultAttributeDisplay::write);
|
||||
public static final AttributeDisplayType<HiddenAttributeDisplay> HIDDEN = define("hidden",
|
||||
HiddenAttributeDisplay::read, HiddenAttributeDisplay::write);
|
||||
public static final AttributeDisplayType<OverrideAttributeDisplay> OVERRIDE = define("override",
|
||||
OverrideAttributeDisplay::read, OverrideAttributeDisplay::write);
|
||||
|
||||
static {
|
||||
REGISTRY.unloadMappings();
|
||||
}
|
||||
}
|
||||
+16
@@ -187,6 +187,22 @@ public final class Attributes {
|
||||
public static final Attribute TEMPT_RANGE = define("tempt_range",
|
||||
null, 10d, 0d, 2048d);
|
||||
|
||||
/**
|
||||
* Added with 1.21.6
|
||||
*/
|
||||
public static final Attribute CAMERA_DISTANCE = define("camera_distance",
|
||||
null, 4d, 0d, 32d);
|
||||
/**
|
||||
* Added with 1.21.6
|
||||
*/
|
||||
public static final Attribute WAYPOINT_TRANSMIT_RANGE = define("waypoint_transmit_range",
|
||||
null, 0d, 0d, 60_000_000d);
|
||||
/**
|
||||
* Added with 1.21.6
|
||||
*/
|
||||
public static final Attribute WAYPOINT_RECEIVE_RANGE = define("waypoint_receive_range",
|
||||
null, 0d, 0d, 60_000_000d);
|
||||
|
||||
/**
|
||||
* This attribute has been renamed in 1.20.5 to {@link #JUMP_STRENGTH}
|
||||
*/
|
||||
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.wrapper.PacketWrapper;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class DefaultAttributeDisplay implements AttributeDisplay {
|
||||
|
||||
public static final DefaultAttributeDisplay INSTANCE = new DefaultAttributeDisplay();
|
||||
|
||||
private DefaultAttributeDisplay() {
|
||||
}
|
||||
|
||||
public static DefaultAttributeDisplay read(PacketWrapper<?> wrapper) {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, DefaultAttributeDisplay display) {
|
||||
// NO-OP
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributeDisplayType<?> getType() {
|
||||
return AttributeDisplayTypes.DEFAULT;
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.wrapper.PacketWrapper;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class HiddenAttributeDisplay implements AttributeDisplay {
|
||||
|
||||
public static final HiddenAttributeDisplay INSTANCE = new HiddenAttributeDisplay();
|
||||
|
||||
private HiddenAttributeDisplay() {
|
||||
}
|
||||
|
||||
public static HiddenAttributeDisplay read(PacketWrapper<?> wrapper) {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, HiddenAttributeDisplay display) {
|
||||
// NO-OP
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributeDisplayType<?> getType() {
|
||||
return AttributeDisplayTypes.HIDDEN;
|
||||
}
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.wrapper.PacketWrapper;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@NullMarked
|
||||
public class OverrideAttributeDisplay implements AttributeDisplay {
|
||||
|
||||
private final Component component;
|
||||
|
||||
public OverrideAttributeDisplay(Component component) {
|
||||
this.component = component;
|
||||
}
|
||||
|
||||
public static OverrideAttributeDisplay read(PacketWrapper<?> wrapper) {
|
||||
return new OverrideAttributeDisplay(wrapper.readComponent());
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, OverrideAttributeDisplay display) {
|
||||
wrapper.writeComponent(display.component);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributeDisplayType<?> getType() {
|
||||
return AttributeDisplayTypes.OVERRIDE;
|
||||
}
|
||||
|
||||
public Component getComponent() {
|
||||
return this.component;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof OverrideAttributeDisplay)) return false;
|
||||
OverrideAttributeDisplay that = (OverrideAttributeDisplay) obj;
|
||||
return this.component.equals(that.component);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(this.component);
|
||||
}
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.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.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class StaticAttributeDisplayType<T extends AttributeDisplay> extends AbstractMappedEntity implements AttributeDisplayType<T> {
|
||||
|
||||
private final Reader<T> reader;
|
||||
private final Writer<T> writer;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public StaticAttributeDisplayType(@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 display) {
|
||||
this.writer.accept(wrapper, display);
|
||||
}
|
||||
}
|
||||
+13
-3
@@ -72,7 +72,12 @@ public class ChatTypeDecoration {
|
||||
wrapper.writeStyle(decoration.style);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static ChatTypeDecoration decode(NBT nbt, ClientVersion version) {
|
||||
return decode(nbt, PacketWrapper.createDummyWrapper(version));
|
||||
}
|
||||
|
||||
public static ChatTypeDecoration decode(NBT nbt, PacketWrapper<?> wrapper) {
|
||||
NBTCompound compound = (NBTCompound) nbt;
|
||||
String translationKey = compound.getStringTagValueOrThrow("translation_key");
|
||||
NBT paramsTag = compound.getTagOrThrow("parameters");
|
||||
@@ -90,11 +95,16 @@ public class ChatTypeDecoration {
|
||||
}
|
||||
NBTCompound styleTag = compound.getCompoundTagOrNull("style");
|
||||
Style style = styleTag == null ? empty() :
|
||||
AdventureSerializer.serializer(version).nbt().deserializeStyle(styleTag);
|
||||
wrapper.getSerializers().nbt().deserializeStyle(styleTag, wrapper);
|
||||
return new ChatTypeDecoration(translationKey, params, style);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static NBT encode(ChatTypeDecoration decoration, ClientVersion version) {
|
||||
return encode(decoration, PacketWrapper.createDummyWrapper(version));
|
||||
}
|
||||
|
||||
public static NBT encode(ChatTypeDecoration decoration, PacketWrapper<?> wrapper) {
|
||||
NBTList<NBTString> paramsTag = NBTList.createStringList();
|
||||
for (Parameter param : decoration.parameters) {
|
||||
paramsTag.addTag(new NBTString(param.getId()));
|
||||
@@ -104,8 +114,8 @@ public class ChatTypeDecoration {
|
||||
compound.setTag("translation_key", new NBTString(decoration.translationKey));
|
||||
compound.setTag("parameters", paramsTag);
|
||||
if (!decoration.style.isEmpty()) {
|
||||
compound.setTag("style", AdventureSerializer.serializer(version)
|
||||
.nbt().serializeStyle(decoration.style));
|
||||
compound.setTag("style", wrapper.getSerializers()
|
||||
.nbt().serializeStyle(decoration.style, wrapper));
|
||||
}
|
||||
return compound;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,20 @@ import java.util.Optional;
|
||||
|
||||
public class Node {
|
||||
|
||||
public static final byte TYPE_MASK = 0b11;
|
||||
public static final byte TYPE_ROOT = 0b00;
|
||||
public static final byte TYPE_LITERAL = 0b01;
|
||||
public static final byte TYPE_ARGUMENT = 0b10;
|
||||
|
||||
public static final byte FLAG_MASK = ~TYPE_MASK;
|
||||
public static final byte FLAG_EXECUTABLE = 0b000100;
|
||||
public static final byte FLAG_REDIRECT = 0b001000;
|
||||
public static final byte FLAG_CUSTOM_SUGGESTIONS = 0b010000;
|
||||
/**
|
||||
* Added with 1.21.6
|
||||
*/
|
||||
public static final byte FLAG_RESTRICTED = 0b100000;
|
||||
|
||||
private byte flags;
|
||||
private List<Integer> children;
|
||||
private int redirectNodeIndex;
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.github.retrooper.packetevents.util.mappings.VersionedRegistry;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -36,9 +37,10 @@ import java.util.Optional;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
@NullMarked
|
||||
public final class Parsers {
|
||||
|
||||
private static final VersionedRegistry<Parser> REGISTRY = new VersionedRegistry<>("argument_type");
|
||||
private static final VersionedRegistry<Parser> REGISTRY = new VersionedRegistry<>("command_argument_type");
|
||||
|
||||
private Parsers() {
|
||||
}
|
||||
@@ -218,6 +220,15 @@ public final class Parsers {
|
||||
(wrapper, value) -> wrapper.writeIdentifier((ResourceLocation) value.get(0))
|
||||
);
|
||||
|
||||
/**
|
||||
* Added with 1.21.6
|
||||
*/
|
||||
public static final Parser HEX_COLOR = define("hex_color", null, null);
|
||||
/**
|
||||
* Added with 1.21.6
|
||||
*/
|
||||
public static final Parser DIALOG = define("dialog", null, null);
|
||||
|
||||
static {
|
||||
REGISTRY.unloadMappings();
|
||||
}
|
||||
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.chat.clickevent;
|
||||
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTInt;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class ChangePageClickEvent implements ClickEvent {
|
||||
|
||||
private final int page;
|
||||
|
||||
@ApiStatus.Obsolete
|
||||
public ChangePageClickEvent(String page) {
|
||||
this(Integer.parseInt(page));
|
||||
}
|
||||
|
||||
public ChangePageClickEvent(int page) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
public static ChangePageClickEvent decode(NBTCompound compound, PacketWrapper<?> wrapper) {
|
||||
int page = wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_5)
|
||||
? compound.getNumberTagValueOrThrow("page").intValue()
|
||||
: Integer.parseInt(compound.getStringTagValueOrThrow("value"));
|
||||
return new ChangePageClickEvent(page);
|
||||
}
|
||||
|
||||
public static void encode(NBTCompound compound, PacketWrapper<?> wrapper, ChangePageClickEvent clickEvent) {
|
||||
if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_5)) {
|
||||
compound.setTag("page", new NBTInt(clickEvent.page));
|
||||
} else {
|
||||
compound.setTag("value", new NBTString(Integer.toString(clickEvent.page)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClickEventAction<?> getAction() {
|
||||
return ClickEventActions.CHANGE_PAGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public net.kyori.adventure.text.event.ClickEvent asAdventure() {
|
||||
return net.kyori.adventure.text.event.ClickEvent.changePage(this.page);
|
||||
}
|
||||
|
||||
public int getPage() {
|
||||
return this.page;
|
||||
}
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.chat.clickevent;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.dialog.Dialog;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTEnd;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.util.adventure.NbtTagHolder;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import net.kyori.adventure.text.event.ClickEvent.Payload;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public interface ClickEvent {
|
||||
|
||||
static ClickEvent decode(NBTCompound compound, PacketWrapper<?> wrapper) {
|
||||
String actionName = compound.getStringTagValueOrThrow("action");
|
||||
ClickEventAction<?> action = ClickEventActions.getRegistry().getByNameOrThrow(actionName);
|
||||
return action.decode(compound, wrapper);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked") // not unchecked
|
||||
static void encode(NBTCompound compound, PacketWrapper<?> wrapper, ClickEvent clickEvent) {
|
||||
compound.set("action", clickEvent.getAction().getName(), ResourceLocation::encode, wrapper);
|
||||
((ClickEventAction<? super ClickEvent>) clickEvent.getAction()).encode(compound, wrapper, clickEvent);
|
||||
}
|
||||
|
||||
ClickEventAction<?> getAction();
|
||||
|
||||
static ClickEvent fromAdventure(net.kyori.adventure.text.event.ClickEvent clickEvent) {
|
||||
switch (clickEvent.action()) {
|
||||
case OPEN_URL:
|
||||
return new OpenUrlClickEvent(clickEvent.value());
|
||||
case OPEN_FILE:
|
||||
return new OpenFileClickEvent(clickEvent.value());
|
||||
case RUN_COMMAND:
|
||||
return new RunCommandClickEvent(clickEvent.value());
|
||||
case SUGGEST_COMMAND:
|
||||
return new SuggestCommandClickEvent(clickEvent.value());
|
||||
case CHANGE_PAGE:
|
||||
return new ChangePageClickEvent(clickEvent.value());
|
||||
case COPY_TO_CLIPBOARD:
|
||||
return new CopyToClipboardClickEvent(clickEvent.value());
|
||||
case SHOW_DIALOG:
|
||||
return new ShowDialogClickEvent((Dialog) ((Payload.Dialog) clickEvent.payload()).dialog());
|
||||
case CUSTOM:
|
||||
Payload.Custom payload = (Payload.Custom) clickEvent.payload();
|
||||
NbtTagHolder nbtTag = (NbtTagHolder) payload.nbt();
|
||||
return new CustomClickEvent(
|
||||
new ResourceLocation(payload.key()),
|
||||
nbtTag.getTag() instanceof NBTEnd ? null : nbtTag.getTag()
|
||||
);
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unsupported clickevent: " + clickEvent);
|
||||
}
|
||||
}
|
||||
|
||||
net.kyori.adventure.text.event.ClickEvent asAdventure();
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.chat.clickevent;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.mapper.MappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public interface ClickEventAction<T extends ClickEvent> extends MappedEntity {
|
||||
|
||||
boolean isAllowFromServer();
|
||||
|
||||
T decode(NBTCompound compound, PacketWrapper<?> wrapper);
|
||||
|
||||
void encode(NBTCompound compound, PacketWrapper<?> wrapper, T clickEvent);
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.chat.clickevent;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.util.NbtMapDecoder;
|
||||
import com.github.retrooper.packetevents.protocol.util.NbtMapEncoder;
|
||||
import com.github.retrooper.packetevents.util.mappings.VersionedRegistry;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public final class ClickEventActions {
|
||||
|
||||
private static final VersionedRegistry<ClickEventAction<?>> REGISTRY = new VersionedRegistry<>("click_event_action");
|
||||
|
||||
private ClickEventActions() {
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static <T extends ClickEvent> ClickEventAction<T> define(
|
||||
String name, boolean allowFromServer,
|
||||
NbtMapDecoder<T> decoder, NbtMapEncoder<T> encoder
|
||||
) {
|
||||
return REGISTRY.define(name, data -> new StaticClickEventAction<>(
|
||||
data, allowFromServer, decoder, encoder));
|
||||
}
|
||||
|
||||
public static VersionedRegistry<ClickEventAction<?>> getRegistry() {
|
||||
return REGISTRY;
|
||||
}
|
||||
|
||||
public static final ClickEventAction<OpenUrlClickEvent> OPEN_URL = define("open_url", true,
|
||||
OpenUrlClickEvent::decode, OpenUrlClickEvent::encode);
|
||||
public static final ClickEventAction<OpenFileClickEvent> OPEN_FILE = define("open_file", false,
|
||||
OpenFileClickEvent::decode, OpenFileClickEvent::encode);
|
||||
public static final ClickEventAction<RunCommandClickEvent> RUN_COMMAND = define("run_command", true,
|
||||
RunCommandClickEvent::decode, RunCommandClickEvent::encode);
|
||||
/**
|
||||
* Removed in 1.9
|
||||
*/
|
||||
@ApiStatus.Obsolete
|
||||
public static final ClickEventAction<TwitchUserInfoClickEvent> TWITCH_USER_INFO = define("twitch_user_info", false,
|
||||
TwitchUserInfoClickEvent::decode, TwitchUserInfoClickEvent::encode);
|
||||
public static final ClickEventAction<SuggestCommandClickEvent> SUGGEST_COMMAND = define("suggest_command", true,
|
||||
SuggestCommandClickEvent::decode, SuggestCommandClickEvent::encode);
|
||||
|
||||
/**
|
||||
* Added with 1.8
|
||||
*/
|
||||
public static final ClickEventAction<ChangePageClickEvent> CHANGE_PAGE = define("change_page", true,
|
||||
ChangePageClickEvent::decode, ChangePageClickEvent::encode);
|
||||
|
||||
/**
|
||||
* Added with 1.15
|
||||
*/
|
||||
public static final ClickEventAction<CopyToClipboardClickEvent> COPY_TO_CLIPBOARD = define("copy_to_clipboard", true,
|
||||
CopyToClipboardClickEvent::decode, CopyToClipboardClickEvent::encode);
|
||||
|
||||
/**
|
||||
* Added with 1.21.6
|
||||
*/
|
||||
public static final ClickEventAction<ShowDialogClickEvent> SHOW_DIALOG = define("show_dialog", true,
|
||||
ShowDialogClickEvent::decode, ShowDialogClickEvent::encode);
|
||||
/**
|
||||
* Added with 1.21.6
|
||||
*/
|
||||
public static final ClickEventAction<CustomClickEvent> CUSTOM = define("custom", true,
|
||||
CustomClickEvent::decode, CustomClickEvent::encode);
|
||||
|
||||
static {
|
||||
REGISTRY.unloadMappings();
|
||||
}
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.chat.clickevent;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class CopyToClipboardClickEvent implements ClickEvent {
|
||||
|
||||
private final String value;
|
||||
|
||||
public CopyToClipboardClickEvent(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public static CopyToClipboardClickEvent decode(NBTCompound compound, PacketWrapper<?> wrapper) {
|
||||
String value = compound.getStringTagValueOrThrow("value");
|
||||
return new CopyToClipboardClickEvent(value);
|
||||
}
|
||||
|
||||
public static void encode(NBTCompound compound, PacketWrapper<?> wrapper, CopyToClipboardClickEvent clickEvent) {
|
||||
compound.setTag("value", new NBTString(clickEvent.value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClickEventAction<?> getAction() {
|
||||
return ClickEventActions.COPY_TO_CLIPBOARD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public net.kyori.adventure.text.event.ClickEvent asAdventure() {
|
||||
return net.kyori.adventure.text.event.ClickEvent.copyToClipboard(this.value);
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.chat.clickevent;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTEnd;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.util.adventure.NbtTagHolder;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public class CustomClickEvent implements ClickEvent {
|
||||
|
||||
private final ResourceLocation id;
|
||||
private final @Nullable NBT payload;
|
||||
|
||||
public CustomClickEvent(ResourceLocation id, @Nullable NBT payload) {
|
||||
this.id = id;
|
||||
this.payload = payload;
|
||||
}
|
||||
|
||||
public static CustomClickEvent decode(NBTCompound compound, PacketWrapper<?> wrapper) {
|
||||
ResourceLocation id = compound.getOrThrow("id", ResourceLocation::decode, wrapper);
|
||||
NBT payload = compound.getTagOrNull("payload");
|
||||
return new CustomClickEvent(id, payload);
|
||||
}
|
||||
|
||||
public static void encode(NBTCompound compound, PacketWrapper<?> wrapper, CustomClickEvent clickEvent) {
|
||||
compound.set("id", clickEvent.id, ResourceLocation::encode, wrapper);
|
||||
if (clickEvent.payload != null) {
|
||||
compound.setTag("payload", clickEvent.payload);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClickEventAction<?> getAction() {
|
||||
return ClickEventActions.CUSTOM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public net.kyori.adventure.text.event.ClickEvent asAdventure() {
|
||||
return net.kyori.adventure.text.event.ClickEvent.custom(
|
||||
this.id.key(), new NbtTagHolder(this.payload != null ? this.payload : NBTEnd.INSTANCE));
|
||||
}
|
||||
|
||||
public ResourceLocation getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public @Nullable NBT getPayload() {
|
||||
return this.payload;
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.chat.clickevent;
|
||||
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class OpenFileClickEvent implements ClickEvent {
|
||||
|
||||
private final String path;
|
||||
|
||||
public OpenFileClickEvent(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public static OpenFileClickEvent decode(NBTCompound compound, PacketWrapper<?> wrapper) {
|
||||
boolean v1215 = wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_5);
|
||||
String path = compound.getStringTagValueOrThrow(v1215 ? "path" : "value");
|
||||
return new OpenFileClickEvent(path);
|
||||
}
|
||||
|
||||
public static void encode(NBTCompound compound, PacketWrapper<?> wrapper, OpenFileClickEvent clickEvent) {
|
||||
boolean v1215 = wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_5);
|
||||
compound.setTag(v1215 ? "path" : "value", new NBTString(clickEvent.path));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClickEventAction<?> getAction() {
|
||||
return ClickEventActions.OPEN_FILE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public net.kyori.adventure.text.event.ClickEvent asAdventure() {
|
||||
return net.kyori.adventure.text.event.ClickEvent.openFile(this.path);
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return this.path;
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.chat.clickevent;
|
||||
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class OpenUrlClickEvent implements ClickEvent {
|
||||
|
||||
private final String url;
|
||||
|
||||
public OpenUrlClickEvent(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public static OpenUrlClickEvent decode(NBTCompound compound, PacketWrapper<?> wrapper) {
|
||||
boolean v1215 = wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_5);
|
||||
String url = compound.getStringTagValueOrThrow(v1215 ? "url" : "value");
|
||||
return new OpenUrlClickEvent(url);
|
||||
}
|
||||
|
||||
public static void encode(NBTCompound compound, PacketWrapper<?> wrapper, OpenUrlClickEvent clickEvent) {
|
||||
boolean v1215 = wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_5);
|
||||
compound.setTag(v1215 ? "url" : "value", new NBTString(clickEvent.url));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClickEventAction<?> getAction() {
|
||||
return ClickEventActions.OPEN_URL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public net.kyori.adventure.text.event.ClickEvent asAdventure() {
|
||||
return net.kyori.adventure.text.event.ClickEvent.openUrl(this.url);
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return this.url;
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.chat.clickevent;
|
||||
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class RunCommandClickEvent implements ClickEvent {
|
||||
|
||||
private final String command;
|
||||
|
||||
public RunCommandClickEvent(String command) {
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
public static RunCommandClickEvent decode(NBTCompound compound, PacketWrapper<?> wrapper) {
|
||||
boolean v1215 = wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_5);
|
||||
String command = compound.getStringTagValueOrThrow(v1215 ? "command" : "value");
|
||||
return new RunCommandClickEvent(command);
|
||||
}
|
||||
|
||||
public static void encode(NBTCompound compound, PacketWrapper<?> wrapper, RunCommandClickEvent clickEvent) {
|
||||
boolean v1215 = wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_5);
|
||||
compound.setTag(v1215 ? "command" : "value", new NBTString(clickEvent.command));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClickEventAction<?> getAction() {
|
||||
return ClickEventActions.RUN_COMMAND;
|
||||
}
|
||||
|
||||
@Override
|
||||
public net.kyori.adventure.text.event.ClickEvent asAdventure() {
|
||||
return net.kyori.adventure.text.event.ClickEvent.runCommand(this.command);
|
||||
}
|
||||
|
||||
public String getCommand() {
|
||||
return this.command;
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.chat.clickevent;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.dialog.Dialog;
|
||||
import com.github.retrooper.packetevents.protocol.dialog.Dialogs;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.MappedEntityRef;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class ShowDialogClickEvent implements ClickEvent {
|
||||
|
||||
private final MappedEntityRef<Dialog> dialog;
|
||||
|
||||
public ShowDialogClickEvent(Dialog dialog) {
|
||||
this(new MappedEntityRef.Static<>(dialog));
|
||||
}
|
||||
|
||||
public ShowDialogClickEvent(MappedEntityRef<Dialog> dialog) {
|
||||
this.dialog = dialog;
|
||||
}
|
||||
|
||||
public static ShowDialogClickEvent decode(NBTCompound compound, PacketWrapper<?> wrapper) {
|
||||
MappedEntityRef<Dialog> dialog = MappedEntityRef.decode(compound.getTagOrThrow("dialog"),
|
||||
Dialogs.getRegistry(), Dialog::decode, wrapper);
|
||||
return new ShowDialogClickEvent(dialog);
|
||||
}
|
||||
|
||||
public static void encode(NBTCompound compound, PacketWrapper<?> wrapper, ShowDialogClickEvent clickEvent) {
|
||||
compound.setTag("dialog", MappedEntityRef.encode(wrapper, Dialog::encode, clickEvent.dialog));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClickEventAction<?> getAction() {
|
||||
return ClickEventActions.SHOW_DIALOG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public net.kyori.adventure.text.event.ClickEvent asAdventure() {
|
||||
return net.kyori.adventure.text.event.ClickEvent.showDialog(this.dialog.get());
|
||||
}
|
||||
|
||||
public MappedEntityRef<Dialog> getDialogRef() {
|
||||
return this.dialog;
|
||||
}
|
||||
|
||||
public Dialog getDialog() {
|
||||
return this.dialog.get();
|
||||
}
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.chat.clickevent;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.mapper.AbstractMappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.util.NbtMapDecoder;
|
||||
import com.github.retrooper.packetevents.protocol.util.NbtMapEncoder;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class StaticClickEventAction<T extends ClickEvent> extends AbstractMappedEntity implements ClickEventAction<T> {
|
||||
|
||||
private final boolean allowFromServer;
|
||||
private final NbtMapDecoder<T> decoder;
|
||||
private final NbtMapEncoder<T> encoder;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public StaticClickEventAction(
|
||||
@Nullable TypesBuilderData data, boolean allowFromServer,
|
||||
NbtMapDecoder<T> decoder, NbtMapEncoder<T> encoder
|
||||
) {
|
||||
super(data);
|
||||
this.allowFromServer = allowFromServer;
|
||||
this.decoder = decoder;
|
||||
this.encoder = encoder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAllowFromServer() {
|
||||
return this.allowFromServer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T decode(NBTCompound compound, PacketWrapper<?> wrapper) {
|
||||
return this.decoder.decode(compound, wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encode(NBTCompound compound, PacketWrapper<?> wrapper, T clickEvent) {
|
||||
this.encoder.encode(compound, wrapper, clickEvent);
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.chat.clickevent;
|
||||
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class SuggestCommandClickEvent implements ClickEvent {
|
||||
|
||||
private final String command;
|
||||
|
||||
public SuggestCommandClickEvent(String command) {
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
public static SuggestCommandClickEvent decode(NBTCompound compound, PacketWrapper<?> wrapper) {
|
||||
boolean v1215 = wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_5);
|
||||
String command = compound.getStringTagValueOrThrow(v1215 ? "command" : "value");
|
||||
return new SuggestCommandClickEvent(command);
|
||||
}
|
||||
|
||||
public static void encode(NBTCompound compound, PacketWrapper<?> wrapper, SuggestCommandClickEvent clickEvent) {
|
||||
boolean v1215 = wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_5);
|
||||
compound.setTag(v1215 ? "command" : "value", new NBTString(clickEvent.command));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClickEventAction<?> getAction() {
|
||||
return ClickEventActions.SUGGEST_COMMAND;
|
||||
}
|
||||
|
||||
@Override
|
||||
public net.kyori.adventure.text.event.ClickEvent asAdventure() {
|
||||
return net.kyori.adventure.text.event.ClickEvent.suggestCommand(this.command);
|
||||
}
|
||||
|
||||
public String getCommand() {
|
||||
return this.command;
|
||||
}
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.chat.clickevent;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* Removed in 1.9
|
||||
*/
|
||||
@NullMarked
|
||||
@ApiStatus.Obsolete
|
||||
public class TwitchUserInfoClickEvent implements ClickEvent {
|
||||
|
||||
private final String value;
|
||||
|
||||
public TwitchUserInfoClickEvent(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public static TwitchUserInfoClickEvent decode(NBTCompound compound, PacketWrapper<?> wrapper) {
|
||||
String value = compound.getStringTagValueOrThrow("value");
|
||||
return new TwitchUserInfoClickEvent(value);
|
||||
}
|
||||
|
||||
public static void encode(NBTCompound compound, PacketWrapper<?> wrapper, TwitchUserInfoClickEvent clickEvent) {
|
||||
compound.setTag("value", new NBTString(clickEvent.value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClickEventAction<?> getAction() {
|
||||
return ClickEventActions.TWITCH_USER_INFO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public net.kyori.adventure.text.event.ClickEvent asAdventure() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
+12
-2
@@ -19,6 +19,8 @@
|
||||
package com.github.retrooper.packetevents.protocol.chat.message;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.chat.ChatType;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.util.adventure.AdventureSerializer;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public class ChatMessage {
|
||||
@@ -34,14 +36,22 @@ public class ChatMessage {
|
||||
return chatContent;
|
||||
}
|
||||
|
||||
public ChatType getType() {
|
||||
return type;
|
||||
public String getChatContentJson(ClientVersion version) {
|
||||
return AdventureSerializer.serializer(version).asJson(this.getChatContent());
|
||||
}
|
||||
|
||||
public void setChatContent(Component chatContent) {
|
||||
this.chatContent = chatContent;
|
||||
}
|
||||
|
||||
public void setChatContentJson(ClientVersion version, String json) {
|
||||
this.setChatContent(AdventureSerializer.serializer(version).fromJson(json));
|
||||
}
|
||||
|
||||
public ChatType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(ChatType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@@ -65,6 +65,16 @@ public class Color implements RGBLike {
|
||||
wrapper.writeInt(color.asRGB());
|
||||
}
|
||||
|
||||
public static Color readShort(PacketWrapper<?> wrapper) {
|
||||
return new Color(wrapper.readUnsignedByte(), wrapper.readUnsignedByte(), wrapper.readUnsignedByte());
|
||||
}
|
||||
|
||||
public static void writeShort(PacketWrapper<?> wrapper, Color color) {
|
||||
wrapper.writeByte(color.red);
|
||||
wrapper.writeByte(color.green);
|
||||
wrapper.writeByte(color.blue);
|
||||
}
|
||||
|
||||
public static Color decode(NBT nbt, ClientVersion version) {
|
||||
if (nbt instanceof NBTNumber) {
|
||||
return new Color(((NBTNumber) nbt).getAsInt());
|
||||
|
||||
+13
@@ -22,14 +22,22 @@ 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 com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@NullMarked
|
||||
public interface IComponentMap {
|
||||
|
||||
static StaticComponentMap decode(NBT nbt, PacketWrapper<?> wrapper, IRegistry<? extends ComponentType<?>> registry) {
|
||||
return decode(nbt, wrapper.getServerVersion().toClientVersion(), registry);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@SuppressWarnings("unchecked") // safe in this case
|
||||
static StaticComponentMap decode(NBT nbt, ClientVersion version, IRegistry<? extends ComponentType<?>> registry) {
|
||||
NBTCompound compound = (NBTCompound) nbt;
|
||||
@@ -45,6 +53,11 @@ public interface IComponentMap {
|
||||
return components.build();
|
||||
}
|
||||
|
||||
static NBT encode(PacketWrapper<?> wrapper, StaticComponentMap components) {
|
||||
return encode(components, wrapper.getServerVersion().toClientVersion());
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@SuppressWarnings("unchecked") // safe in this case
|
||||
static NBT encode(StaticComponentMap components, ClientVersion version) {
|
||||
NBTCompound compound = new NBTCompound();
|
||||
|
||||
+18
-1
@@ -20,8 +20,10 @@ 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.AttributeDisplay;
|
||||
import com.github.retrooper.packetevents.protocol.attribute.AttributeOperation;
|
||||
import com.github.retrooper.packetevents.protocol.attribute.Attributes;
|
||||
import com.github.retrooper.packetevents.protocol.attribute.DefaultAttributeDisplay;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerUpdateAttributes.PropertyModifier;
|
||||
@@ -133,24 +135,39 @@ public class ItemAttributeModifiers {
|
||||
private Attribute attribute;
|
||||
private Modifier modifier;
|
||||
private EquipmentSlotGroup slotGroup;
|
||||
private AttributeDisplay display;
|
||||
|
||||
@ApiStatus.Obsolete
|
||||
public ModifierEntry(Attribute attribute, Modifier modifier, EquipmentSlotGroup slotGroup) {
|
||||
this(attribute, modifier, slotGroup, DefaultAttributeDisplay.INSTANCE);
|
||||
}
|
||||
|
||||
public ModifierEntry(
|
||||
Attribute attribute, Modifier modifier,
|
||||
EquipmentSlotGroup slotGroup, AttributeDisplay display
|
||||
) {
|
||||
this.attribute = attribute;
|
||||
this.modifier = modifier;
|
||||
this.slotGroup = slotGroup;
|
||||
this.display = display;
|
||||
}
|
||||
|
||||
public static ModifierEntry read(PacketWrapper<?> wrapper) {
|
||||
Attribute attribute = wrapper.readMappedEntity(Attributes::getById);
|
||||
Modifier modifier = Modifier.read(wrapper);
|
||||
EquipmentSlotGroup slot = wrapper.readEnum(EquipmentSlotGroup.values());
|
||||
return new ModifierEntry(attribute, modifier, slot);
|
||||
AttributeDisplay display = wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_6)
|
||||
? AttributeDisplay.read(wrapper) : DefaultAttributeDisplay.INSTANCE;
|
||||
return new ModifierEntry(attribute, modifier, slot, display);
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, ModifierEntry entry) {
|
||||
wrapper.writeMappedEntity(entry.attribute);
|
||||
Modifier.write(wrapper, entry.modifier);
|
||||
wrapper.writeEnum(entry.slotGroup);
|
||||
if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_6)) {
|
||||
AttributeDisplay.write(wrapper, entry.display);
|
||||
}
|
||||
}
|
||||
|
||||
public Attribute getAttribute() {
|
||||
|
||||
+83
-7
@@ -24,6 +24,7 @@ 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.protocol.sound.Sounds;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
@@ -41,7 +42,18 @@ public class ItemEquippable {
|
||||
private boolean dispensable;
|
||||
private boolean swappable;
|
||||
private boolean damageOnHurt;
|
||||
/**
|
||||
* Added with 1.21.5
|
||||
*/
|
||||
private boolean equipOnInteract;
|
||||
/**
|
||||
* Added with 1.21.6
|
||||
*/
|
||||
private boolean canBeSheared;
|
||||
/**
|
||||
* Added with 1.21.6
|
||||
*/
|
||||
private Sound shearingSound;
|
||||
|
||||
@ApiStatus.Obsolete
|
||||
public ItemEquippable(
|
||||
@@ -58,6 +70,7 @@ public class ItemEquippable {
|
||||
dispensable, swappable, damageOnHurt, false);
|
||||
}
|
||||
|
||||
@ApiStatus.Obsolete
|
||||
public ItemEquippable(
|
||||
EquipmentSlot slot,
|
||||
Sound equipSound,
|
||||
@@ -68,6 +81,24 @@ public class ItemEquippable {
|
||||
boolean swappable,
|
||||
boolean damageOnHurt,
|
||||
boolean equipOnInteract
|
||||
) {
|
||||
this(slot, equipSound, assetId, cameraOverlay, allowedEntities,
|
||||
dispensable, swappable, damageOnHurt, equipOnInteract,
|
||||
false, Sounds.ITEM_SHEARS_SNIP);
|
||||
}
|
||||
|
||||
public ItemEquippable(
|
||||
EquipmentSlot slot,
|
||||
Sound equipSound,
|
||||
@Nullable ResourceLocation assetId,
|
||||
@Nullable ResourceLocation cameraOverlay,
|
||||
@Nullable MappedEntitySet<EntityType> allowedEntities,
|
||||
boolean dispensable,
|
||||
boolean swappable,
|
||||
boolean damageOnHurt,
|
||||
boolean equipOnInteract,
|
||||
boolean canBeSheared,
|
||||
Sound shearingSound
|
||||
) {
|
||||
this.slot = slot;
|
||||
this.equipSound = equipSound;
|
||||
@@ -78,6 +109,8 @@ public class ItemEquippable {
|
||||
this.swappable = swappable;
|
||||
this.damageOnHurt = damageOnHurt;
|
||||
this.equipOnInteract = equipOnInteract;
|
||||
this.canBeSheared = canBeSheared;
|
||||
this.shearingSound = shearingSound;
|
||||
}
|
||||
|
||||
public static ItemEquippable read(PacketWrapper<?> wrapper) {
|
||||
@@ -90,9 +123,19 @@ public class ItemEquippable {
|
||||
boolean dispensable = wrapper.readBoolean();
|
||||
boolean swappable = wrapper.readBoolean();
|
||||
boolean damageOnHurt = wrapper.readBoolean();
|
||||
boolean equipOnInteract = wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_5) && wrapper.readBoolean();
|
||||
boolean equipOnInteract = false;
|
||||
boolean canBeSheared = false;
|
||||
Sound shearingSound = Sounds.ITEM_SHEARS_SNIP;
|
||||
if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_5)) {
|
||||
equipOnInteract = wrapper.readBoolean();
|
||||
if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_6)) {
|
||||
canBeSheared = wrapper.readBoolean();
|
||||
shearingSound = Sound.read(wrapper);
|
||||
}
|
||||
}
|
||||
return new ItemEquippable(slot, equipSound, assetId,
|
||||
cameraOverlay, allowedEntities, dispensable, swappable, damageOnHurt, equipOnInteract);
|
||||
cameraOverlay, allowedEntities, dispensable, swappable,
|
||||
damageOnHurt, equipOnInteract, canBeSheared, shearingSound);
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, ItemEquippable equippable) {
|
||||
@@ -106,6 +149,10 @@ public class ItemEquippable {
|
||||
wrapper.writeBoolean(equippable.damageOnHurt);
|
||||
if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_5)) {
|
||||
wrapper.writeBoolean(equippable.equipOnInteract);
|
||||
if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_6)) {
|
||||
wrapper.writeBoolean(equippable.canBeSheared);
|
||||
Sound.write(wrapper, equippable.shearingSound);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,6 +234,34 @@ public class ItemEquippable {
|
||||
this.equipOnInteract = equipOnInteract;
|
||||
}
|
||||
|
||||
/**
|
||||
* Added with 1.21.6
|
||||
*/
|
||||
public boolean isCanBeSheared() {
|
||||
return this.canBeSheared;
|
||||
}
|
||||
|
||||
/**
|
||||
* Added with 1.21.6
|
||||
*/
|
||||
public void setCanBeSheared(boolean canBeSheared) {
|
||||
this.canBeSheared = canBeSheared;
|
||||
}
|
||||
|
||||
/**
|
||||
* Added with 1.21.6
|
||||
*/
|
||||
public Sound getShearingSound() {
|
||||
return this.shearingSound;
|
||||
}
|
||||
|
||||
/**
|
||||
* Added with 1.21.6
|
||||
*/
|
||||
public void setShearingSound(Sound shearingSound) {
|
||||
this.shearingSound = shearingSound;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public @Nullable ResourceLocation getModel() {
|
||||
return this.assetId;
|
||||
@@ -199,27 +274,28 @@ public class ItemEquippable {
|
||||
|
||||
@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.equipOnInteract != that.equipOnInteract) return false;
|
||||
if (this.canBeSheared != that.canBeSheared) return false;
|
||||
if (this.slot != that.slot) return false;
|
||||
if (!Objects.equals(this.equipSound, that.equipSound)) return false;
|
||||
if (!this.equipSound.equals(that.equipSound)) return false;
|
||||
if (!Objects.equals(this.assetId, that.assetId)) return false;
|
||||
if (!Objects.equals(this.cameraOverlay, that.cameraOverlay)) return false;
|
||||
if (!Objects.equals(this.allowedEntities, that.allowedEntities)) return false;
|
||||
return Objects.equals(this.equipOnInteract, that.equipOnInteract);
|
||||
return this.shearingSound.equals(that.shearingSound);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.slot, this.equipSound, this.assetId, this.cameraOverlay, this.allowedEntities, this.dispensable, this.swappable, this.damageOnHurt, this.equipOnInteract);
|
||||
return Objects.hash(this.slot, this.equipSound, this.assetId, this.cameraOverlay, this.allowedEntities, this.dispensable, this.swappable, this.damageOnHurt, this.equipOnInteract, this.canBeSheared, this.shearingSound);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ItemEquippable{slot=" + this.slot + ", equipSound=" + this.equipSound + ", assetId=" + this.assetId + ", cameraOverlay=" + this.cameraOverlay + ", allowedEntities=" + this.allowedEntities + ", dispensable=" + this.dispensable + ", swappable=" + this.swappable + ", damageOnHurt=" + this.damageOnHurt + ", equipOnInteract=" + this.equipOnInteract + '}';
|
||||
return "ItemEquippable{slot=" + this.slot + ", equipSound=" + this.equipSound + ", assetId=" + this.assetId + ", cameraOverlay=" + this.cameraOverlay + ", allowedEntities=" + this.allowedEntities + ", dispensable=" + this.dispensable + ", swappable=" + this.swappable + ", damageOnHurt=" + this.damageOnHurt + ", equipOnInteract=" + this.equipOnInteract + ", canBeSheared=" + this.canBeSheared + ", shearingSound=" + this.shearingSound + '}';
|
||||
}
|
||||
}
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.dialog.body.DialogBody;
|
||||
import com.github.retrooper.packetevents.protocol.dialog.input.Input;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTByte;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.util.adventure.AdventureSerializer;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@NullMarked
|
||||
public final class CommonDialogData {
|
||||
|
||||
private final Component title;
|
||||
private final @Nullable Component externalTitle;
|
||||
private final boolean canCloseWithEscape;
|
||||
private final boolean pause;
|
||||
private final DialogAction afterAction;
|
||||
private final List<DialogBody> body;
|
||||
private final List<Input> inputs;
|
||||
|
||||
public CommonDialogData(
|
||||
Component title, @Nullable Component externalTitle, boolean canCloseWithEscape, boolean pause,
|
||||
DialogAction afterAction, List<DialogBody> body, List<Input> inputs
|
||||
) {
|
||||
if (pause && !afterAction.isWillUnpause()) {
|
||||
throw new IllegalArgumentException("Dialogs that pause the game must use after_action "
|
||||
+ "values that unpause it after user action!");
|
||||
}
|
||||
this.title = title;
|
||||
this.externalTitle = externalTitle;
|
||||
this.canCloseWithEscape = canCloseWithEscape;
|
||||
this.pause = pause;
|
||||
this.afterAction = afterAction;
|
||||
this.body = body;
|
||||
this.inputs = inputs;
|
||||
}
|
||||
|
||||
public static CommonDialogData decode(NBTCompound compound, PacketWrapper<?> wrapper) {
|
||||
Component title = compound.getOrThrow("title", AdventureSerializer.serializer(wrapper), wrapper);
|
||||
Component externalTitle = compound.getOrNull("external_title", AdventureSerializer.serializer(wrapper), wrapper);
|
||||
boolean canCloseWithEscape = compound.getBooleanOr("can_close_with_escape", true);
|
||||
boolean pause = compound.getBooleanOr("pause", true);
|
||||
DialogAction afterAction = compound.getOr("after_action", DialogAction::decode, DialogAction.CLOSE, wrapper);
|
||||
List<DialogBody> body = compound.getListOrEmpty("body", DialogBody::decode, wrapper);
|
||||
List<Input> inputs = compound.getListOrEmpty("inputs", Input::decode, wrapper);
|
||||
return new CommonDialogData(title, externalTitle, canCloseWithEscape, pause, afterAction, body, inputs);
|
||||
}
|
||||
|
||||
public static void encode(NBTCompound compound, PacketWrapper<?> wrapper, CommonDialogData data) {
|
||||
compound.set("title", data.title, AdventureSerializer.serializer(wrapper), wrapper);
|
||||
if (data.externalTitle != null) {
|
||||
compound.set("external_title", data.externalTitle, AdventureSerializer.serializer(wrapper), wrapper);
|
||||
}
|
||||
if (!data.canCloseWithEscape) {
|
||||
compound.setTag("can_close_with_escape", new NBTByte(false));
|
||||
}
|
||||
if (!data.pause) {
|
||||
compound.setTag("pause", new NBTByte(false));
|
||||
}
|
||||
if (data.afterAction != DialogAction.CLOSE) {
|
||||
compound.set("after_action", data.afterAction, DialogAction::encode, wrapper);
|
||||
}
|
||||
if (!data.body.isEmpty()) {
|
||||
compound.setCompactList("body", data.body, DialogBody::encode, wrapper);
|
||||
}
|
||||
if (!data.inputs.isEmpty()) {
|
||||
compound.setList("inputs", data.inputs, Input::encode, wrapper);
|
||||
}
|
||||
}
|
||||
|
||||
public Component getTitle() {
|
||||
return this.title;
|
||||
}
|
||||
|
||||
public @Nullable Component getExternalTitle() {
|
||||
return this.externalTitle;
|
||||
}
|
||||
|
||||
public boolean isCanCloseWithEscape() {
|
||||
return this.canCloseWithEscape;
|
||||
}
|
||||
|
||||
public boolean isPause() {
|
||||
return this.pause;
|
||||
}
|
||||
|
||||
public DialogAction getAfterAction() {
|
||||
return this.afterAction;
|
||||
}
|
||||
|
||||
public List<DialogBody> getBody() {
|
||||
return this.body;
|
||||
}
|
||||
|
||||
public List<Input> getInputs() {
|
||||
return this.inputs;
|
||||
}
|
||||
}
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.dialog.button.ActionButton;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.AbstractMappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@NullMarked
|
||||
public class ConfirmationDialog extends AbstractMappedEntity implements Dialog {
|
||||
|
||||
private final CommonDialogData common;
|
||||
private final ActionButton yesButton;
|
||||
private final ActionButton noButton;
|
||||
|
||||
public ConfirmationDialog(CommonDialogData common, ActionButton yesButton, ActionButton noButton) {
|
||||
this(null, common, yesButton, noButton);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public ConfirmationDialog(
|
||||
@Nullable TypesBuilderData data, CommonDialogData common,
|
||||
ActionButton yesButton, ActionButton noButton
|
||||
) {
|
||||
super(data);
|
||||
this.common = common;
|
||||
this.yesButton = yesButton;
|
||||
this.noButton = noButton;
|
||||
}
|
||||
|
||||
public static ConfirmationDialog decode(NBTCompound compound, PacketWrapper<?> wrapper) {
|
||||
CommonDialogData common = CommonDialogData.decode(compound, wrapper);
|
||||
ActionButton yesButton = compound.getOrThrow("yes", ActionButton::decode, wrapper);
|
||||
ActionButton noButton = compound.getOrThrow("no", ActionButton::decode, wrapper);
|
||||
return new ConfirmationDialog(null, common, yesButton, noButton);
|
||||
}
|
||||
|
||||
public static void encode(NBTCompound compound, PacketWrapper<?> wrapper, ConfirmationDialog dialog) {
|
||||
CommonDialogData.encode(compound, wrapper, dialog.common);
|
||||
compound.set("yes", dialog.yesButton, ActionButton::encode, wrapper);
|
||||
compound.set("no", dialog.noButton, ActionButton::encode, wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog copy(@Nullable TypesBuilderData newData) {
|
||||
return new ConfirmationDialog(newData, this.common, this.yesButton, this.noButton);
|
||||
}
|
||||
|
||||
public CommonDialogData getCommon() {
|
||||
return this.common;
|
||||
}
|
||||
|
||||
public ActionButton getYesButton() {
|
||||
return this.yesButton;
|
||||
}
|
||||
|
||||
public ActionButton getNoButton() {
|
||||
return this.noButton;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialogType<?> getType() {
|
||||
return DialogTypes.CONFIRMATION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deepEquals(Object obj) {
|
||||
if (!(obj instanceof ConfirmationDialog)) return false;
|
||||
if (!super.equals(obj)) return false;
|
||||
ConfirmationDialog that = (ConfirmationDialog) obj;
|
||||
if (!this.common.equals(that.common)) return false;
|
||||
if (!this.yesButton.equals(that.yesButton)) return false;
|
||||
return this.noButton.equals(that.noButton);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deepHashCode() {
|
||||
return Objects.hash(super.hashCode(), this.common, this.yesButton, this.noButton);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog;
|
||||
|
||||
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.util.mappings.TypesBuilderData;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import net.kyori.adventure.dialog.DialogLike;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public interface Dialog extends MappedEntity, DeepComparableEntity, CopyableEntity<Dialog>, DialogLike {
|
||||
|
||||
static Dialog read(PacketWrapper<?> wrapper) {
|
||||
return wrapper.readMappedEntityOrDirect(Dialogs.getRegistry(), Dialog::readDirect);
|
||||
}
|
||||
|
||||
static void write(PacketWrapper<?> wrapper, Dialog dialog) {
|
||||
wrapper.writeMappedEntityOrDirect(dialog, Dialog::writeDirect);
|
||||
}
|
||||
|
||||
static Dialog readDirect(PacketWrapper<?> wrapper) {
|
||||
return decodeDirect(wrapper.readNBTRaw(), wrapper, null);
|
||||
}
|
||||
|
||||
static void writeDirect(PacketWrapper<?> wrapper, Dialog dialog) {
|
||||
wrapper.writeNBTRaw(encodeDirect(dialog, wrapper));
|
||||
}
|
||||
|
||||
static Dialog decode(NBT nbt, PacketWrapper<?> wrapper) {
|
||||
if (nbt instanceof NBTString) {
|
||||
return wrapper.replaceRegistry(Dialogs.getRegistry()).getByNameOrThrow(((NBTString) nbt).getValue());
|
||||
}
|
||||
return decodeDirect(nbt, wrapper, null);
|
||||
}
|
||||
|
||||
static NBT encode(PacketWrapper<?> wrapper, Dialog dialog) {
|
||||
if (dialog.isRegistered()) {
|
||||
return new NBTString(dialog.getName().toString());
|
||||
}
|
||||
return encodeDirect(dialog, wrapper);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
static Dialog decodeDirect(NBT nbt, PacketWrapper<?> wrapper, @Nullable TypesBuilderData data) {
|
||||
NBTCompound compound = (NBTCompound) nbt;
|
||||
String dialogTypeName = compound.getStringTagValueOrThrow("type");
|
||||
DialogType<?> dialogType = DialogTypes.getRegistry().getByNameOrThrow(dialogTypeName);
|
||||
// TODO pass down data instead of copying
|
||||
return dialogType.decode(compound, wrapper).copy(data);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
@SuppressWarnings("unchecked") // not unchecked
|
||||
static NBT encodeDirect(Dialog dialog, PacketWrapper<?> wrapper) {
|
||||
NBTCompound compound = new NBTCompound();
|
||||
compound.setTag("type", new NBTString(dialog.getType().getName().toString()));
|
||||
((DialogType<? super Dialog>) dialog.getType()).encode(compound, wrapper, dialog);
|
||||
return compound;
|
||||
}
|
||||
|
||||
DialogType<?> getType();
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
|
||||
import com.github.retrooper.packetevents.util.adventure.AdventureIndexUtil;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import net.kyori.adventure.util.Index;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public enum DialogAction {
|
||||
|
||||
CLOSE("close", true),
|
||||
NONE("none", false),
|
||||
WAIT_FOR_RESPONSE("wait_for_response", true);
|
||||
|
||||
public static final Index<String, DialogAction> NAME_INDEX = Index.create(
|
||||
DialogAction.class, DialogAction::getName);
|
||||
|
||||
private final String name;
|
||||
private final boolean willUnpause;
|
||||
|
||||
DialogAction(String name, boolean willUnpause) {
|
||||
this.name = name;
|
||||
this.willUnpause = willUnpause;
|
||||
}
|
||||
|
||||
public static DialogAction decode(NBT nbt, PacketWrapper<?> wrapper) {
|
||||
return AdventureIndexUtil.indexValueOrThrow(NAME_INDEX, ((NBTString) nbt).getValue());
|
||||
}
|
||||
|
||||
public static NBT encode(PacketWrapper<?> wrapper, DialogAction action) {
|
||||
return new NBTString(action.name);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public boolean isWillUnpause() {
|
||||
return this.willUnpause;
|
||||
}
|
||||
}
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.dialog.button.ActionButton;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.AbstractMappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.MappedEntityRefSet;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.MappedEntitySet;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTInt;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@NullMarked
|
||||
public class DialogListDialog extends AbstractMappedEntity implements Dialog {
|
||||
|
||||
private final CommonDialogData common;
|
||||
private final MappedEntityRefSet<Dialog> dialogs;
|
||||
private final @Nullable ActionButton exitAction;
|
||||
private final int columns;
|
||||
private final int buttonWidth;
|
||||
|
||||
public DialogListDialog(
|
||||
CommonDialogData common,
|
||||
MappedEntityRefSet<Dialog> dialogs,
|
||||
@Nullable ActionButton exitAction,
|
||||
int columns, int buttonWidth
|
||||
) {
|
||||
this(null, common, dialogs, exitAction, columns, buttonWidth);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public DialogListDialog(
|
||||
@Nullable TypesBuilderData data,
|
||||
CommonDialogData common,
|
||||
MappedEntityRefSet<Dialog> dialogs,
|
||||
@Nullable ActionButton exitAction,
|
||||
int columns, int buttonWidth
|
||||
) {
|
||||
super(data);
|
||||
this.common = common;
|
||||
this.dialogs = dialogs;
|
||||
this.exitAction = exitAction;
|
||||
this.columns = columns;
|
||||
this.buttonWidth = buttonWidth;
|
||||
}
|
||||
|
||||
public static DialogListDialog decode(NBTCompound compound, PacketWrapper<?> wrapper) {
|
||||
CommonDialogData common = CommonDialogData.decode(compound, wrapper);
|
||||
MappedEntityRefSet<Dialog> dialogs = compound.getOrThrow("dialogs", MappedEntitySet::decodeRefSet, wrapper);
|
||||
ActionButton action = compound.getOrNull("exit_action", ActionButton::decode, wrapper);
|
||||
int columns = compound.getNumberTagValueOrDefault("columns", 2).intValue();
|
||||
int buttonWidth = compound.getNumberTagValueOrDefault("button_width", 150).intValue();
|
||||
return new DialogListDialog(null, common, dialogs, action, columns, buttonWidth);
|
||||
}
|
||||
|
||||
public static void encode(NBTCompound compound, PacketWrapper<?> wrapper, DialogListDialog dialog) {
|
||||
CommonDialogData.encode(compound, wrapper, dialog.common);
|
||||
compound.set("dialogs", dialog.dialogs, MappedEntitySet::encodeRefSet, wrapper);
|
||||
if (dialog.exitAction != null) {
|
||||
compound.set("exit_action", dialog.exitAction, ActionButton::encode, wrapper);
|
||||
}
|
||||
if (dialog.columns != 2) {
|
||||
compound.setTag("columns", new NBTInt(dialog.columns));
|
||||
}
|
||||
if (dialog.buttonWidth != 150) {
|
||||
compound.setTag("button_width", new NBTInt(dialog.buttonWidth));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog copy(@Nullable TypesBuilderData newData) {
|
||||
return new DialogListDialog(newData, this.common, this.dialogs, this.exitAction, this.columns, this.buttonWidth);
|
||||
}
|
||||
|
||||
public CommonDialogData getCommon() {
|
||||
return this.common;
|
||||
}
|
||||
|
||||
public MappedEntityRefSet<Dialog> getDialogs() {
|
||||
return this.dialogs;
|
||||
}
|
||||
|
||||
public @Nullable ActionButton getExitAction() {
|
||||
return this.exitAction;
|
||||
}
|
||||
|
||||
public int getColumns() {
|
||||
return this.columns;
|
||||
}
|
||||
|
||||
public int getButtonWidth() {
|
||||
return this.buttonWidth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialogType<?> getType() {
|
||||
return DialogTypes.DIALOG_LIST;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deepEquals(Object obj) {
|
||||
if (!(obj instanceof DialogListDialog)) return false;
|
||||
if (!super.equals(obj)) return false;
|
||||
DialogListDialog that = (DialogListDialog) obj;
|
||||
if (this.columns != that.columns) return false;
|
||||
if (this.buttonWidth != that.buttonWidth) return false;
|
||||
if (!this.common.equals(that.common)) return false;
|
||||
if (!this.dialogs.equals(that.dialogs)) return false;
|
||||
return Objects.equals(this.exitAction, that.exitAction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deepHashCode() {
|
||||
return Objects.hash(super.hashCode(), this.common, this.dialogs, this.exitAction, this.columns, this.buttonWidth);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.mapper.MappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public interface DialogType<T extends Dialog> extends MappedEntity {
|
||||
|
||||
T decode(NBTCompound compound, PacketWrapper<?> wrapper);
|
||||
|
||||
void encode(NBTCompound compound, PacketWrapper<?> wrapper, T dialog);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.util.NbtMapDecoder;
|
||||
import com.github.retrooper.packetevents.protocol.util.NbtMapEncoder;
|
||||
import com.github.retrooper.packetevents.util.mappings.VersionedRegistry;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public final class DialogTypes {
|
||||
|
||||
private static final VersionedRegistry<DialogType<?>> REGISTRY = new VersionedRegistry<>("dialog_type");
|
||||
|
||||
private DialogTypes() {
|
||||
}
|
||||
|
||||
public static VersionedRegistry<DialogType<?>> getRegistry() {
|
||||
return REGISTRY;
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static <T extends Dialog> DialogType<T> define(String name, NbtMapDecoder<T> decoder, NbtMapEncoder<T> encoder) {
|
||||
return REGISTRY.define(name, data -> new StaticDialogType<>(data, decoder, encoder));
|
||||
}
|
||||
|
||||
public static final DialogType<NoticeDialog> NOTICE = define("notice",
|
||||
NoticeDialog::decode, NoticeDialog::encode);
|
||||
public static final DialogType<ServerLinksDialog> SERVER_LINKS = define("server_links",
|
||||
ServerLinksDialog::decode, ServerLinksDialog::encode);
|
||||
public static final DialogType<DialogListDialog> DIALOG_LIST = define("dialog_list",
|
||||
DialogListDialog::decode, DialogListDialog::encode);
|
||||
public static final DialogType<MultiActionDialog> MULTI_ACTION = define("multi_action",
|
||||
MultiActionDialog::decode, MultiActionDialog::encode);
|
||||
public static final DialogType<ConfirmationDialog> CONFIRMATION = define("confirmation",
|
||||
ConfirmationDialog::decode, ConfirmationDialog::encode);
|
||||
|
||||
static {
|
||||
REGISTRY.unloadMappings();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.dialog.button.ActionButton;
|
||||
import com.github.retrooper.packetevents.protocol.dialog.button.CommonButtonData;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.MappedEntitySet;
|
||||
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.jspecify.annotations.NullMarked;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
@NullMarked
|
||||
public final class Dialogs {
|
||||
|
||||
private static final ActionButton DEFAULT_BACK_BUTTON = new ActionButton(
|
||||
new CommonButtonData(Component.translatable("gui.back"), null, 200),
|
||||
null);
|
||||
|
||||
private static final VersionedRegistry<Dialog> REGISTRY = new VersionedRegistry<>("dialog");
|
||||
|
||||
private Dialogs() {
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static Dialog define(String name, Dialog dialog) {
|
||||
return REGISTRY.define(name, dialog::copy);
|
||||
}
|
||||
|
||||
public static VersionedRegistry<Dialog> getRegistry() {
|
||||
return REGISTRY;
|
||||
}
|
||||
|
||||
public static final Dialog SERVER_LINKS = define("server_links", new ServerLinksDialog(
|
||||
new CommonDialogData(
|
||||
Component.translatable("menu.server_links.title"),
|
||||
Component.translatable("menu.server_links"),
|
||||
true,
|
||||
true,
|
||||
DialogAction.CLOSE,
|
||||
Collections.emptyList(),
|
||||
Collections.emptyList()
|
||||
),
|
||||
DEFAULT_BACK_BUTTON,
|
||||
1,
|
||||
310
|
||||
));
|
||||
public static final Dialog CUSTOM_OPTIONS = define("custom_options", new DialogListDialog(
|
||||
new CommonDialogData(
|
||||
Component.translatable("menu.custom_options.title"),
|
||||
Component.translatable("menu.custom_options"),
|
||||
true,
|
||||
true,
|
||||
DialogAction.CLOSE,
|
||||
Collections.emptyList(),
|
||||
Collections.emptyList()
|
||||
),
|
||||
new MappedEntitySet<>(new ResourceLocation("pause_screen_additions")),
|
||||
DEFAULT_BACK_BUTTON,
|
||||
1,
|
||||
310
|
||||
));
|
||||
public static final Dialog QUICK_ACTIONS = define("quick_actions", new DialogListDialog(
|
||||
new CommonDialogData(
|
||||
Component.translatable("menu.quick_actions.title"),
|
||||
Component.translatable("menu.quick_actions"),
|
||||
true,
|
||||
true,
|
||||
DialogAction.CLOSE,
|
||||
Collections.emptyList(),
|
||||
Collections.emptyList()
|
||||
),
|
||||
new MappedEntitySet<>(new ResourceLocation("quick_actions")),
|
||||
DEFAULT_BACK_BUTTON,
|
||||
1,
|
||||
310
|
||||
));
|
||||
|
||||
static {
|
||||
REGISTRY.unloadMappings();
|
||||
}
|
||||
}
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.dialog.button.ActionButton;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.AbstractMappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTInt;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@NullMarked
|
||||
public class MultiActionDialog extends AbstractMappedEntity implements Dialog {
|
||||
|
||||
private final CommonDialogData common;
|
||||
private final List<ActionButton> actions;
|
||||
private final @Nullable ActionButton exitAction;
|
||||
private final int columns;
|
||||
|
||||
public MultiActionDialog(
|
||||
CommonDialogData common,
|
||||
List<ActionButton> actions,
|
||||
@Nullable ActionButton exitAction,
|
||||
int columns
|
||||
) {
|
||||
this(null, common, actions, exitAction, columns);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public MultiActionDialog(
|
||||
@Nullable TypesBuilderData data,
|
||||
CommonDialogData common,
|
||||
List<ActionButton> actions,
|
||||
@Nullable ActionButton exitAction,
|
||||
int columns
|
||||
) {
|
||||
super(data);
|
||||
this.common = common;
|
||||
this.actions = actions;
|
||||
this.exitAction = exitAction;
|
||||
this.columns = columns;
|
||||
}
|
||||
|
||||
public static MultiActionDialog decode(NBTCompound compound, PacketWrapper<?> wrapper) {
|
||||
CommonDialogData common = CommonDialogData.decode(compound, wrapper);
|
||||
List<ActionButton> actions = compound.getListOrThrow("actions", ActionButton::decode, wrapper);
|
||||
ActionButton action = compound.getOrNull("exit_action", ActionButton::decode, wrapper);
|
||||
int columns = compound.getNumberTagValueOrDefault("columns", 2).intValue();
|
||||
int buttonWidth = compound.getNumberTagValueOrDefault("button_width", 150).intValue();
|
||||
return new MultiActionDialog(null, common, actions, action, columns);
|
||||
}
|
||||
|
||||
public static void encode(NBTCompound compound, PacketWrapper<?> wrapper, MultiActionDialog dialog) {
|
||||
CommonDialogData.encode(compound, wrapper, dialog.common);
|
||||
compound.setList("actions", dialog.actions, ActionButton::encode, wrapper);
|
||||
if (dialog.exitAction != null) {
|
||||
compound.set("exit_action", dialog.exitAction, ActionButton::encode, wrapper);
|
||||
}
|
||||
if (dialog.columns != 2) {
|
||||
compound.setTag("columns", new NBTInt(dialog.columns));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog copy(@Nullable TypesBuilderData newData) {
|
||||
return new MultiActionDialog(newData, this.common, this.actions, this.exitAction, this.columns);
|
||||
}
|
||||
|
||||
public CommonDialogData getCommon() {
|
||||
return this.common;
|
||||
}
|
||||
|
||||
public List<ActionButton> getActions() {
|
||||
return this.actions;
|
||||
}
|
||||
|
||||
public @Nullable ActionButton getExitAction() {
|
||||
return this.exitAction;
|
||||
}
|
||||
|
||||
public int getColumns() {
|
||||
return this.columns;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialogType<?> getType() {
|
||||
return DialogTypes.MULTI_ACTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deepEquals(Object obj) {
|
||||
if (!(obj instanceof MultiActionDialog)) return false;
|
||||
if (!super.equals(obj)) return false;
|
||||
MultiActionDialog that = (MultiActionDialog) obj;
|
||||
if (this.columns != that.columns) return false;
|
||||
if (!this.common.equals(that.common)) return false;
|
||||
if (!this.actions.equals(that.actions)) return false;
|
||||
return Objects.equals(this.exitAction, that.exitAction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deepHashCode() {
|
||||
return Objects.hash(super.hashCode(), this.common, this.actions, this.exitAction, this.columns);
|
||||
}
|
||||
}
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.dialog.button.ActionButton;
|
||||
import com.github.retrooper.packetevents.protocol.dialog.button.CommonButtonData;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.AbstractMappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
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 org.jspecify.annotations.NullMarked;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@NullMarked
|
||||
public class NoticeDialog extends AbstractMappedEntity implements Dialog {
|
||||
|
||||
public static final ActionButton DEFAULT_ACTION = new ActionButton(
|
||||
new CommonButtonData(Component.translatable("gui.ok"), null, 150),
|
||||
null
|
||||
);
|
||||
|
||||
private final CommonDialogData common;
|
||||
private final ActionButton action;
|
||||
|
||||
public NoticeDialog(CommonDialogData common, ActionButton action) {
|
||||
this(null, common, action);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public NoticeDialog(@Nullable TypesBuilderData data, CommonDialogData common, ActionButton action) {
|
||||
super(data);
|
||||
this.common = common;
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
public static NoticeDialog decode(NBTCompound compound, PacketWrapper<?> wrapper) {
|
||||
CommonDialogData common = CommonDialogData.decode(compound, wrapper);
|
||||
ActionButton action = compound.getOr("action", ActionButton::decode, DEFAULT_ACTION, wrapper);
|
||||
return new NoticeDialog(null, common, action);
|
||||
}
|
||||
|
||||
public static void encode(NBTCompound compound, PacketWrapper<?> wrapper, NoticeDialog dialog) {
|
||||
CommonDialogData.encode(compound, wrapper, dialog.common);
|
||||
if (dialog.action != DEFAULT_ACTION) {
|
||||
compound.set("action", dialog.action, ActionButton::encode, wrapper);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog copy(@Nullable TypesBuilderData newData) {
|
||||
return new NoticeDialog(newData, this.common, this.action);
|
||||
}
|
||||
|
||||
public CommonDialogData getCommon() {
|
||||
return this.common;
|
||||
}
|
||||
|
||||
public ActionButton getAction() {
|
||||
return this.action;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialogType<?> getType() {
|
||||
return DialogTypes.NOTICE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deepEquals(Object obj) {
|
||||
if (!(obj instanceof NoticeDialog)) return false;
|
||||
if (!super.equals(obj)) return false;
|
||||
NoticeDialog that = (NoticeDialog) obj;
|
||||
if (!this.common.equals(that.common)) return false;
|
||||
return this.action.equals(that.action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deepHashCode() {
|
||||
return Objects.hash(super.hashCode(), this.common, this.action);
|
||||
}
|
||||
}
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.dialog.button.ActionButton;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.AbstractMappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTInt;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@NullMarked
|
||||
public class ServerLinksDialog extends AbstractMappedEntity implements Dialog {
|
||||
|
||||
private final CommonDialogData common;
|
||||
private final @Nullable ActionButton exitAction;
|
||||
private final int columns;
|
||||
private final int buttonWidth;
|
||||
|
||||
public ServerLinksDialog(
|
||||
CommonDialogData common,
|
||||
@Nullable ActionButton exitAction,
|
||||
int columns, int buttonWidth
|
||||
) {
|
||||
this(null, common, exitAction, columns, buttonWidth);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public ServerLinksDialog(
|
||||
@Nullable TypesBuilderData data,
|
||||
CommonDialogData common,
|
||||
@Nullable ActionButton exitAction,
|
||||
int columns, int buttonWidth
|
||||
) {
|
||||
super(data);
|
||||
this.common = common;
|
||||
this.exitAction = exitAction;
|
||||
this.columns = columns;
|
||||
this.buttonWidth = buttonWidth;
|
||||
}
|
||||
|
||||
public static ServerLinksDialog decode(NBTCompound compound, PacketWrapper<?> wrapper) {
|
||||
CommonDialogData common = CommonDialogData.decode(compound, wrapper);
|
||||
ActionButton action = compound.getOrNull("exit_action", ActionButton::decode, wrapper);
|
||||
int columns = compound.getNumberTagValueOrDefault("columns", 2).intValue();
|
||||
int buttonWidth = compound.getNumberTagValueOrDefault("button_width", 150).intValue();
|
||||
return new ServerLinksDialog(null, common, action, columns, buttonWidth);
|
||||
}
|
||||
|
||||
public static void encode(NBTCompound compound, PacketWrapper<?> wrapper, ServerLinksDialog dialog) {
|
||||
CommonDialogData.encode(compound, wrapper, dialog.common);
|
||||
if (dialog.exitAction != null) {
|
||||
compound.set("exit_action", dialog.exitAction, ActionButton::encode, wrapper);
|
||||
}
|
||||
if (dialog.columns != 2) {
|
||||
compound.setTag("columns", new NBTInt(dialog.columns));
|
||||
}
|
||||
if (dialog.buttonWidth != 150) {
|
||||
compound.setTag("button_width", new NBTInt(dialog.buttonWidth));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog copy(@Nullable TypesBuilderData newData) {
|
||||
return new ServerLinksDialog(newData, this.common, this.exitAction, this.columns, this.buttonWidth);
|
||||
}
|
||||
|
||||
public CommonDialogData getCommon() {
|
||||
return this.common;
|
||||
}
|
||||
|
||||
public @Nullable ActionButton getExitAction() {
|
||||
return this.exitAction;
|
||||
}
|
||||
|
||||
public int getColumns() {
|
||||
return this.columns;
|
||||
}
|
||||
|
||||
public int getButtonWidth() {
|
||||
return this.buttonWidth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialogType<?> getType() {
|
||||
return DialogTypes.SERVER_LINKS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deepEquals(Object obj) {
|
||||
if (!(obj instanceof ServerLinksDialog)) return false;
|
||||
if (!super.equals(obj)) return false;
|
||||
ServerLinksDialog that = (ServerLinksDialog) obj;
|
||||
if (this.columns != that.columns) return false;
|
||||
if (this.buttonWidth != that.buttonWidth) return false;
|
||||
if (!this.common.equals(that.common)) return false;
|
||||
return Objects.equals(this.exitAction, that.exitAction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deepHashCode() {
|
||||
return Objects.hash(super.hashCode(), this.common, this.exitAction, this.columns, this.buttonWidth);
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.mapper.AbstractMappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.util.NbtMapDecoder;
|
||||
import com.github.retrooper.packetevents.protocol.util.NbtMapEncoder;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class StaticDialogType<T extends Dialog> extends AbstractMappedEntity implements DialogType<T> {
|
||||
|
||||
private final NbtMapDecoder<T> decoder;
|
||||
private final NbtMapEncoder<T> encoder;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public StaticDialogType(@Nullable TypesBuilderData data, NbtMapDecoder<T> decoder, NbtMapEncoder<T> encoder) {
|
||||
super(data);
|
||||
this.decoder = decoder;
|
||||
this.encoder = encoder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T decode(NBTCompound compound, PacketWrapper<?> wrapper) {
|
||||
return this.decoder.decode(compound, wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encode(NBTCompound compound, PacketWrapper<?> wrapper, T dialog) {
|
||||
this.encoder.encode(compound, wrapper, dialog);
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog.action;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public interface Action {
|
||||
|
||||
static Action decode(NBT nbt, PacketWrapper<?> wrapper) {
|
||||
NBTCompound compound = (NBTCompound) nbt;
|
||||
String typeName = compound.getStringTagValueOrThrow("type");
|
||||
ActionType<?> action = ActionTypes.getRegistry().getByNameOrThrow(typeName);
|
||||
return action.decode(compound, wrapper);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked") // not unchecked
|
||||
static NBT encode(PacketWrapper<?> wrapper, Action action) {
|
||||
NBTCompound compound = new NBTCompound();
|
||||
compound.set("type", action.getType().getName(), ResourceLocation::encode, wrapper);
|
||||
((ActionType<? super Action>) action.getType()).encode(compound, wrapper, action);
|
||||
return compound;
|
||||
}
|
||||
|
||||
ActionType<?> getType();
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog.action;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.mapper.MappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public interface ActionType<T extends Action> extends MappedEntity {
|
||||
|
||||
T decode(NBTCompound compound, PacketWrapper<?> wrapper);
|
||||
|
||||
void encode(NBTCompound compound, PacketWrapper<?> wrapper, T action);
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog.action;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.util.NbtMapDecoder;
|
||||
import com.github.retrooper.packetevents.protocol.util.NbtMapEncoder;
|
||||
import com.github.retrooper.packetevents.util.mappings.VersionedRegistry;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public final class ActionTypes {
|
||||
|
||||
private static final VersionedRegistry<ActionType<?>> REGISTRY = new VersionedRegistry<>("dialog_action_type");
|
||||
|
||||
private ActionTypes() {
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static <T extends Action> ActionType<T> define(String name, NbtMapDecoder<T> decoder, NbtMapEncoder<T> encoder) {
|
||||
return REGISTRY.define(name, data -> new StaticActionType<>(data, decoder, encoder));
|
||||
}
|
||||
|
||||
public static final ActionType<StaticAction> OPEN_URL = define("open_url",
|
||||
StaticAction::decode, StaticAction::encode);
|
||||
public static final ActionType<StaticAction> RUN_COMMAND = define("run_command",
|
||||
StaticAction::decode, StaticAction::encode);
|
||||
public static final ActionType<StaticAction> SUGGEST_COMMAND = define("suggest_command",
|
||||
StaticAction::decode, StaticAction::encode);
|
||||
public static final ActionType<StaticAction> SHOW_DIALOG = define("show_dialog",
|
||||
StaticAction::decode, StaticAction::encode);
|
||||
public static final ActionType<StaticAction> CHANGE_PAGE = define("change_page",
|
||||
StaticAction::decode, StaticAction::encode);
|
||||
public static final ActionType<StaticAction> COPY_TO_CLIPBOARD = define("copy_to_clipboard",
|
||||
StaticAction::decode, StaticAction::encode);
|
||||
public static final ActionType<StaticAction> CUSTOM = define("custom",
|
||||
StaticAction::decode, StaticAction::encode);
|
||||
public static final ActionType<DynamicRunCommandAction> DYNAMIC_RUN_COMMAND = define("dynamic/run_command",
|
||||
DynamicRunCommandAction::decode, DynamicRunCommandAction::encode);
|
||||
public static final ActionType<DynamicCustomAction> DYNAMIC_CUSTOM = define("dynamic/custom",
|
||||
DynamicCustomAction::decode, DynamicCustomAction::encode);
|
||||
|
||||
public static VersionedRegistry<ActionType<?>> getRegistry() {
|
||||
return REGISTRY;
|
||||
}
|
||||
|
||||
static {
|
||||
REGISTRY.unloadMappings();
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog.action;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* This uses the same format as command function macros.
|
||||
*/
|
||||
@NullMarked
|
||||
public class DialogTemplate {
|
||||
|
||||
private final String raw;
|
||||
|
||||
public DialogTemplate(String raw) {
|
||||
this.raw = raw;
|
||||
}
|
||||
|
||||
public static DialogTemplate decode(NBT nbt, PacketWrapper<?> wrapper) {
|
||||
return new DialogTemplate(((NBTString) nbt).getValue());
|
||||
}
|
||||
|
||||
public static NBT encode(PacketWrapper<?> wrapper, DialogTemplate template) {
|
||||
return new NBTString(template.raw);
|
||||
}
|
||||
|
||||
public String getRaw() {
|
||||
return this.raw;
|
||||
}
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog.action;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public class DynamicCustomAction implements Action {
|
||||
|
||||
private final ResourceLocation id;
|
||||
private final @Nullable NBTCompound additions;
|
||||
|
||||
public DynamicCustomAction(ResourceLocation id, @Nullable NBTCompound additions) {
|
||||
this.id = id;
|
||||
this.additions = additions;
|
||||
}
|
||||
|
||||
public static DynamicCustomAction decode(NBTCompound compound, PacketWrapper<?> wrapper) {
|
||||
ResourceLocation id = compound.getOrThrow("id", ResourceLocation::decode, wrapper);
|
||||
NBTCompound additions = compound.getCompoundTagOrNull("additions");
|
||||
return new DynamicCustomAction(id, additions);
|
||||
}
|
||||
|
||||
public static void encode(NBTCompound compound, PacketWrapper<?> wrapper, DynamicCustomAction action) {
|
||||
compound.set("id", action.id, ResourceLocation::encode, wrapper);
|
||||
if (action.additions != null) {
|
||||
compound.setTag("additions", action.additions);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionType<?> getType() {
|
||||
return ActionTypes.DYNAMIC_CUSTOM;
|
||||
}
|
||||
|
||||
public ResourceLocation getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public @Nullable NBTCompound getAdditions() {
|
||||
return this.additions;
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog.action;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class DynamicRunCommandAction implements Action {
|
||||
|
||||
private final DialogTemplate template;
|
||||
|
||||
public DynamicRunCommandAction(DialogTemplate template) {
|
||||
this.template = template;
|
||||
}
|
||||
|
||||
public static DynamicRunCommandAction decode(NBTCompound compound, PacketWrapper<?> wrapper) {
|
||||
DialogTemplate template = compound.getOrThrow("template", DialogTemplate::decode, wrapper);
|
||||
return new DynamicRunCommandAction(template);
|
||||
}
|
||||
|
||||
public static void encode(NBTCompound compound, PacketWrapper<?> wrapper, DynamicRunCommandAction action) {
|
||||
compound.set("template", action.template, DialogTemplate::encode, wrapper);
|
||||
}
|
||||
|
||||
public DialogTemplate getTemplate() {
|
||||
return this.template;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionType<?> getType() {
|
||||
return ActionTypes.DYNAMIC_RUN_COMMAND;
|
||||
}
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog.action;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.chat.clickevent.ClickEvent;
|
||||
import com.github.retrooper.packetevents.protocol.chat.clickevent.ClickEventAction;
|
||||
import com.github.retrooper.packetevents.protocol.chat.clickevent.ClickEventActions;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class StaticAction implements Action {
|
||||
|
||||
private final ActionType<?> actionType;
|
||||
private final ClickEvent clickEvent;
|
||||
|
||||
public StaticAction(ClickEvent clickEvent) {
|
||||
if (!clickEvent.getAction().isAllowFromServer()) {
|
||||
throw new IllegalArgumentException("Can't create action for unreadable "
|
||||
+ "click event with action " + clickEvent.getAction());
|
||||
}
|
||||
this.actionType = ActionTypes.getRegistry().getByNameOrThrow(clickEvent.getAction().getName());
|
||||
this.clickEvent = clickEvent;
|
||||
}
|
||||
|
||||
public static StaticAction decode(NBTCompound compound, PacketWrapper<?> wrapper) {
|
||||
String actionName = compound.getStringTagValueOrThrow("type");
|
||||
ClickEventAction<?> action = ClickEventActions.getRegistry().getByNameOrThrow(actionName);
|
||||
ClickEvent clickEvent = action.decode(compound, wrapper);
|
||||
return new StaticAction(clickEvent);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void encode(NBTCompound compound, PacketWrapper<?> wrapper, StaticAction action) {
|
||||
((ClickEventAction<? super ClickEvent>) action.clickEvent.getAction()).encode(compound, wrapper, action.clickEvent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionType<?> getType() {
|
||||
return this.actionType;
|
||||
}
|
||||
|
||||
public ClickEvent getClickEvent() {
|
||||
return this.clickEvent;
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog.action;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.mapper.AbstractMappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.util.NbtMapDecoder;
|
||||
import com.github.retrooper.packetevents.protocol.util.NbtMapEncoder;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class StaticActionType<T extends Action> extends AbstractMappedEntity implements ActionType<T> {
|
||||
|
||||
private final NbtMapDecoder<T> decoder;
|
||||
private final NbtMapEncoder<T> encoder;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public StaticActionType(@Nullable TypesBuilderData data, NbtMapDecoder<T> decoder, NbtMapEncoder<T> encoder) {
|
||||
super(data);
|
||||
this.decoder = decoder;
|
||||
this.encoder = encoder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T decode(NBTCompound compound, PacketWrapper<?> wrapper) {
|
||||
return this.decoder.decode(compound, wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encode(NBTCompound compound, PacketWrapper<?> wrapper, T action) {
|
||||
this.encoder.encode(compound, wrapper, action);
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog.body;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public interface DialogBody {
|
||||
|
||||
static DialogBody decode(NBT nbt, PacketWrapper<?> wrapper) {
|
||||
NBTCompound compound = (NBTCompound) nbt;
|
||||
String typeName = compound.getStringTagValueOrThrow("type");
|
||||
DialogBodyType<?> type = DialogBodyTypes.getRegistry().getByNameOrThrow(typeName);
|
||||
return type.decode(compound, wrapper);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked") // not unchecked
|
||||
static NBT encode(PacketWrapper<?> wrapper, DialogBody body) {
|
||||
NBTCompound compound = new NBTCompound();
|
||||
compound.set("type", body.getType().getName(), ResourceLocation::encode, wrapper);
|
||||
((DialogBodyType<? super DialogBody>) body.getType()).encode(compound, wrapper, body);
|
||||
return compound;
|
||||
}
|
||||
|
||||
DialogBodyType<?> getType();
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog.body;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.mapper.MappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public interface DialogBodyType<T extends DialogBody> extends MappedEntity {
|
||||
|
||||
T decode(NBTCompound compound, PacketWrapper<?> wrapper);
|
||||
|
||||
void encode(NBTCompound compound, PacketWrapper<?> wrapper, T dialogBody);
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog.body;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.util.NbtMapDecoder;
|
||||
import com.github.retrooper.packetevents.protocol.util.NbtMapEncoder;
|
||||
import com.github.retrooper.packetevents.util.mappings.VersionedRegistry;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public final class DialogBodyTypes {
|
||||
|
||||
private static final VersionedRegistry<DialogBodyType<?>> REGISTRY = new VersionedRegistry<>("dialog_body_type");
|
||||
|
||||
private DialogBodyTypes() {
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static <T extends DialogBody> DialogBodyType<T> define(String name, NbtMapDecoder<T> decoder, NbtMapEncoder<T> encoder) {
|
||||
return REGISTRY.define(name, data -> new StaticDialogBodyType<>(data, decoder, encoder));
|
||||
}
|
||||
|
||||
public static VersionedRegistry<DialogBodyType<?>> getRegistry() {
|
||||
return REGISTRY;
|
||||
}
|
||||
|
||||
public static final DialogBodyType<ItemDialogBody> ITEM = define("item",
|
||||
ItemDialogBody::decode, ItemDialogBody::encode);
|
||||
public static final DialogBodyType<PlainMessageDialogBody> PLAIN_MESSAGE = define("plain_message",
|
||||
PlainMessageDialogBody::decode, PlainMessageDialogBody::encode);
|
||||
|
||||
static {
|
||||
REGISTRY.unloadMappings();
|
||||
}
|
||||
}
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog.body;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTByte;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTInt;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public class ItemDialogBody implements DialogBody {
|
||||
|
||||
private final ItemStack item;
|
||||
private final @Nullable PlainMessage description;
|
||||
private final boolean showDecorations;
|
||||
private final boolean showTooltip;
|
||||
private final int width;
|
||||
private final int height;
|
||||
|
||||
public ItemDialogBody(
|
||||
ItemStack item, @Nullable PlainMessage description,
|
||||
boolean showDecorations, boolean showTooltip,
|
||||
int width, int height
|
||||
) {
|
||||
this.item = item;
|
||||
this.description = description;
|
||||
this.showDecorations = showDecorations;
|
||||
this.showTooltip = showTooltip;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public static ItemDialogBody decode(NBTCompound compound, PacketWrapper<?> wrapper) {
|
||||
ItemStack item = compound.getOrThrow("item", ItemStack::decode, wrapper);
|
||||
PlainMessage description = compound.getOrNull("description", PlainMessage::decode, wrapper);
|
||||
boolean showDecorations = compound.getBooleanOr("show_decorations", true);
|
||||
boolean showTooltip = compound.getBooleanOr("show_tooltip", true);
|
||||
int width = compound.getNumberTagValueOrDefault("width", 16).intValue();
|
||||
int height = compound.getNumberTagValueOrDefault("height", 16).intValue();
|
||||
return new ItemDialogBody(item, description, showDecorations, showTooltip, width, height);
|
||||
}
|
||||
|
||||
public static void encode(NBTCompound compound, PacketWrapper<?> wrapper, ItemDialogBody body) {
|
||||
compound.set("item", body.item, ItemStack::encode, wrapper);
|
||||
if (body.description != null) {
|
||||
compound.set("description", body.description, PlainMessage::encode, wrapper);
|
||||
}
|
||||
if (!body.showDecorations) {
|
||||
compound.setTag("show_decorations", new NBTByte(false));
|
||||
}
|
||||
if (!body.showTooltip) {
|
||||
compound.setTag("show_tooltip", new NBTByte(false));
|
||||
}
|
||||
if (body.width != 16) {
|
||||
compound.setTag("width", new NBTInt(body.width));
|
||||
}
|
||||
if (body.height != 16) {
|
||||
compound.setTag("height", new NBTInt(body.height));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialogBodyType<?> getType() {
|
||||
return DialogBodyTypes.ITEM;
|
||||
}
|
||||
|
||||
public ItemStack getItem() {
|
||||
return this.item;
|
||||
}
|
||||
|
||||
public @Nullable PlainMessage getDescription() {
|
||||
return this.description;
|
||||
}
|
||||
|
||||
public boolean isShowDecorations() {
|
||||
return this.showDecorations;
|
||||
}
|
||||
|
||||
public boolean isShowTooltip() {
|
||||
return this.showTooltip;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return this.width;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return this.height;
|
||||
}
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog.body;
|
||||
|
||||
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.util.adventure.AdventureSerializer;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class PlainMessage {
|
||||
|
||||
private final Component contents;
|
||||
private final int width;
|
||||
|
||||
public PlainMessage(Component contents, int width) {
|
||||
this.contents = contents;
|
||||
this.width = width;
|
||||
}
|
||||
|
||||
public static PlainMessage decode(NBT nbt, PacketWrapper<?> wrapper) {
|
||||
return decode((NBTCompound) nbt, wrapper);
|
||||
}
|
||||
|
||||
public static PlainMessage decode(NBTCompound compound, PacketWrapper<?> wrapper) {
|
||||
Component contents = compound.getOrThrow("contents", AdventureSerializer.serializer(wrapper), wrapper);
|
||||
int width = compound.getNumberTagValueOrDefault("width", 200).intValue();
|
||||
return new PlainMessage(contents, width);
|
||||
}
|
||||
|
||||
public static NBT encode(PacketWrapper<?> wrapper, PlainMessage message) {
|
||||
NBTCompound compound = new NBTCompound();
|
||||
encode(compound, wrapper, message);
|
||||
return compound;
|
||||
}
|
||||
|
||||
public static void encode(NBTCompound compound, PacketWrapper<?> wrapper, PlainMessage message) {
|
||||
compound.set("contents", message.contents, AdventureSerializer.serializer(wrapper), wrapper);
|
||||
if (message.width != 200) {
|
||||
compound.setTag("width", new NBTInt(message.width));
|
||||
}
|
||||
}
|
||||
|
||||
public Component getContents() {
|
||||
return this.contents;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return this.width;
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog.body;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class PlainMessageDialogBody implements DialogBody {
|
||||
|
||||
private final PlainMessage message;
|
||||
|
||||
public PlainMessageDialogBody(PlainMessage message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public static PlainMessageDialogBody decode(NBTCompound compound, PacketWrapper<?> wrapper) {
|
||||
return new PlainMessageDialogBody(PlainMessage.decode(compound, wrapper));
|
||||
}
|
||||
|
||||
public static void encode(NBTCompound compound, PacketWrapper<?> wrapper, PlainMessageDialogBody body) {
|
||||
PlainMessage.encode(compound, wrapper, body.message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialogBodyType<?> getType() {
|
||||
return DialogBodyTypes.PLAIN_MESSAGE;
|
||||
}
|
||||
|
||||
public PlainMessage getMessage() {
|
||||
return this.message;
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog.body;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.mapper.AbstractMappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.util.NbtMapDecoder;
|
||||
import com.github.retrooper.packetevents.protocol.util.NbtMapEncoder;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class StaticDialogBodyType<T extends DialogBody> extends AbstractMappedEntity implements DialogBodyType<T> {
|
||||
|
||||
private final NbtMapDecoder<T> decoder;
|
||||
private final NbtMapEncoder<T> encoder;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public StaticDialogBodyType(@Nullable TypesBuilderData data, NbtMapDecoder<T> decoder, NbtMapEncoder<T> encoder) {
|
||||
super(data);
|
||||
this.decoder = decoder;
|
||||
this.encoder = encoder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T decode(NBTCompound compound, PacketWrapper<?> wrapper) {
|
||||
return this.decoder.decode(compound, wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encode(NBTCompound compound, PacketWrapper<?> wrapper, T dialogBody) {
|
||||
this.encoder.encode(compound, wrapper, dialogBody);
|
||||
}
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog.button;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.dialog.action.Action;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public class ActionButton {
|
||||
|
||||
private final CommonButtonData button;
|
||||
private final @Nullable Action action;
|
||||
|
||||
public ActionButton(CommonButtonData button, @Nullable Action action) {
|
||||
this.button = button;
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
public static ActionButton decode(NBT nbt, PacketWrapper<?> wrapper) {
|
||||
NBTCompound compound = (NBTCompound) nbt;
|
||||
CommonButtonData button = CommonButtonData.decode(compound, wrapper);
|
||||
Action action = compound.getOrNull("action", Action::decode, wrapper);
|
||||
return new ActionButton(button, action);
|
||||
}
|
||||
|
||||
public static NBT encode(PacketWrapper<?> wrapper, ActionButton button) {
|
||||
NBTCompound compound = new NBTCompound();
|
||||
CommonButtonData.encode(compound, wrapper, button.button);
|
||||
if (button.action != null) {
|
||||
compound.set("action", button.action, Action::encode, wrapper);
|
||||
}
|
||||
return compound;
|
||||
}
|
||||
|
||||
public CommonButtonData getButton() {
|
||||
return this.button;
|
||||
}
|
||||
|
||||
public @Nullable Action getAction() {
|
||||
return this.action;
|
||||
}
|
||||
}
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog.button;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTInt;
|
||||
import com.github.retrooper.packetevents.util.adventure.AdventureSerializer;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public class CommonButtonData {
|
||||
|
||||
private final Component label;
|
||||
private final @Nullable Component tooltip;
|
||||
private final int width;
|
||||
|
||||
public CommonButtonData(Component label, @Nullable Component tooltip, int width) {
|
||||
this.label = label;
|
||||
this.tooltip = tooltip;
|
||||
this.width = width;
|
||||
}
|
||||
|
||||
public static CommonButtonData decode(NBTCompound compound, PacketWrapper<?> wrapper) {
|
||||
AdventureSerializer serializer = AdventureSerializer.serializer(wrapper);
|
||||
Component label = compound.getOrThrow("label", serializer, wrapper);
|
||||
Component tooltip = compound.getOrNull("tooltip", serializer, wrapper);
|
||||
int width = compound.getNumberTagValueOrDefault("width", 150).intValue();
|
||||
return new CommonButtonData(label, tooltip, width);
|
||||
}
|
||||
|
||||
public static void encode(NBTCompound compound, PacketWrapper<?> wrapper, CommonButtonData button) {
|
||||
AdventureSerializer serializer = AdventureSerializer.serializer(wrapper);
|
||||
compound.set("label", button.label, serializer, wrapper);
|
||||
if (button.tooltip != null) {
|
||||
compound.set("tooltip", button.tooltip, serializer, wrapper);
|
||||
}
|
||||
if (button.width != 150) {
|
||||
compound.setTag("width", new NBTInt(button.width));
|
||||
}
|
||||
}
|
||||
|
||||
public Component getLabel() {
|
||||
return this.label;
|
||||
}
|
||||
|
||||
public @Nullable Component getTooltip() {
|
||||
return this.tooltip;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return this.width;
|
||||
}
|
||||
}
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog.input;
|
||||
|
||||
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.util.adventure.AdventureSerializer;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class BooleanInputControl implements InputControl {
|
||||
|
||||
private final Component label;
|
||||
private final boolean initial;
|
||||
private final String onTrue;
|
||||
private final String onFalse;
|
||||
|
||||
public BooleanInputControl(Component label, boolean initial, String onTrue, String onFalse) {
|
||||
this.label = label;
|
||||
this.initial = initial;
|
||||
this.onTrue = onTrue;
|
||||
this.onFalse = onFalse;
|
||||
}
|
||||
|
||||
public static BooleanInputControl decode(NBTCompound compound, PacketWrapper<?> wrapper) {
|
||||
Component label = compound.getOrThrow("label", AdventureSerializer.serializer(wrapper), wrapper);
|
||||
boolean initial = compound.getBoolean("initial");
|
||||
String onTrue = compound.getStringTagValueOrDefault("on_true", "true");
|
||||
String onFalse = compound.getStringTagValueOrDefault("on_false", "false");
|
||||
return new BooleanInputControl(label, initial, onTrue, onFalse);
|
||||
}
|
||||
|
||||
public static void encode(NBTCompound compound, PacketWrapper<?> wrapper, BooleanInputControl control) {
|
||||
compound.set("label", control.label, AdventureSerializer.serializer(wrapper), wrapper);
|
||||
if (control.initial) {
|
||||
compound.setTag("initial", new NBTByte(true));
|
||||
}
|
||||
if (!"true".equals(control.onTrue)) {
|
||||
compound.setTag("on_true", new NBTString(control.onTrue));
|
||||
}
|
||||
if (!"false".equals(control.onFalse)) {
|
||||
compound.setTag("on_false", new NBTString(control.onFalse));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputControlType<?> getType() {
|
||||
return InputControlTypes.BOOLEAN;
|
||||
}
|
||||
|
||||
public Component getLabel() {
|
||||
return this.label;
|
||||
}
|
||||
|
||||
public boolean isInitial() {
|
||||
return this.initial;
|
||||
}
|
||||
|
||||
public String getOnTrue() {
|
||||
return this.onTrue;
|
||||
}
|
||||
|
||||
public String getOnFalse() {
|
||||
return this.onFalse;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog.input;
|
||||
|
||||
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.wrapper.PacketWrapper;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class Input {
|
||||
|
||||
private final String key;
|
||||
private final InputControl control;
|
||||
|
||||
public Input(String key, InputControl control) {
|
||||
this.key = key;
|
||||
this.control = control;
|
||||
}
|
||||
|
||||
public static Input decode(NBT nbt, PacketWrapper<?> wrapper) {
|
||||
NBTCompound compound = (NBTCompound) nbt;
|
||||
String key = compound.getStringTagValueOrThrow("key");
|
||||
InputControl control = InputControl.decode(compound, wrapper);
|
||||
return new Input(key, control);
|
||||
}
|
||||
|
||||
public static NBT encode(PacketWrapper<?> wrapper, Input input) {
|
||||
NBTCompound compound = new NBTCompound();
|
||||
compound.setTag("key", new NBTString(input.key));
|
||||
InputControl.encode(compound, wrapper, input.control);
|
||||
return compound;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return this.key;
|
||||
}
|
||||
|
||||
public InputControl getControl() {
|
||||
return this.control;
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog.input;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public interface InputControl {
|
||||
|
||||
static InputControl decode(NBTCompound compound, PacketWrapper<?> wrapper) {
|
||||
String typeName = compound.getStringTagValueOrThrow("type");
|
||||
InputControlType<?> type = InputControlTypes.getRegistry().getByNameOrThrow(typeName);
|
||||
return type.decode(compound, wrapper);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked") // not unchecked
|
||||
static void encode(NBTCompound compound, PacketWrapper<?> wrapper, InputControl control) {
|
||||
compound.set("type", control.getType().getName(), ResourceLocation::encode, wrapper);
|
||||
((InputControlType<? super InputControl>) control.getType()).encode(compound, wrapper, control);
|
||||
}
|
||||
|
||||
InputControlType<?> getType();
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog.input;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.mapper.MappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public interface InputControlType<T extends InputControl> extends MappedEntity {
|
||||
|
||||
T decode(NBTCompound compound, PacketWrapper<?> wrapper);
|
||||
|
||||
void encode(NBTCompound compound, PacketWrapper<?> wrapper, T control);
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog.input;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.util.NbtMapDecoder;
|
||||
import com.github.retrooper.packetevents.protocol.util.NbtMapEncoder;
|
||||
import com.github.retrooper.packetevents.util.mappings.VersionedRegistry;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public final class InputControlTypes {
|
||||
|
||||
private static final VersionedRegistry<InputControlType<?>> REGISTRY = new VersionedRegistry<>("input_control_type");
|
||||
|
||||
private InputControlTypes() {
|
||||
}
|
||||
|
||||
public static VersionedRegistry<InputControlType<?>> getRegistry() {
|
||||
return REGISTRY;
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static <T extends InputControl> InputControlType<T> define(
|
||||
String name, NbtMapDecoder<T> decoder, NbtMapEncoder<T> encoder
|
||||
) {
|
||||
return REGISTRY.define(name, data ->
|
||||
new StaticInputControlType<>(data, decoder, encoder));
|
||||
}
|
||||
|
||||
public static final InputControlType<BooleanInputControl> BOOLEAN = define("boolean",
|
||||
BooleanInputControl::decode, BooleanInputControl::encode);
|
||||
public static final InputControlType<NumberRangeInputControl> NUMBER_RANGE = define("number_range",
|
||||
NumberRangeInputControl::decode, NumberRangeInputControl::encode);
|
||||
public static final InputControlType<SingleOptionInputControl> SINGLE_OPTION = define("single_option",
|
||||
SingleOptionInputControl::decode, SingleOptionInputControl::encode);
|
||||
public static final InputControlType<TextInputControl> TEXT = define("text",
|
||||
TextInputControl::decode, TextInputControl::encode);
|
||||
|
||||
static {
|
||||
REGISTRY.unloadMappings();
|
||||
}
|
||||
}
|
||||
+146
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog.input;
|
||||
|
||||
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.nbt.NBTNumber;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
|
||||
import com.github.retrooper.packetevents.util.adventure.AdventureSerializer;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public class NumberRangeInputControl implements InputControl {
|
||||
|
||||
private final int width;
|
||||
private final Component label;
|
||||
private final String labelFormat;
|
||||
private final RangeInfo rangeInfo;
|
||||
|
||||
public NumberRangeInputControl(int width, Component label, String labelFormat, RangeInfo rangeInfo) {
|
||||
this.width = width;
|
||||
this.label = label;
|
||||
this.labelFormat = labelFormat;
|
||||
this.rangeInfo = rangeInfo;
|
||||
}
|
||||
|
||||
public static NumberRangeInputControl decode(NBTCompound compound, PacketWrapper<?> wrapper) {
|
||||
int width = compound.getNumberTagValueOrDefault("width", 200).intValue();
|
||||
Component label = compound.getOrThrow("label", AdventureSerializer.serializer(wrapper), wrapper);
|
||||
String labelFormat = compound.getStringTagValueOrDefault("label_format", "options.generic_value");
|
||||
RangeInfo rangeInfo = RangeInfo.decode(compound, wrapper);
|
||||
return new NumberRangeInputControl(width, label, labelFormat, rangeInfo);
|
||||
}
|
||||
|
||||
public static void encode(NBTCompound compound, PacketWrapper<?> wrapper, NumberRangeInputControl control) {
|
||||
if (control.width != 200) {
|
||||
compound.setTag("width", new NBTInt(control.width));
|
||||
}
|
||||
compound.set("label", control.label, AdventureSerializer.serializer(wrapper), wrapper);
|
||||
if (!"options.generic_value".equals(control.labelFormat)) {
|
||||
compound.setTag("label_format", new NBTString(control.labelFormat));
|
||||
}
|
||||
RangeInfo.encode(compound, wrapper, control.rangeInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputControlType<?> getType() {
|
||||
return InputControlTypes.NUMBER_RANGE;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return this.width;
|
||||
}
|
||||
|
||||
public Component getLabel() {
|
||||
return this.label;
|
||||
}
|
||||
|
||||
public String getLabelFormat() {
|
||||
return this.labelFormat;
|
||||
}
|
||||
|
||||
public RangeInfo getRangeInfo() {
|
||||
return this.rangeInfo;
|
||||
}
|
||||
|
||||
public static final class RangeInfo {
|
||||
|
||||
private final float start;
|
||||
private final float end;
|
||||
private final @Nullable Float initial;
|
||||
private final @Nullable Float step;
|
||||
|
||||
public RangeInfo(float start, float end, @Nullable Float initial, @Nullable Float step) {
|
||||
if (initial != null) {
|
||||
float min = Math.min(start, end);
|
||||
float max = Math.max(start, end);
|
||||
if (initial < min || initial > max) {
|
||||
throw new IllegalArgumentException("Initial value " + initial
|
||||
+ " is outside of range [" + min + ", " + max + "]");
|
||||
}
|
||||
}
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.initial = initial;
|
||||
this.step = step;
|
||||
}
|
||||
|
||||
public static RangeInfo decode(NBTCompound compound, PacketWrapper<?> wrapper) {
|
||||
float start = compound.getNumberTagValueOrThrow("start").floatValue();
|
||||
float end = compound.getNumberTagValueOrThrow("end").floatValue();
|
||||
NBTNumber initialTag = compound.getNumberTagOrNull("initial");
|
||||
Float initial = initialTag != null ? initialTag.getAsFloat() : null;
|
||||
NBTNumber stepTag = compound.getNumberTagOrNull("step");
|
||||
Float step = stepTag != null ? stepTag.getAsFloat() : null;
|
||||
return new RangeInfo(start, end, initial, step);
|
||||
}
|
||||
|
||||
public static void encode(NBTCompound compound, PacketWrapper<?> wrapper, RangeInfo rangeInfo) {
|
||||
compound.setTag("start", new NBTFloat(rangeInfo.start));
|
||||
compound.setTag("end", new NBTFloat(rangeInfo.end));
|
||||
if (rangeInfo.initial != null) {
|
||||
compound.setTag("initial", new NBTFloat(rangeInfo.initial));
|
||||
}
|
||||
if (rangeInfo.step != null) {
|
||||
compound.setTag("step", new NBTFloat(rangeInfo.step));
|
||||
}
|
||||
}
|
||||
|
||||
public float getStart() {
|
||||
return this.start;
|
||||
}
|
||||
|
||||
public float getEnd() {
|
||||
return this.end;
|
||||
}
|
||||
|
||||
public @Nullable Float getInitial() {
|
||||
return this.initial;
|
||||
}
|
||||
|
||||
public @Nullable Float getStep() {
|
||||
return this.step;
|
||||
}
|
||||
}
|
||||
}
|
||||
+145
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog.input;
|
||||
|
||||
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.NBTInt;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
|
||||
import com.github.retrooper.packetevents.util.adventure.AdventureSerializer;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@NullMarked
|
||||
public class SingleOptionInputControl implements InputControl {
|
||||
|
||||
private final int width;
|
||||
private final List<Entry> options;
|
||||
private final Component label;
|
||||
private final boolean labelVisible;
|
||||
|
||||
public SingleOptionInputControl(int width, List<Entry> options, Component label, boolean labelVisible) {
|
||||
boolean initial = false;
|
||||
for (Entry entry : options) {
|
||||
if (entry.initial) {
|
||||
if (initial) {
|
||||
throw new IllegalArgumentException("Multiple initial values");
|
||||
}
|
||||
initial = true;
|
||||
}
|
||||
}
|
||||
this.width = width;
|
||||
this.options = options;
|
||||
this.label = label;
|
||||
this.labelVisible = labelVisible;
|
||||
}
|
||||
|
||||
public static SingleOptionInputControl decode(NBTCompound compound, PacketWrapper<?> wrapper) {
|
||||
int width = compound.getNumberTagValueOrDefault("width", 200).intValue();
|
||||
List<Entry> options = compound.getListOrThrow("options", Entry::decode, wrapper);
|
||||
Component label = compound.getOrThrow("label", AdventureSerializer.serializer(wrapper), wrapper);
|
||||
boolean labelVisible = compound.getBooleanOr("label_visible", true);
|
||||
return new SingleOptionInputControl(width, options, label, labelVisible);
|
||||
}
|
||||
|
||||
public static void encode(NBTCompound compound, PacketWrapper<?> wrapper, SingleOptionInputControl control) {
|
||||
if (control.width != 200) {
|
||||
compound.setTag("width", new NBTInt(control.width));
|
||||
}
|
||||
compound.setList("options", control.options, Entry::encode, wrapper);
|
||||
compound.set("label", control.label, AdventureSerializer.serializer(wrapper), wrapper);
|
||||
if (!control.labelVisible) {
|
||||
compound.setTag("label_visible", new NBTByte(false));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputControlType<?> getType() {
|
||||
return InputControlTypes.SINGLE_OPTION;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return this.width;
|
||||
}
|
||||
|
||||
public List<Entry> getOptions() {
|
||||
return this.options;
|
||||
}
|
||||
|
||||
public Component getLabel() {
|
||||
return this.label;
|
||||
}
|
||||
|
||||
public boolean isLabelVisible() {
|
||||
return this.labelVisible;
|
||||
}
|
||||
|
||||
public static final class Entry {
|
||||
|
||||
private final String id;
|
||||
private final @Nullable Component display;
|
||||
private final boolean initial;
|
||||
|
||||
public Entry(String id, @Nullable Component display, boolean initial) {
|
||||
this.id = id;
|
||||
this.display = display;
|
||||
this.initial = initial;
|
||||
}
|
||||
|
||||
public static Entry decode(NBT nbt, PacketWrapper<?> wrapper) {
|
||||
if (nbt instanceof NBTString) {
|
||||
return new Entry(((NBTString) nbt).getValue(), null, false);
|
||||
}
|
||||
NBTCompound compound = (NBTCompound) nbt;
|
||||
String id = compound.getStringTagValueOrThrow("id");
|
||||
Component display = compound.getOrNull("display", AdventureSerializer.serializer(wrapper), wrapper);
|
||||
boolean initial = compound.getBooleanOr("initial", false);
|
||||
return new Entry(id, display, initial);
|
||||
}
|
||||
|
||||
public static NBT encode(PacketWrapper<?> wrapper, Entry entry) {
|
||||
NBTCompound compound = new NBTCompound();
|
||||
compound.setTag("id", new NBTString(entry.id));
|
||||
if (entry.display != null) {
|
||||
compound.set("display", entry.display, AdventureSerializer.serializer(wrapper), wrapper);
|
||||
}
|
||||
if (entry.initial) {
|
||||
compound.setTag("initial", new NBTByte(true));
|
||||
}
|
||||
return compound;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public @Nullable Component getDisplay() {
|
||||
return this.display;
|
||||
}
|
||||
|
||||
public boolean isInitial() {
|
||||
return this.initial;
|
||||
}
|
||||
}
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog.input;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.mapper.AbstractMappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.util.NbtMapDecoder;
|
||||
import com.github.retrooper.packetevents.protocol.util.NbtMapEncoder;
|
||||
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class StaticInputControlType<T extends InputControl> extends AbstractMappedEntity implements InputControlType<T> {
|
||||
|
||||
private final NbtMapDecoder<T> decoder;
|
||||
private final NbtMapEncoder<T> encoder;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public StaticInputControlType(
|
||||
@Nullable TypesBuilderData data,
|
||||
NbtMapDecoder<T> decoder,
|
||||
NbtMapEncoder<T> encoder
|
||||
) {
|
||||
super(data);
|
||||
this.decoder = decoder;
|
||||
this.encoder = encoder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T decode(NBTCompound compound, PacketWrapper<?> wrapper) {
|
||||
return this.decoder.decode(compound, wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encode(NBTCompound compound, PacketWrapper<?> wrapper, T control) {
|
||||
this.encoder.encode(compound, wrapper, control);
|
||||
}
|
||||
}
|
||||
+151
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.dialog.input;
|
||||
|
||||
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.NBTInt;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
|
||||
import com.github.retrooper.packetevents.util.adventure.AdventureSerializer;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public class TextInputControl implements InputControl {
|
||||
|
||||
private final int width;
|
||||
private final Component label;
|
||||
private final boolean labelVisible;
|
||||
private final String initial;
|
||||
private final int maxLength;
|
||||
private final @Nullable MultilineOptions multiline;
|
||||
|
||||
public TextInputControl(int width, Component label, boolean labelVisible, String initial, int maxLength, @Nullable MultilineOptions multiline) {
|
||||
if (initial.length() > maxLength) {
|
||||
throw new IllegalArgumentException("Default text length exceeds allowed size");
|
||||
}
|
||||
this.width = width;
|
||||
this.label = label;
|
||||
this.labelVisible = labelVisible;
|
||||
this.initial = initial;
|
||||
this.maxLength = maxLength;
|
||||
this.multiline = multiline;
|
||||
}
|
||||
|
||||
public static TextInputControl decode(NBTCompound compound, PacketWrapper<?> wrapper) {
|
||||
int width = compound.getNumberTagValueOrDefault("width", 200).intValue();
|
||||
Component label = compound.getOrThrow("label", AdventureSerializer.serializer(wrapper), wrapper);
|
||||
boolean labelVisible = compound.getBooleanOr("label_visible", true);
|
||||
String initial = compound.getStringTagValueOrDefault("initial", "");
|
||||
int maxLength = compound.getNumberTagValueOrDefault("max_length", 32).intValue();
|
||||
MultilineOptions multiline = compound.getOrNull("multiline", MultilineOptions::decode, wrapper);
|
||||
return new TextInputControl(width, label, labelVisible, initial, maxLength, multiline);
|
||||
}
|
||||
|
||||
public static void encode(NBTCompound compound, PacketWrapper<?> wrapper, TextInputControl control) {
|
||||
if (control.width != 200) {
|
||||
compound.setTag("width", new NBTInt(control.width));
|
||||
}
|
||||
compound.set("label", control.label, AdventureSerializer.serializer(wrapper), wrapper);
|
||||
if (!control.labelVisible) {
|
||||
compound.setTag("label_visible", new NBTByte(false));
|
||||
}
|
||||
if (!control.initial.isEmpty()) {
|
||||
compound.setTag("initial", new NBTString(control.initial));
|
||||
}
|
||||
if (control.maxLength != 32) {
|
||||
compound.setTag("max_length", new NBTInt(control.maxLength));
|
||||
}
|
||||
if (control.multiline != null) {
|
||||
compound.set("multiline", control.multiline, MultilineOptions::encode, wrapper);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputControlType<?> getType() {
|
||||
return InputControlTypes.TEXT;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return this.width;
|
||||
}
|
||||
|
||||
public Component getLabel() {
|
||||
return this.label;
|
||||
}
|
||||
|
||||
public boolean isLabelVisible() {
|
||||
return this.labelVisible;
|
||||
}
|
||||
|
||||
public String getInitial() {
|
||||
return this.initial;
|
||||
}
|
||||
|
||||
public int getMaxLength() {
|
||||
return this.maxLength;
|
||||
}
|
||||
|
||||
public @Nullable MultilineOptions getMultiline() {
|
||||
return this.multiline;
|
||||
}
|
||||
|
||||
public static final class MultilineOptions {
|
||||
|
||||
private final @Nullable Integer maxLines;
|
||||
private final @Nullable Integer height;
|
||||
|
||||
public MultilineOptions(@Nullable Integer maxLines, @Nullable Integer height) {
|
||||
this.maxLines = maxLines;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public static MultilineOptions decode(NBT nbt, PacketWrapper<?> wrapper) {
|
||||
NBTCompound compound = (NBTCompound) nbt;
|
||||
Number maxLines = compound.getNumberTagValueOrNull("max_lines");
|
||||
Number height = compound.getNumberTagValueOrNull("height");
|
||||
return new MultilineOptions(
|
||||
maxLines != null ? maxLines.intValue() : null,
|
||||
height != null ? height.intValue() : null
|
||||
);
|
||||
}
|
||||
|
||||
public static NBT encode(PacketWrapper<?> wrapper, MultilineOptions options) {
|
||||
NBTCompound compound = new NBTCompound();
|
||||
if (options.maxLines != null) {
|
||||
compound.setTag("max_lines", new NBTInt(options.maxLines));
|
||||
}
|
||||
if (options.height != null) {
|
||||
compound.setTag("height", new NBTInt(options.height));
|
||||
}
|
||||
return compound;
|
||||
}
|
||||
|
||||
public @Nullable Integer getMaxLines() {
|
||||
return this.maxLines;
|
||||
}
|
||||
|
||||
public @Nullable Integer getHeight() {
|
||||
return this.height;
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
@@ -296,6 +296,11 @@ public final class EntityTypes {
|
||||
*/
|
||||
public static final EntityType LINGERING_POTION = define("lingering_potion", POTION);
|
||||
|
||||
/**
|
||||
* Added with 1.21.6
|
||||
*/
|
||||
public static final EntityType HAPPY_GHAST = define("happy_ghast", ABSTRACT_ANIMAL);
|
||||
|
||||
/**
|
||||
* Returns an immutable view of the entity types.
|
||||
*
|
||||
|
||||
+19
-7
@@ -50,14 +50,16 @@ public interface WolfVariant extends MappedEntity, CopyableEntity<WolfVariant>,
|
||||
MappedEntitySet<Biome> getBiomes();
|
||||
|
||||
static WolfVariant read(PacketWrapper<?> wrapper) {
|
||||
if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_5)) {
|
||||
if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_5)
|
||||
|| wrapper.getServerVersion().isOlderThan(ServerVersion.V_1_21)) {
|
||||
return wrapper.readMappedEntity(WolfVariants.getRegistry());
|
||||
}
|
||||
return wrapper.readMappedEntityOrDirect(WolfVariants.getRegistry(), WolfVariant::readDirect);
|
||||
}
|
||||
|
||||
static void write(PacketWrapper<?> wrapper, WolfVariant variant) {
|
||||
if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_5)) {
|
||||
if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_5)
|
||||
|| wrapper.getServerVersion().isOlderThan(ServerVersion.V_1_21)) {
|
||||
wrapper.writeMappedEntity(variant);
|
||||
} else {
|
||||
wrapper.writeMappedEntityOrDirect(variant, WolfVariant::writeDirect);
|
||||
@@ -87,14 +89,19 @@ public interface WolfVariant extends MappedEntity, CopyableEntity<WolfVariant>,
|
||||
MappedEntitySet.write(wrapper, variant.getBiomes());
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
static WolfVariant decode(NBT nbt, ClientVersion version, @Nullable TypesBuilderData data) {
|
||||
return decode(nbt, PacketWrapper.createDummyWrapper(version), data);
|
||||
}
|
||||
|
||||
static WolfVariant decode(NBT nbt, PacketWrapper<?> wrapper, @Nullable TypesBuilderData data) {
|
||||
NBTCompound compound = (NBTCompound) nbt;
|
||||
if (version.isOlderThan(ClientVersion.V_1_21_5)) {
|
||||
if (wrapper.getServerVersion().isOlderThan(ServerVersion.V_1_21_5)) {
|
||||
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());
|
||||
MappedEntitySet<Biome> biomes = compound.getOrThrow("biomes", (tag, ew) ->
|
||||
MappedEntitySet.decode(tag, ew, Biomes.getRegistry()), wrapper);
|
||||
return new StaticWolfVariant(data, wildTexture, tameTexture, angryTexture, biomes);
|
||||
}
|
||||
NBTCompound assets = compound.getCompoundTagOrThrow("assets");
|
||||
@@ -105,13 +112,18 @@ public interface WolfVariant extends MappedEntity, CopyableEntity<WolfVariant>,
|
||||
angryTexture, MappedEntitySet.createEmpty());
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
static NBT encode(WolfVariant variant, ClientVersion version) {
|
||||
return encode(PacketWrapper.createDummyWrapper(version), variant);
|
||||
}
|
||||
|
||||
static NBT encode(PacketWrapper<?> wrapper, WolfVariant variant) {
|
||||
NBTCompound compound = new NBTCompound();
|
||||
if (version.isOlderThan(ClientVersion.V_1_21_5)) {
|
||||
if (wrapper.getServerVersion().isOlderThan(ServerVersion.V_1_21_5)) {
|
||||
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));
|
||||
compound.set("biomes", variant.getBiomes(), MappedEntitySet::encode, wrapper);
|
||||
} else {
|
||||
NBTCompound assets = new NBTCompound();
|
||||
assets.setTag("wild", new NBTString(variant.getWildTexture().toString()));
|
||||
|
||||
@@ -107,6 +107,11 @@ public class ItemStack {
|
||||
this.registryHolder = registryHolder;
|
||||
}
|
||||
|
||||
public static ItemStack decode(NBT nbt, PacketWrapper<?> wrapper) {
|
||||
return decode(nbt, wrapper.getServerVersion().toClientVersion());
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static ItemStack decode(NBT nbt, ClientVersion version) {
|
||||
if (nbt instanceof NBTString) {
|
||||
ResourceLocation itemName = new ResourceLocation(((NBTString) nbt).getValue());
|
||||
@@ -131,6 +136,11 @@ public class ItemStack {
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public static NBT encode(PacketWrapper<?> wrapper, ItemStack itemStack) {
|
||||
return encodeForParticle(itemStack, wrapper.getServerVersion().toClientVersion());
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static NBT encodeForParticle(ItemStack itemStack, ClientVersion version) {
|
||||
if (version.isNewerThanOrEquals(ClientVersion.V_1_20_5)) {
|
||||
boolean simple = itemStack.isEmpty()
|
||||
|
||||
+5
-3
@@ -69,7 +69,7 @@ public final class ItemStackSerialization {
|
||||
ClientVersion version = wrapper.getServerVersion().toClientVersion();
|
||||
ItemType type = ItemTypes.getRegistry().getByIdOrThrow(version, typeId);
|
||||
int amount = wrapper.readByte();
|
||||
int legacyData = v1_13_2 ? -1 : wrapper.readShort();
|
||||
int legacyData = version.isOlderThan(ClientVersion.V_1_13) ? wrapper.readShort() : -1;
|
||||
NBTCompound nbt = wrapper.readNBT();
|
||||
return ItemStack.builder().type(type).amount(amount)
|
||||
.nbt(nbt).legacyData(legacyData)
|
||||
@@ -80,12 +80,14 @@ public final class ItemStackSerialization {
|
||||
* Removed with 1.20.5
|
||||
*/
|
||||
private static void writeLegacy(PacketWrapper<?> wrapper, ItemStack stack) {
|
||||
if (wrapper.getServerVersion().isOlderThanOrEquals(ServerVersion.V_1_12_2)) {
|
||||
if (wrapper.getServerVersion().isOlderThan(ServerVersion.V_1_13_2)) {
|
||||
int typeId = stack.isEmpty() ? -1 : stack.getType().getId(wrapper.getServerVersion().toClientVersion());
|
||||
wrapper.writeShort(typeId);
|
||||
if (typeId != -1) {
|
||||
wrapper.writeByte(stack.getAmount());
|
||||
wrapper.writeShort(stack.getLegacyData());
|
||||
if (wrapper.getServerVersion().isOlderThan(ServerVersion.V_1_13)) {
|
||||
wrapper.writeShort(stack.getLegacyData());
|
||||
}
|
||||
wrapper.writeNBT(stack.getNBT());
|
||||
}
|
||||
} else if (stack.isEmpty()) {
|
||||
|
||||
+11
@@ -22,6 +22,7 @@ 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 com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -35,14 +36,24 @@ public final class EnchantmentCost {
|
||||
this.perLevelAboveFirst = perLevelAboveFirst;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static EnchantmentCost decode(NBT nbt, ClientVersion version) {
|
||||
return decode(nbt, PacketWrapper.createDummyWrapper(version));
|
||||
}
|
||||
|
||||
public static EnchantmentCost decode(NBT nbt, PacketWrapper<?> wrapper) {
|
||||
NBTCompound compound = (NBTCompound) nbt;
|
||||
int base = compound.getNumberTagOrThrow("base").getAsInt();
|
||||
int perLevelAboveFirst = compound.getNumberTagOrThrow("per_level_above_first").getAsInt();
|
||||
return new EnchantmentCost(base, perLevelAboveFirst);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static NBT encode(EnchantmentCost cost, ClientVersion version) {
|
||||
return encode(PacketWrapper.createDummyWrapper(version), cost);
|
||||
}
|
||||
|
||||
public static NBT encode(PacketWrapper<?> wrapper, EnchantmentCost cost) {
|
||||
NBTCompound compound = new NBTCompound();
|
||||
compound.setTag("base", new NBTInt(cost.base));
|
||||
compound.setTag("per_level_above_first", new NBTInt(cost.perLevelAboveFirst));
|
||||
|
||||
+30
-14
@@ -28,6 +28,8 @@ 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 com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -37,6 +39,7 @@ import java.util.Optional;
|
||||
|
||||
import static com.github.retrooper.packetevents.util.adventure.AdventureIndexUtil.indexValueOrThrow;
|
||||
|
||||
@NullMarked
|
||||
public final class EnchantmentDefinition {
|
||||
|
||||
private final MappedEntitySet<ItemType> supportedItems;
|
||||
@@ -65,16 +68,21 @@ public final class EnchantmentDefinition {
|
||||
this.slots = slots;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static EnchantmentDefinition decode(NBT nbt, ClientVersion version) {
|
||||
return decode(nbt, PacketWrapper.createDummyWrapper(version));
|
||||
}
|
||||
|
||||
public static EnchantmentDefinition decode(NBT nbt, PacketWrapper<?> wrapper) {
|
||||
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()));
|
||||
MappedEntitySet<ItemType> supportedItems = compound.getOrThrow("supported_items", (tag, ew) ->
|
||||
MappedEntitySet.decode(tag, ew, ItemTypes.getRegistry()), wrapper);
|
||||
Optional<MappedEntitySet<ItemType>> primaryItems = Optional.ofNullable(compound.getOrNull("primary_items",
|
||||
(tag, ew) -> MappedEntitySet.decode(tag, ew, ItemTypes.getRegistry()), wrapper));
|
||||
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);
|
||||
EnchantmentCost minCost = compound.getOrThrow("min_cost", EnchantmentCost::decode, wrapper);
|
||||
EnchantmentCost maxCost = compound.getOrThrow("max_cost", EnchantmentCost::decode, wrapper);
|
||||
int anvilCost = compound.getNumberTagOrThrow("anvil_cost").getAsInt();
|
||||
|
||||
NBT slotsTag = compound.getTagOrThrow("slots");
|
||||
@@ -96,24 +104,32 @@ public final class EnchantmentDefinition {
|
||||
maxLevel, minCost, maxCost, anvilCost, slots);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static NBT encode(EnchantmentDefinition definition, ClientVersion version) {
|
||||
return encode(PacketWrapper.createDummyWrapper(version), definition);
|
||||
}
|
||||
|
||||
public static NBT encode(PacketWrapper<?> wrapper, EnchantmentDefinition definition) {
|
||||
NBTCompound compound = new NBTCompound();
|
||||
encode(compound, wrapper, definition);
|
||||
return compound;
|
||||
}
|
||||
|
||||
public static void encode(NBTCompound compound, PacketWrapper<?> wrapper, EnchantmentDefinition definition) {
|
||||
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.set("supported_items", definition.supportedItems, MappedEntitySet::encode, wrapper);
|
||||
definition.primaryItems.ifPresent(set -> compound.set(
|
||||
"primary_items", set, MappedEntitySet::encode, wrapper));
|
||||
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.set("min_cost", definition.minCost, EnchantmentCost::encode, wrapper);
|
||||
compound.set("max_cost", definition.maxCost, EnchantmentCost::encode, wrapper);
|
||||
compound.setTag("anvil_cost", new NBTInt(definition.anvilCost));
|
||||
compound.setTag("slots", slotsTag);
|
||||
return compound;
|
||||
}
|
||||
|
||||
public MappedEntitySet<ItemType> getSupportedItems() {
|
||||
|
||||
+27
-11
@@ -25,17 +25,20 @@ import com.github.retrooper.packetevents.protocol.item.enchantment.EnchantmentDe
|
||||
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.MappedEntityRefSet;
|
||||
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 com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@NullMarked
|
||||
public interface EnchantmentType extends MappedEntity, CopyableEntity<EnchantmentType>, DeepComparableEntity {
|
||||
|
||||
Component getDescription();
|
||||
@@ -44,30 +47,43 @@ public interface EnchantmentType extends MappedEntity, CopyableEntity<Enchantmen
|
||||
|
||||
MappedEntitySet<EnchantmentType> getExclusiveSet();
|
||||
|
||||
MappedEntityRefSet<EnchantmentType> getExclusiveRefSet();
|
||||
|
||||
StaticComponentMap getEffects();
|
||||
|
||||
@Deprecated
|
||||
static EnchantmentType decode(NBT nbt, ClientVersion version, @Nullable TypesBuilderData data) {
|
||||
return decode(nbt, PacketWrapper.createDummyWrapper(version), data);
|
||||
}
|
||||
|
||||
static EnchantmentType decode(NBT nbt, PacketWrapper<?> wrapper, @Nullable TypesBuilderData data) {
|
||||
NBTCompound compound = (NBTCompound) nbt;
|
||||
Component description = AdventureSerializer.serializer(version).fromNbtTag(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()))
|
||||
Component description = compound.getOrThrow("description", wrapper.getSerializers(), wrapper);
|
||||
EnchantmentDefinition definition = EnchantmentDefinition.decode(compound, wrapper);
|
||||
MappedEntityRefSet<EnchantmentType> exclusiveSet = Optional.ofNullable(compound.getTagOrNull("exclusive_set"))
|
||||
.map(tag -> MappedEntitySet.<EnchantmentType>decodeRefSet(tag, wrapper))
|
||||
.orElseGet(MappedEntitySet::createEmpty);
|
||||
StaticComponentMap effects = Optional.ofNullable(compound.getTagOrNull("effects"))
|
||||
.map(tag -> IComponentMap.decode(tag, version,
|
||||
.map(tag -> IComponentMap.decode(tag, wrapper,
|
||||
EnchantEffectComponentTypes.getRegistry()))
|
||||
.orElse(StaticComponentMap.EMPTY);
|
||||
return new StaticEnchantmentType(data, description, definition, exclusiveSet, effects);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
static NBT encode(EnchantmentType type, ClientVersion version) {
|
||||
NBTCompound compound = (NBTCompound) EnchantmentDefinition.encode(type.getDefinition(), version);
|
||||
compound.setTag("description", AdventureSerializer.serializer(version).asNbtTag(type.getDescription()));
|
||||
if (!type.getExclusiveSet().isEmpty()) {
|
||||
compound.setTag("exclusive_set", MappedEntitySet.encode(type.getExclusiveSet(), version));
|
||||
return encode(type, PacketWrapper.createDummyWrapper(version));
|
||||
}
|
||||
|
||||
static NBT encode(EnchantmentType type, PacketWrapper<?> wrapper) {
|
||||
NBTCompound compound = new NBTCompound();
|
||||
EnchantmentDefinition.encode(compound, wrapper, type.getDefinition());
|
||||
compound.set("description", type.getDescription(), wrapper.getSerializers(), wrapper);
|
||||
if (!type.getExclusiveRefSet().isEmpty()) {
|
||||
compound.set("exclusive_set", type.getExclusiveRefSet(), MappedEntitySet::encodeRefSet, wrapper);
|
||||
}
|
||||
if (!type.getEffects().isEmpty()) {
|
||||
compound.setTag("effects", IComponentMap.encode(type.getEffects(), version));
|
||||
compound.set("effects", type.getEffects(), IComponentMap::encode, wrapper);
|
||||
}
|
||||
return compound;
|
||||
}
|
||||
|
||||
+3
-1
@@ -25,6 +25,7 @@ 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.VersionedRegistry;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -64,12 +65,13 @@ public final class EnchantmentTypes {
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static EnchantmentType define(String key) {
|
||||
PacketWrapper<?> wrapper = PacketWrapper.createDummyWrapper(ClientVersion.getLatest());
|
||||
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);
|
||||
return EnchantmentType.decode(dataTag, wrapper, data);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+37
-9
@@ -18,22 +18,30 @@
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.item.enchantment.type;
|
||||
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
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.MappedEntityRefSet;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.MappedEntitySet;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.ResolvableEntity;
|
||||
import com.github.retrooper.packetevents.util.mappings.GlobalRegistryHolder;
|
||||
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 org.jspecify.annotations.NullMarked;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class StaticEnchantmentType extends AbstractMappedEntity implements EnchantmentType {
|
||||
@NullMarked
|
||||
public class StaticEnchantmentType extends AbstractMappedEntity implements EnchantmentType, ResolvableEntity {
|
||||
|
||||
private final Component description;
|
||||
private final EnchantmentDefinition definition;
|
||||
private final MappedEntitySet<EnchantmentType> exclusiveSet;
|
||||
private final MappedEntityRefSet<EnchantmentType> exclusiveSetRef;
|
||||
private @Nullable MappedEntitySet<EnchantmentType> exclusiveSet;
|
||||
private final StaticComponentMap effects;
|
||||
|
||||
public StaticEnchantmentType(
|
||||
@@ -50,20 +58,27 @@ public class StaticEnchantmentType extends AbstractMappedEntity implements Encha
|
||||
@Nullable TypesBuilderData data,
|
||||
Component description,
|
||||
EnchantmentDefinition definition,
|
||||
MappedEntitySet<EnchantmentType> exclusiveSet,
|
||||
MappedEntityRefSet<EnchantmentType> exclusiveSet,
|
||||
StaticComponentMap effects
|
||||
) {
|
||||
super(data);
|
||||
this.description = description;
|
||||
this.definition = definition;
|
||||
this.exclusiveSet = exclusiveSet;
|
||||
this.exclusiveSetRef = exclusiveSet;
|
||||
this.effects = effects;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doResolve(PacketWrapper<?> wrapper) {
|
||||
this.exclusiveSet = this.exclusiveSetRef.resolve(wrapper, EnchantmentTypes.getRegistry());
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnchantmentType copy(@Nullable TypesBuilderData newData) {
|
||||
return new StaticEnchantmentType(newData, this.description,
|
||||
this.definition, this.exclusiveSet, this.effects);
|
||||
StaticEnchantmentType type = new StaticEnchantmentType(newData, this.description,
|
||||
this.definition, this.exclusiveSetRef, this.effects);
|
||||
type.exclusiveSet = this.exclusiveSet;
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -78,9 +93,22 @@ public class StaticEnchantmentType extends AbstractMappedEntity implements Encha
|
||||
|
||||
@Override
|
||||
public MappedEntitySet<EnchantmentType> getExclusiveSet() {
|
||||
if (this.exclusiveSet == null) {
|
||||
// this shouldn't need to be called normally
|
||||
this.exclusiveSet = this.exclusiveSetRef.resolve(
|
||||
PacketEvents.getAPI().getServerManager().getVersion().toClientVersion(),
|
||||
GlobalRegistryHolder.INSTANCE,
|
||||
EnchantmentTypes.getRegistry()
|
||||
);
|
||||
}
|
||||
return this.exclusiveSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappedEntityRefSet<EnchantmentType> getExclusiveRefSet() {
|
||||
return this.exclusiveSetRef;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StaticComponentMap getEffects() {
|
||||
return this.effects;
|
||||
@@ -94,17 +122,17 @@ public class StaticEnchantmentType extends AbstractMappedEntity implements Encha
|
||||
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;
|
||||
if (!this.exclusiveSetRef.equals(that.exclusiveSetRef)) 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);
|
||||
return Objects.hash(super.hashCode(), this.description, this.definition, this.exclusiveSetRef, this.effects);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "StaticEnchantmentType{description=" + this.description + ", definition=" + this.definition + ", exclusiveSet=" + this.exclusiveSet + ", effects=" + this.effects + "}";
|
||||
return "StaticEnchantmentType{description=" + this.description + ", definition=" + this.definition + ", exclusiveSetRef=" + this.exclusiveSetRef + ", effects=" + this.effects + "}";
|
||||
}
|
||||
}
|
||||
+14
-5
@@ -28,7 +28,6 @@ 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;
|
||||
@@ -82,21 +81,31 @@ public interface Instrument extends MappedEntity, CopyableEntity<Instrument>, De
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
static Instrument decode(NBT nbt, ClientVersion version, @Nullable TypesBuilderData data) {
|
||||
return decode(nbt, PacketWrapper.createDummyWrapper(version), data);
|
||||
}
|
||||
|
||||
static Instrument decode(NBT nbt, PacketWrapper<?> wrapper, @Nullable TypesBuilderData data) {
|
||||
NBTCompound compound = (NBTCompound) nbt;
|
||||
Sound sound = Sound.decode(compound.getTagOrThrow("sound_event"), version);
|
||||
Sound sound = compound.getOrThrow("sound_event", Sound::decode, wrapper);
|
||||
float useSeconds = compound.getNumberTagOrThrow("use_duration").getAsFloat();
|
||||
float range = compound.getNumberTagOrThrow("range").getAsFloat();
|
||||
Component description = AdventureSerializer.serializer(version).fromNbtTag(compound.getTagOrThrow("description"));
|
||||
Component description = compound.getOrThrow("description", wrapper.getSerializers(), wrapper);
|
||||
return new StaticInstrument(data, sound, useSeconds, range, description);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
static NBT encode(Instrument instrument, ClientVersion version) {
|
||||
return encode(PacketWrapper.createDummyWrapper(version), instrument);
|
||||
}
|
||||
|
||||
static NBT encode(PacketWrapper<?> wrapper, Instrument instrument) {
|
||||
NBTCompound compound = new NBTCompound();
|
||||
compound.setTag("sound_event", Sound.encode(instrument.getSound(), version));
|
||||
compound.set("sound_event", instrument.getSound(), Sound::encode, wrapper);
|
||||
compound.setTag("use_duration", new NBTFloat(instrument.getUseSeconds()));
|
||||
compound.setTag("range", new NBTFloat(instrument.getRange()));
|
||||
compound.setTag("description", AdventureSerializer.serializer(version).asNbtTag(instrument.getDescription()));
|
||||
compound.set("description", instrument.getDescription(), wrapper.getSerializers(), wrapper);
|
||||
return compound;
|
||||
}
|
||||
}
|
||||
+16
-9
@@ -27,7 +27,6 @@ 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;
|
||||
@@ -43,23 +42,31 @@ public interface IJukeboxSong extends MappedEntity, CopyableEntity<IJukeboxSong>
|
||||
|
||||
int getComparatorOutput();
|
||||
|
||||
@Deprecated
|
||||
static IJukeboxSong decode(NBT nbt, ClientVersion version, @Nullable TypesBuilderData data) {
|
||||
return decode(nbt, PacketWrapper.createDummyWrapper(version), data);
|
||||
}
|
||||
|
||||
static IJukeboxSong decode(NBT nbt, PacketWrapper<?> wrapper, @Nullable TypesBuilderData data) {
|
||||
NBTCompound compound = (NBTCompound) nbt;
|
||||
Sound sound = Sound.decode(compound.getTagOrThrow("sound_event"), version);
|
||||
Component description = AdventureSerializer.serializer(version).fromNbtTag(compound.getTagOrThrow("description"));
|
||||
Sound sound = compound.getOrThrow("sound_event", Sound::decode, wrapper);
|
||||
Component description = compound.getOrThrow("description", wrapper.getSerializers(), wrapper);
|
||||
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);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
static NBT encode(IJukeboxSong jukeboxSong, ClientVersion version) {
|
||||
return encode(PacketWrapper.createDummyWrapper(version), jukeboxSong);
|
||||
}
|
||||
|
||||
static NBT encode(PacketWrapper<?> wrapper, IJukeboxSong song) {
|
||||
NBTCompound compound = new NBTCompound();
|
||||
|
||||
compound.setTag("sound_event", Sound.encode(jukeboxSong.getSound(), version));
|
||||
compound.setTag("description", AdventureSerializer.serializer(version).asNbtTag(jukeboxSong.getDescription()));
|
||||
compound.setTag("length_in_seconds", new NBTFloat(jukeboxSong.getLengthInSeconds()));
|
||||
compound.setTag("comparator_output", new NBTInt(jukeboxSong.getComparatorOutput()));
|
||||
|
||||
compound.set("sound_event", song.getSound(), Sound::encode, wrapper);
|
||||
compound.set("description", song.getDescription(), wrapper.getSerializers(), wrapper);
|
||||
compound.setTag("length_in_seconds", new NBTFloat(song.getLengthInSeconds()));
|
||||
compound.setTag("comparator_output", new NBTInt(song.getComparatorOutput()));
|
||||
return compound;
|
||||
}
|
||||
|
||||
|
||||
+12
@@ -81,6 +81,18 @@ public final class JukeboxSongs {
|
||||
public static final IJukeboxSong CREATOR_MUSIC_BOX = define("creator_music_box", Sounds.MUSIC_DISC_CREATOR_MUSIC_BOX,
|
||||
73, 11);
|
||||
|
||||
/**
|
||||
* Added with 1.21.6
|
||||
*/
|
||||
public static final IJukeboxSong TEARS = define("tears", Sounds.MUSIC_DISC_TEARS,
|
||||
175, 10);
|
||||
|
||||
/**
|
||||
* Added with 1.21.7
|
||||
*/
|
||||
public static final IJukeboxSong LAVA_CHICKEN = define("lava_chicken", Sounds.MUSIC_DISC_LAVA_CHICKEN,
|
||||
134, 9);
|
||||
|
||||
/**
|
||||
* Returns an immutable view of the jukebox songs.
|
||||
*
|
||||
|
||||
+16
-7
@@ -31,7 +31,6 @@ 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;
|
||||
@@ -102,12 +101,17 @@ public interface TrimMaterial extends MappedEntity, CopyableEntity<TrimMaterial>
|
||||
wrapper.writeComponent(material.getDescription());
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
static TrimMaterial decode(NBT nbt, ClientVersion version, @Nullable TypesBuilderData data) {
|
||||
return decode(nbt, PacketWrapper.createDummyWrapper(version), data);
|
||||
}
|
||||
|
||||
static TrimMaterial decode(NBT nbt, PacketWrapper<?> wrapper, @Nullable TypesBuilderData data) {
|
||||
NBTCompound compound = (NBTCompound) nbt;
|
||||
String assetName = compound.getStringTagValueOrThrow("asset_name");
|
||||
ItemType ingredient = version.isNewerThanOrEquals(ClientVersion.V_1_21_5)
|
||||
ItemType ingredient = wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_5)
|
||||
? null : ItemTypes.getByName(compound.getStringTagValueOrThrow("ingredient"));
|
||||
float itemModelIndex = version.isNewerThanOrEquals(ClientVersion.V_1_21_4)
|
||||
float itemModelIndex = wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.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;
|
||||
@@ -121,11 +125,16 @@ public interface TrimMaterial extends MappedEntity, CopyableEntity<TrimMaterial>
|
||||
} else {
|
||||
overrideArmorMaterials = Collections.emptyMap();
|
||||
}
|
||||
Component description = AdventureSerializer.serializer(version).fromNbtTag(((NBTCompound) nbt).getTagOrThrow("description"));
|
||||
Component description = ((NBTCompound) nbt).getOrThrow("description", wrapper.getSerializers(), wrapper);
|
||||
return new StaticTrimMaterial(data, assetName, ingredient, itemModelIndex, overrideArmorMaterials, description);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
static NBT encode(TrimMaterial material, ClientVersion version) {
|
||||
return encode(PacketWrapper.createDummyWrapper(version), material);
|
||||
}
|
||||
|
||||
static NBT encode(PacketWrapper<?> wrapper, TrimMaterial material) {
|
||||
NBTCompound overrideArmorMaterialsTag;
|
||||
if (!material.getOverrideArmorMaterials().isEmpty()) {
|
||||
overrideArmorMaterialsTag = new NBTCompound();
|
||||
@@ -140,16 +149,16 @@ public interface TrimMaterial extends MappedEntity, CopyableEntity<TrimMaterial>
|
||||
|
||||
NBTCompound compound = new NBTCompound();
|
||||
compound.setTag("asset_name", new NBTString(material.getAssetName()));
|
||||
if (version.isOlderThan(ClientVersion.V_1_21_5)) {
|
||||
if (wrapper.getServerVersion().isOlderThan(ServerVersion.V_1_21_5)) {
|
||||
compound.setTag("ingredient", new NBTString(material.getIngredient().getName().toString()));
|
||||
}
|
||||
if (version.isOlderThan(ClientVersion.V_1_21_4)) {
|
||||
if (wrapper.getServerVersion().isOlderThan(ServerVersion.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.serializer(version).asNbtTag(material.getDescription()));
|
||||
compound.set("description", material.getDescription(), wrapper.getSerializers(), wrapper);
|
||||
return compound;
|
||||
}
|
||||
}
|
||||
+16
-7
@@ -30,7 +30,6 @@ 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;
|
||||
@@ -77,24 +76,34 @@ public interface TrimPattern extends MappedEntity, CopyableEntity<TrimPattern>,
|
||||
wrapper.writeBoolean(pattern.isDecal());
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
static TrimPattern decode(NBT nbt, ClientVersion version, @Nullable TypesBuilderData data) {
|
||||
return decode(nbt, PacketWrapper.createDummyWrapper(version), data);
|
||||
}
|
||||
|
||||
static TrimPattern decode(NBT nbt, PacketWrapper<?> wrapper, @Nullable TypesBuilderData data) {
|
||||
NBTCompound compound = (NBTCompound) nbt;
|
||||
ResourceLocation assetId = new ResourceLocation(compound.getStringTagValueOrThrow("asset_id"));
|
||||
ItemType templateItem = version.isNewerThanOrEquals(ClientVersion.V_1_21_5) ? null :
|
||||
ItemType templateItem = wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_5) ? null :
|
||||
ItemTypes.getByName(compound.getStringTagValueOrThrow("template_item"));
|
||||
Component description = AdventureSerializer.serializer(version).fromNbtTag(compound.getTagOrThrow("description"));
|
||||
boolean decal = version.isNewerThanOrEquals(ClientVersion.V_1_20_2) && compound.getBoolean("decal");
|
||||
Component description = compound.getOrThrow("description", wrapper.getSerializers(), wrapper);
|
||||
boolean decal = wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_20_2) && compound.getBoolean("decal");
|
||||
return new StaticTrimPattern(data, assetId, templateItem, description, decal);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
static NBT encode(TrimPattern pattern, ClientVersion version) {
|
||||
return encode(PacketWrapper.createDummyWrapper(version), pattern);
|
||||
}
|
||||
|
||||
static NBT encode(PacketWrapper<?> wrapper, TrimPattern pattern) {
|
||||
NBTCompound compound = new NBTCompound();
|
||||
compound.setTag("asset_id", new NBTString(pattern.getAssetId().toString()));
|
||||
if (version.isOlderThan(ClientVersion.V_1_21_5)) {
|
||||
if (wrapper.getServerVersion().isOlderThan(ServerVersion.V_1_21_5)) {
|
||||
compound.setTag("template_item", new NBTString(pattern.getTemplateItem().getName().toString()));
|
||||
}
|
||||
compound.setTag("description", AdventureSerializer.serializer(version).asNbtTag(pattern.getDescription()));
|
||||
if (version.isNewerThanOrEquals(ClientVersion.V_1_20_2)) {
|
||||
compound.set("description", pattern.getDescription(), wrapper.getSerializers(), wrapper);
|
||||
if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_20_2)) {
|
||||
compound.setTag("decal", new NBTByte(pattern.isDecal()));
|
||||
}
|
||||
return compound;
|
||||
|
||||
+84
-1
@@ -1476,6 +1476,88 @@ public final class ItemTypes {
|
||||
public static final ItemType BLUE_EGG = builder("blue_egg").setMaxAmount(16).build();
|
||||
public static final ItemType BROWN_EGG = builder("brown_egg").setMaxAmount(16).build();
|
||||
|
||||
/**
|
||||
* Added with 1.21.6
|
||||
*/
|
||||
public static final ItemType DRIED_GHAST = builder("dried_ghast").setMaxAmount(64).setPlacedType(StateTypes.DRIED_GHAST).build();
|
||||
/**
|
||||
* Added with 1.21.6
|
||||
*/
|
||||
public static final ItemType WHITE_HARNESS = builder("white_harness").setMaxAmount(1).build();
|
||||
/**
|
||||
* Added with 1.21.6
|
||||
*/
|
||||
public static final ItemType ORANGE_HARNESS = builder("orange_harness").setMaxAmount(1).build();
|
||||
/**
|
||||
* Added with 1.21.6
|
||||
*/
|
||||
public static final ItemType MAGENTA_HARNESS = builder("magenta_harness").setMaxAmount(1).build();
|
||||
/**
|
||||
* Added with 1.21.6
|
||||
*/
|
||||
public static final ItemType LIGHT_BLUE_HARNESS = builder("light_blue_harness").setMaxAmount(1).build();
|
||||
/**
|
||||
* Added with 1.21.6
|
||||
*/
|
||||
public static final ItemType YELLOW_HARNESS = builder("yellow_harness").setMaxAmount(1).build();
|
||||
/**
|
||||
* Added with 1.21.6
|
||||
*/
|
||||
public static final ItemType LIME_HARNESS = builder("lime_harness").setMaxAmount(1).build();
|
||||
/**
|
||||
* Added with 1.21.6
|
||||
*/
|
||||
public static final ItemType PINK_HARNESS = builder("pink_harness").setMaxAmount(1).build();
|
||||
/**
|
||||
* Added with 1.21.6
|
||||
*/
|
||||
public static final ItemType GRAY_HARNESS = builder("gray_harness").setMaxAmount(1).build();
|
||||
/**
|
||||
* Added with 1.21.6
|
||||
*/
|
||||
public static final ItemType LIGHT_GRAY_HARNESS = builder("light_gray_harness").setMaxAmount(1).build();
|
||||
/**
|
||||
* Added with 1.21.6
|
||||
*/
|
||||
public static final ItemType CYAN_HARNESS = builder("cyan_harness").setMaxAmount(1).build();
|
||||
/**
|
||||
* Added with 1.21.6
|
||||
*/
|
||||
public static final ItemType PURPLE_HARNESS = builder("purple_harness").setMaxAmount(1).build();
|
||||
/**
|
||||
* Added with 1.21.6
|
||||
*/
|
||||
public static final ItemType BLUE_HARNESS = builder("blue_harness").setMaxAmount(1).build();
|
||||
/**
|
||||
* Added with 1.21.6
|
||||
*/
|
||||
public static final ItemType BROWN_HARNESS = builder("brown_harness").setMaxAmount(1).build();
|
||||
/**
|
||||
* Added with 1.21.6
|
||||
*/
|
||||
public static final ItemType GREEN_HARNESS = builder("green_harness").setMaxAmount(1).build();
|
||||
/**
|
||||
* Added with 1.21.6
|
||||
*/
|
||||
public static final ItemType RED_HARNESS = builder("red_harness").setMaxAmount(1).build();
|
||||
/**
|
||||
* Added with 1.21.6
|
||||
*/
|
||||
public static final ItemType BLACK_HARNESS = builder("black_harness").setMaxAmount(1).build();
|
||||
/**
|
||||
* Added with 1.21.6
|
||||
*/
|
||||
public static final ItemType HAPPY_GHAST_SPAWN_EGG = builder("happy_ghast_spawn_egg").setMaxAmount(64).build();
|
||||
/**
|
||||
* Added with 1.21.6
|
||||
*/
|
||||
public static final ItemType MUSIC_DISC_TEARS = builder("music_disc_tears").setMaxAmount(1).setAttributes(ItemAttribute.MUSIC_DISC).build();
|
||||
|
||||
/**
|
||||
* Added with 1.21.7
|
||||
*/
|
||||
public static final ItemType MUSIC_DISC_LAVA_CHICKEN = builder("music_disc_lava_chicken").setMaxAmount(1).setAttributes(ItemAttribute.MUSIC_DISC).build();
|
||||
|
||||
/**
|
||||
* @deprecated Burning furnace shows up as a missing texture, removed in 1.9
|
||||
*/
|
||||
@@ -1603,7 +1685,8 @@ public final class ItemTypes {
|
||||
// all versions where base components were changed TODO UPDATE
|
||||
ClientVersion[] versions = new ClientVersion[]{
|
||||
ClientVersion.V_1_20_5, ClientVersion.V_1_21, ClientVersion.V_1_21_2,
|
||||
ClientVersion.V_1_21_4, ClientVersion.V_1_21_5,
|
||||
ClientVersion.V_1_21_4, ClientVersion.V_1_21_5, ClientVersion.V_1_21_6,
|
||||
ClientVersion.V_1_21_7,
|
||||
};
|
||||
for (ClientVersion version : versions) {
|
||||
parseAllComponents(version);
|
||||
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.nbt.NBT;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.util.NbtDecoder;
|
||||
import com.github.retrooper.packetevents.protocol.util.NbtEncoder;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.util.mappings.IRegistry;
|
||||
import com.github.retrooper.packetevents.util.mappings.IRegistryHolder;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@NullMarked
|
||||
public interface MappedEntityRef<T extends MappedEntity> extends Supplier<T> {
|
||||
|
||||
T get();
|
||||
|
||||
static <T extends MappedEntity> MappedEntityRef<T> decode(
|
||||
NBT tag, IRegistry<T> registry, NbtDecoder<T> decoder, PacketWrapper<?> wrapper
|
||||
) {
|
||||
if (tag instanceof NBTString) {
|
||||
ResourceLocation name = new ResourceLocation(((NBTString) tag).getValue());
|
||||
return new Named<>(wrapper, registry, name);
|
||||
}
|
||||
return new Static<>(decoder.decode(tag, wrapper));
|
||||
}
|
||||
|
||||
static <T extends MappedEntity> NBT encode(PacketWrapper<?> wrapper, NbtEncoder<T> encoder, MappedEntityRef<T> ref) {
|
||||
if (ref instanceof Named) {
|
||||
return new NBTString(((Named<T>) ref).name.toString());
|
||||
} else if (ref instanceof Static) {
|
||||
return encoder.encode(wrapper, ((Static<T>) ref).entity);
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Unsupported MappedEntityRef implementation: " + ref);
|
||||
}
|
||||
}
|
||||
|
||||
final class Static<T extends MappedEntity> implements MappedEntityRef<T> {
|
||||
|
||||
private final T entity;
|
||||
|
||||
public Static(T entity) {
|
||||
this.entity = entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get() {
|
||||
return this.entity;
|
||||
}
|
||||
}
|
||||
|
||||
final class Named<T extends MappedEntity> implements MappedEntityRef<T> {
|
||||
|
||||
private final WeakReference<IRegistryHolder> registryHolder;
|
||||
private final ClientVersion version;
|
||||
private final IRegistry<T> registry;
|
||||
private final ResourceLocation name;
|
||||
private volatile @Nullable T entity;
|
||||
|
||||
public Named(PacketWrapper<?> wrapper, IRegistry<T> registry, ResourceLocation name) {
|
||||
this(wrapper.getRegistryHolder(), wrapper.getServerVersion().toClientVersion(), registry, name);
|
||||
}
|
||||
|
||||
public Named(IRegistryHolder registryHolder, ClientVersion version, IRegistry<T> registry, ResourceLocation name) {
|
||||
this.registryHolder = new WeakReference<>(registryHolder);
|
||||
this.version = version;
|
||||
this.registry = registry;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get() {
|
||||
T entity = this.entity;
|
||||
if (entity == null) {
|
||||
synchronized (this) {
|
||||
entity = this.entity;
|
||||
if (entity == null) {
|
||||
// registry holder may be a user object, so ensure no user objects get leaked accidentally
|
||||
IRegistryHolder registryHolder = this.registryHolder.get();
|
||||
if (registryHolder == null) {
|
||||
throw new IllegalStateException("Registry holder for " + this.registry
|
||||
+ "/" + this.version + "/" + this.name + "has disappeared");
|
||||
}
|
||||
// replace registry and lookup entity
|
||||
IRegistry<T> registry = registryHolder.getRegistryOr(this.registry, this.version);
|
||||
entity = registry.getByNameOrThrow(this.name);
|
||||
this.entity = entity;
|
||||
}
|
||||
}
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.util.mappings.IRegistry;
|
||||
import com.github.retrooper.packetevents.util.mappings.IRegistryHolder;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public interface MappedEntityRefSet<T extends MappedEntity> {
|
||||
|
||||
default MappedEntitySet<T> resolve(PacketWrapper<?> wrapper, IRegistry<T> registry) {
|
||||
ClientVersion version = wrapper.getServerVersion().toClientVersion();
|
||||
IRegistry<T> replacedRegistry = wrapper.getRegistryHolder().getRegistryOr(registry, version);
|
||||
return this.resolve(version, replacedRegistry);
|
||||
}
|
||||
|
||||
default MappedEntitySet<T> resolve(ClientVersion version, IRegistryHolder registryHolder, IRegistry<T> registry) {
|
||||
IRegistry<T> replacedRegistry = registryHolder.getRegistryOr(registry, version);
|
||||
return this.resolve(version, replacedRegistry);
|
||||
}
|
||||
|
||||
MappedEntitySet<T> resolve(ClientVersion version, IRegistry<T> registry);
|
||||
|
||||
boolean isEmpty();
|
||||
}
|
||||
+181
-1
@@ -24,10 +24,14 @@ 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.IRegistry;
|
||||
import com.github.retrooper.packetevents.util.mappings.IRegistryHolder;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiFunction;
|
||||
@@ -35,7 +39,8 @@ import java.util.function.BiFunction;
|
||||
/**
|
||||
* Either a key to a specific tag or a list of possible entities.
|
||||
*/
|
||||
public class MappedEntitySet<T> {
|
||||
@NullMarked
|
||||
public class MappedEntitySet<T extends MappedEntity> implements MappedEntityRefSet<T> {
|
||||
|
||||
private final @Nullable ResourceLocation tagKey;
|
||||
private final @Nullable List<T> entities;
|
||||
@@ -63,6 +68,27 @@ public class MappedEntitySet<T> {
|
||||
return new MappedEntitySet<>(new ArrayList<>(0));
|
||||
}
|
||||
|
||||
public static <Z extends MappedEntity> MappedEntityRefSet<Z> readRefSet(PacketWrapper<?> wrapper) {
|
||||
int count = wrapper.readVarInt() - 1;
|
||||
if (count == -1) {
|
||||
return new MappedEntitySet<>(wrapper.readIdentifier());
|
||||
}
|
||||
int[] entries = wrapper.readVarIntArrayOfSize(Math.min(count, 65536));
|
||||
return new IdRefSetImpl<>(entries);
|
||||
}
|
||||
|
||||
public static void writeRefSet(PacketWrapper<?> wrapper, MappedEntityRefSet<?> refSet) {
|
||||
if (refSet instanceof IdRefSetImpl<?>) {
|
||||
IdRefSetImpl<?> idRefSet = (IdRefSetImpl<?>) refSet;
|
||||
wrapper.writeVarInt(idRefSet.entries.length + 1);
|
||||
wrapper.writeVarIntArrayOfSize(idRefSet.entries);
|
||||
} else if (refSet instanceof MappedEntitySet<?>) {
|
||||
write(wrapper, (MappedEntitySet<?>) refSet);
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Unsupported mapped entity reference set implementation: " + refSet);
|
||||
}
|
||||
}
|
||||
|
||||
public static <Z extends MappedEntity> MappedEntitySet<Z> read(
|
||||
PacketWrapper<?> wrapper, BiFunction<ClientVersion, Integer, Z> getter) {
|
||||
int count = wrapper.readVarInt() - 1;
|
||||
@@ -90,8 +116,14 @@ public class MappedEntitySet<T> {
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static <Z extends MappedEntity> MappedEntitySet<Z> decode(
|
||||
NBT nbt, ClientVersion version, IRegistry<Z> registry) {
|
||||
return decode(nbt, PacketWrapper.createDummyWrapper(version), registry);
|
||||
}
|
||||
|
||||
public static <Z extends MappedEntity> MappedEntitySet<Z> decode(
|
||||
NBT nbt, PacketWrapper<?> wrapper, IRegistry<Z> registry) {
|
||||
List<Z> list;
|
||||
if (nbt instanceof NBTString) {
|
||||
String singleEntry = ((NBTString) nbt).getValue();
|
||||
@@ -117,7 +149,12 @@ public class MappedEntitySet<T> {
|
||||
return new MappedEntitySet<>(list);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static <Z extends MappedEntity> NBT encode(MappedEntitySet<Z> set, ClientVersion version) {
|
||||
return encodeRefSet(PacketWrapper.createDummyWrapper(version), set);
|
||||
}
|
||||
|
||||
public static <Z extends MappedEntity> NBT encode(PacketWrapper<?> wrapper, MappedEntitySet<Z> set) {
|
||||
if (set.tagKey != null) {
|
||||
return new NBTString("#" + set.tagKey);
|
||||
}
|
||||
@@ -130,6 +167,69 @@ public class MappedEntitySet<T> {
|
||||
return listTag;
|
||||
}
|
||||
|
||||
public static <Z extends MappedEntity> MappedEntityRefSet<Z> decodeRefSet(NBT nbt, PacketWrapper<?> wrapper) {
|
||||
return decodeRefSet(nbt, wrapper.getServerVersion().toClientVersion());
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static <Z extends MappedEntity> MappedEntityRefSet<Z> decodeRefSet(NBT nbt, ClientVersion version) {
|
||||
List<String> list;
|
||||
if (nbt instanceof NBTString) {
|
||||
String singleEntry = ((NBTString) nbt).getValue();
|
||||
// check whether this is a tag key or a single-entry list
|
||||
if (!singleEntry.isEmpty() && singleEntry.charAt(0) == '#') {
|
||||
String tagName = singleEntry.substring(1);
|
||||
ResourceLocation tagKey = new ResourceLocation(tagName);
|
||||
return new MappedEntitySet<>(tagKey);
|
||||
}
|
||||
// single entry list
|
||||
list = Collections.singletonList(singleEntry);
|
||||
} else {
|
||||
// assume it's a list
|
||||
NBTList<?> listTag = (NBTList<?>) nbt;
|
||||
list = new ArrayList<>(listTag.size());
|
||||
for (NBT tag : listTag.getTags()) {
|
||||
list.add(((NBTString) tag).getValue());
|
||||
}
|
||||
}
|
||||
return new NameRefSetImpl<>(list);
|
||||
}
|
||||
|
||||
public static <Z extends MappedEntity> NBT encodeRefSet(PacketWrapper<?> wrapper, MappedEntityRefSet<Z> refSet) {
|
||||
return encodeRefSet(refSet, wrapper.getServerVersion().toClientVersion());
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static <Z extends MappedEntity> NBT encodeRefSet(MappedEntityRefSet<Z> refSet, ClientVersion version) {
|
||||
if (refSet instanceof NameRefSetImpl<?>) {
|
||||
NameRefSetImpl<?> nameRefSet = (NameRefSetImpl<?>) refSet;
|
||||
NBTList<NBTString> listTag = NBTList.createStringList();
|
||||
for (String entityName : nameRefSet.entries) {
|
||||
listTag.addTag(new NBTString(entityName));
|
||||
}
|
||||
return listTag;
|
||||
} else if (refSet instanceof MappedEntitySet<?>) {
|
||||
return encode((MappedEntitySet<?>) refSet, version);
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Unsupported mapped entity reference set implementation: " + refSet);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappedEntitySet<T> resolve(PacketWrapper<?> wrapper, IRegistry<T> registry) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappedEntitySet<T> resolve(ClientVersion version, IRegistryHolder registryHolder, IRegistry<T> registry) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappedEntitySet<T> resolve(ClientVersion version, IRegistry<T> registry) {
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return this.entities != null && this.entities.isEmpty();
|
||||
}
|
||||
@@ -160,4 +260,84 @@ public class MappedEntitySet<T> {
|
||||
public String toString() {
|
||||
return "MappedEntitySet{tagKey=" + this.tagKey + ", entities=" + this.entities + '}';
|
||||
}
|
||||
|
||||
private static final class IdRefSetImpl<T extends MappedEntity> implements MappedEntityRefSet<T> {
|
||||
|
||||
private final int[] entries;
|
||||
|
||||
public IdRefSetImpl(int[] entries) {
|
||||
this.entries = entries;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappedEntitySet<T> resolve(ClientVersion version, IRegistry<T> registry) {
|
||||
List<T> entities = new ArrayList<>(this.entries.length);
|
||||
for (int entityId : this.entries) {
|
||||
entities.add(registry.getByIdOrThrow(version, entityId));
|
||||
}
|
||||
return new MappedEntitySet<>(entities);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return this.entries.length == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof IdRefSetImpl)) return false;
|
||||
IdRefSetImpl<?> idRefSet = (IdRefSetImpl<?>) obj;
|
||||
return Arrays.equals(this.entries, idRefSet.entries);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Arrays.hashCode(this.entries);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "IdRefSetImpl{entries=" + Arrays.toString(this.entries) + '}';
|
||||
}
|
||||
}
|
||||
|
||||
private static final class NameRefSetImpl<T extends MappedEntity> implements MappedEntityRefSet<T> {
|
||||
|
||||
private final List<String> entries;
|
||||
|
||||
public NameRefSetImpl(List<String> entries) {
|
||||
this.entries = entries;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappedEntitySet<T> resolve(ClientVersion version, IRegistry<T> registry) {
|
||||
List<T> entities = new ArrayList<>(this.entries.size());
|
||||
for (String entityName : this.entries) {
|
||||
entities.add(registry.getByNameOrThrow(entityName));
|
||||
}
|
||||
return new MappedEntitySet<>(entities);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return this.entries.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof NameRefSetImpl)) return false;
|
||||
NameRefSetImpl<?> that = (NameRefSetImpl<?>) obj;
|
||||
return this.entries.equals(that.entries);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(this.entries);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NameRefSetImpl{entries=" + this.entries + '}';
|
||||
}
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 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.util.mappings.IRegistryHolder;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* Used internally for loading additional data
|
||||
* after registry entries have already been added.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
@NullMarked
|
||||
public interface ResolvableEntity {
|
||||
|
||||
void doResolve(PacketWrapper<?> wrapper);
|
||||
}
|
||||
@@ -18,11 +18,17 @@
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.nbt;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.util.NbtDecoder;
|
||||
import com.github.retrooper.packetevents.protocol.util.NbtEncoder;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -108,6 +114,20 @@ public class NBTCompound extends NBT {
|
||||
return getTagOfTypeOrNull(key, NBTCompound.class);
|
||||
}
|
||||
|
||||
public Number getNumberTagValueOrThrow(String key) {
|
||||
return this.getNumberTagOrThrow(key).getAsNumber();
|
||||
}
|
||||
|
||||
public @Nullable Number getNumberTagValueOrNull(String key) {
|
||||
return this.getNumberTagValueOrDefault(key, null);
|
||||
}
|
||||
|
||||
@Contract("_, !null -> !null")
|
||||
public @Nullable Number getNumberTagValueOrDefault(String key, @Nullable Number number) {
|
||||
NBTNumber tag = this.getNumberTagOrNull(key);
|
||||
return tag != null ? tag.getAsNumber() : number;
|
||||
}
|
||||
|
||||
public NBTNumber getNumberTagOrThrow(String key) {
|
||||
return getTagOfTypeOrThrow(key, NBTNumber.class);
|
||||
}
|
||||
@@ -207,9 +227,92 @@ public class NBTCompound extends NBT {
|
||||
}
|
||||
|
||||
public boolean getBoolean(String string) {
|
||||
return this.getBooleanOr(string, false);
|
||||
}
|
||||
|
||||
public boolean getBooleanOr(String string, boolean defaultValue) {
|
||||
NBTNumber nbtByte = this.getTagOfTypeOrNull(string, NBTNumber.class);
|
||||
// Empty byte tags are considered 0
|
||||
return nbtByte != null && nbtByte.getAsByte() != 0;
|
||||
return nbtByte != null ? nbtByte.getAsByte() != 0 : defaultValue;
|
||||
}
|
||||
|
||||
@Contract("_, _, !null, _ -> !null")
|
||||
public <T> @Nullable T getOr(String key, NbtDecoder<T> decoder, @Nullable T def, PacketWrapper<?> wrapper) {
|
||||
NBT tag = this.getTagOrNull(key);
|
||||
return tag != null ? decoder.decode(tag, wrapper) : def;
|
||||
}
|
||||
|
||||
public <T> @Nullable T getOrNull(String key, NbtDecoder<T> decoder, PacketWrapper<?> wrapper) {
|
||||
return this.getOr(key, decoder, null, wrapper);
|
||||
}
|
||||
|
||||
public <T> T getOrThrow(String key, NbtDecoder<T> decoder, PacketWrapper<?> wrapper) {
|
||||
return decoder.decode(this.getTagOrThrow(key), wrapper);
|
||||
}
|
||||
|
||||
@Contract("_, _, !null, _ -> !null")
|
||||
public <T> @Nullable List<T> getListOr(String key, NbtDecoder<T> decoder, @Nullable List<T> def, PacketWrapper<?> wrapper) {
|
||||
NBT tag = this.getTagOrNull(key);
|
||||
if (tag instanceof NBTList) {
|
||||
// entries in list format
|
||||
List<? extends NBT> tags = ((NBTList<?>) tag).getTags();
|
||||
List<T> list = new ArrayList<>(tags.size());
|
||||
for (NBT element : tags) {
|
||||
list.add(decoder.decode(element, wrapper));
|
||||
}
|
||||
return list;
|
||||
} else if (tag != null) {
|
||||
// single entry
|
||||
List<T> list = new ArrayList<>(1);
|
||||
list.add(decoder.decode(tag, wrapper));
|
||||
return list;
|
||||
} else {
|
||||
// null, return default
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
public <T> @Nullable List<T> getListOrNull(String key, NbtDecoder<T> decoder, PacketWrapper<?> wrapper) {
|
||||
return this.getListOr(key, decoder, null, wrapper);
|
||||
}
|
||||
|
||||
public <T> List<T> getListOrEmpty(String key, NbtDecoder<T> decoder, PacketWrapper<?> wrapper) {
|
||||
return this.getListOr(key, decoder, Collections.emptyList(), wrapper);
|
||||
}
|
||||
|
||||
public <T> List<T> getListOrThrow(String key, NbtDecoder<T> decoder, PacketWrapper<?> wrapper) {
|
||||
List<T> list = this.getListOrNull(key, decoder, wrapper);
|
||||
if (list == null) {
|
||||
throw new IllegalStateException(MessageFormat.format("NBT {0} does not exist", key));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public <T> void set(String key, T value, NbtEncoder<T> encoder, PacketWrapper<?> wrapper) {
|
||||
this.setTag(key, encoder.encode(wrapper, value));
|
||||
}
|
||||
|
||||
public <T> void setList(String key, List<T> value, NbtEncoder<T> encoder, PacketWrapper<?> wrapper) {
|
||||
if (value.isEmpty()) {
|
||||
this.setTag(key, new NBTList<>(NBTType.END, 0));
|
||||
} else {
|
||||
// determine list type using first value in list
|
||||
NBT firstVal = encoder.encode(wrapper, value.get(0));
|
||||
NBTList<?> list = new NBTList<>(firstVal.getType(), value.size());
|
||||
list.addTagUnsafe(firstVal);
|
||||
// add remaining list entries
|
||||
for (int i = 1; i < value.size(); i++) {
|
||||
list.addTagUnsafe(encoder.encode(wrapper, value.get(i)));
|
||||
}
|
||||
this.setTag(key, list);
|
||||
}
|
||||
}
|
||||
|
||||
public <T> void setCompactList(String key, List<T> value, NbtEncoder<T> encoder, PacketWrapper<?> wrapper) {
|
||||
if (value.size() == 1) {
|
||||
this.set(key, value.get(0), encoder, wrapper);
|
||||
} else {
|
||||
this.setList(key, value, encoder, wrapper);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Loaded 100 of 261 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user