Compare commits

...
486 Commits
Author SHA1 Message Date
retrooper 55b548d3ca packetevents release 2.9.4 2025-07-22 21:10:14 +02:00
retrooper 8eff09ff6e feat: SpigotConversionUtil#getEntityMetadata is now part of the API 2025-07-22 20:00:50 +02:00
retrooper 59596653a2 patch: correct WrapperPlayServerWorldBorder implementation for versions lower than 1.12 2025-07-20 20:54:10 +02:00
retrooper 4df76391cb feat: add support for extracting metadata from a Bukkit entity in SpigotReflectionUtil 2025-07-20 20:37:24 +02:00
retrooper 822f1d26b8 patch: re-add support for outdated server software with no accessible version 2025-07-19 22:04:32 +02:00
retrooper 55a42ab0e2 increment packetevents version to 2.9.4-SNAPSHOT 2025-07-17 16:47:11 +02:00
retrooper cdf3521154 packetevents 2.9.3 release 2025-07-17 16:36:51 +02:00
retrooper 820b530240 add 1.21.8 server version constant 2025-07-17 16:11:48 +02:00
retrooper 1823f61748 increment version to 2.9.3-snapshot 2025-07-17 15:54:24 +02:00
retrooper d27d8ffd6a packetevents 2.9.2 release 2025-07-17 15:18:28 +02:00
retrooper 7a57012822 Revert "Cleanup gradle configuration mess"
This reverts commit cfb054b8b2.
2025-07-17 14:01:23 +02:00
retrooper 0a10f4d861 Merge pull request #1265 from Luuzzi/2.0
fix spawn position for versions lower than 1.8 & protocol 4 support
2025-07-13 22:52:41 +02:00
retrooper d1a3145483 Merge pull request #1300 from GrimAnticheat/feature/read-list-max-size
Add new readList(Reader<K> reader, int maxSize) function to PacketWrapper
2025-07-13 22:46:25 +02:00
retrooper 08096106f8 patch: UserLoginEvent always fired in PlayerJoinEvent to provide UUID and username (so it's not a breaking change). 2025-07-13 22:41:22 +02:00
Luuzzi a3fbccc454 1.7.5 and lower doesn't have action START_JUMPING_WITH_HORSE 2025-07-13 20:36:10 +03:00
Luuzzi 9ea931d58d resolve #1301 2025-07-13 20:19:39 +03:00
Alexandr 364be4e34d Merge branch 'retrooper:2.0' into 2.0 2025-07-12 19:11:19 +03:00
Axionize b22394c288 Add new readList(Reader<K> reader, int maxSize) function to PacketWrapper 2025-07-12 09:49:19 -04:00
retrooper 208dfbc3f3 Merge pull request #1294 from booky10/fix/gradle-config-mess
Cleanup gradle configuration mess
2025-07-10 09:11:36 +02:00
booky10 cfb054b8b2 Cleanup gradle configuration mess 2025-07-10 04:58:23 +02:00
booky10 f47e6880fd [skip ci] Add fabric production run task 2025-07-10 02:53:39 +02:00
booky10 f55f791f8a [skip ci] Update gradle wrapper to v8.14.3 2025-07-10 02:53:38 +02:00
booky10 ba389ddb57 [skip ci] Fix changelog 2025-07-10 02:53:38 +02:00
booky10 2ce143d466 [skip ci] Increment version to v2.9.2 snapshot 2025-07-10 02:53:38 +02:00
booky10 b7f99503d9 Release packetevents v2.9.1 2025-07-10 02:14:43 +02:00
booky10 52adfbae8a Fix "publishMods" task name breaking shadow jar exclusions
This should be fixed properly, this is just a quick fix to get out a proper release
2025-07-10 02:08:11 +02:00
booky10 a861066cab Don't copy artifacts to root build directory 2025-07-10 02:07:21 +02:00
retrooper 1acec02bfb PacketEvents 2.9.1 snapshot 2025-07-10 01:27:48 +02:00
retrooper b88857386a Release PacketEvents 2.9.0 2025-07-10 00:42:32 +02:00
retrooper 4c48d4c1df Merge pull request #1291 from booky10/feat/publishing-workflow
Automatic release publishing
2025-07-10 00:34:47 +02:00
retrooper 68f8fd3d03 Merge pull request #1290 from booky10/fix/recursive-dialog-resolving
Store dialog click event field as reference for names
2025-07-10 00:29:56 +02:00
retrooper 2d625c6e7a feat: add setters to WrapperPlayServerWorldBorder 2025-07-10 00:15:19 +02:00
booky10 83fe2cce0d Revert "Setup testing setup v2"
This reverts commit 11e4033ec6.
2025-07-09 23:46:20 +02:00
booky10 73bfaebab6 Fix publishing type for github release
Was stable even for snapshots because version isn't set yet in root project
2025-07-09 23:39:57 +02:00
booky10 2ac61fd5cb Fix snapshot detection 2025-07-09 23:30:04 +02:00
booky10 7d31150b35 Add v2.6.0 and v2.7.0 changelogs to CHANGELOG.md 2025-07-09 23:28:19 +02:00
booky10 11e4033ec6 Setup testing setup v2 2025-07-09 23:20:51 +02:00
booky10 a6a8866727 Revert "Setup testing setup"
This reverts commit 84a0759288.
2025-07-09 23:20:08 +02:00
booky10 ce61c3ef52 Fix github tag name 2025-07-09 23:13:50 +02:00
retrooper 4602ea8107 Merge pull request #1251 from booky10/fix/attempt-fixing-random-login-race-condition-injection-issues
Attempt fixing random login race condition injection issues
2025-07-09 23:12:48 +02:00
booky10 5fb1a6c85e Write changelog to github output instead of stdout 2025-07-09 23:12:05 +02:00
retrooper 7e2ac525ac Merge pull request #1287 from booky10/feat/effect-wrapper
Add missing WrapperPlayServerEffect
2025-07-09 23:07:55 +02:00
booky10 7590d6f7de Fix missing loaders field for modrinth publishing 2025-07-09 22:58:24 +02:00
booky10 d7c2284ccb Add gradle preparation step to release workflow 2025-07-09 22:51:30 +02:00
booky10 84a0759288 Setup testing setup 2025-07-09 22:46:10 +02:00
booky10 0ca8e27fc8 Finish implementing release workflow 2025-07-09 22:43:04 +02:00
retrooper 5e30aef0a1 patch: correction of WORLD_BORDER wrapper 2025-07-09 21:26:31 +02:00
retrooper 9e53791fef patch: WrapperPlayServerWorldBorder exception fix for 1.8-1.11.2 2025-07-09 21:12:06 +02:00
booky10 8346918e86 Start implementing release automation workflow 2025-07-09 19:30:31 +02:00
booky10 7714c6253a Store dialog click event field as reference for names 2025-07-09 18:19:35 +02:00
booky10 0a00e970d7 Access ResourceKey location using fields instead of methods
Method order is sort-of unpredictable, my test in 1.21.4/1.21.6 resulted in the registry name being returned instead of the registry entry's name
2025-07-09 17:37:31 +02:00
retrooper d0dd8dc4cd patch: potentially fix SpigotConversionUtil#typeFromBukkitWorld for 1.17+ 2025-07-09 17:18:16 +02:00
booky10andjtJava bc01609828 Add missing WrapperPlayServerEffect
Based on https://github.com/retrooper/packetevents/pull/702

Fixes https://github.com/retrooper/packetevents/issues/415
Fixes https://github.com/retrooper/packetevents/pull/423

Co-authored-by: jtJava <ilovefuud@gmail.com>
2025-07-09 16:59:44 +02:00
booky10 c6e7bcb980 Remove useless zero-byte-suffix for chunk data
Mojang fixed the issue in 1.21.6, but we forgot to remove our fix too
2025-07-09 16:33:27 +02:00
booky10 8987194030 Fix changes to ChatMessage
Some small fixes to https://github.com/retrooper/packetevents/pull/1267

* Uses consistent version-specific gson serializer instead of platform-dependent one
* Uses component getters/setters instead of directly accessing field to allow for overrides to work
2025-07-09 15:52:45 +02:00
booky10 4495db796d Update comment in PlayerManagerImpl 2025-07-09 15:44:29 +02:00
booky10 e1a29a20a7 Small cleanup for listeners 2025-07-09 15:40:57 +02:00
booky10 bd5ef7cb30 Update to support paper's configuration api
Paper no longer creates the player object during the configuration phase, like vanilla
Also, paper has removed the early connection reference in the player object added by CraftBukkit in 1.20.5

PacketEvents now uses the pre-1.20.5 logic for extracting the player reference
As a result, all handshake/status/login/config packets won't have access to the player object;
play packets should always have the player set
2025-07-09 15:38:15 +02:00
booky10 36363c885c Merge branch '2.0' into fix/attempt-fixing-random-login-race-condition-injection-issues 2025-07-09 14:42:12 +02:00
retrooper a198f0e8d6 Merge pull request #1286 from retrooper/revert-1250-dev
Revert "Refactor TaskWrapper into interface and implementation classes"
2025-07-08 19:39:41 +02:00
retrooper 69cbe1e405 Revert "Refactor TaskWrapper into interface and implementation classes" 2025-07-08 19:39:19 +02:00
retrooper 2b0ec87da6 Merge pull request #1250 from ShortyDev/dev
Refactor TaskWrapper into interface and implementation classes
2025-07-08 14:46:55 +02:00
retrooper 08f95b8036 Merge branch '2.0' of https://github.com/retrooper/packetevents into 2.0 2025-07-08 14:34:42 +02:00
retrooper a15ad3a8d7 patch: typo, put actual code in comment; also removed previous sponsor of computational servers; 2025-07-08 14:34:35 +02:00
retrooper fef7f983b0 Merge pull request #1267 from iiAhmedYT/patch-1
Allow getting/setting json in ChatMessage
2025-07-08 14:27:57 +02:00
retrooper 71eae683fb Merge remote-tracking branch 'origin/2.0' into 2.0 2025-07-08 14:21:22 +02:00
retrooper f692f41025 patch: fix the plugin disabling on unsupported version check 2025-07-08 14:21:09 +02:00
retrooper 3b4acde6f8 Merge pull request #1273 from ineanto/2.0
feat: add RemoteChatSession getter
2025-07-08 14:13:17 +02:00
retrooper 6b14595582 patch: import optimization in spigot reflection util 2025-07-08 13:40:58 +02:00
retrooper 50c2a69449 patch: packetevents disables itself when running on an unsupported Minecraft version;
changing "packetevents 2.0 failed to inject" message;
2025-07-07 19:32:23 +02:00
Alexandr b62fc6922c Merge branch 'retrooper:2.0' into 2.0 2025-06-30 06:55:33 +03:00
booky 1b5479f04f Merge pull request #1269 from HSGamer/2.0
correctly parse payload in WrapperCommonClientCustomClickAction
2025-06-29 17:20:13 +02:00
booky10 ac0041ff52 Read nbt end tags as null for custom click action packet 2025-06-29 17:13:25 +02:00
Luuzzi c6f129cdd3 added setData and getData to WrappedBlockState 2025-06-28 22:49:57 +03:00
ineanto 21226e6ac9 feat: add remote chat session getter via reflection 2025-06-28 21:41:46 +02:00
hsgamer b14f5f5031 correctly parse payload in WrapperCommonClientCustomClickAction
the payload is either an NBT or NBTEnd, but no boolean byte. So we don't have to check optional
close #1268
2025-06-27 13:22:11 +07:00
Ahmed Waleed 6ff9f8c401 Allow getting/setting json in ChatMessage 2025-06-27 02:04:00 +03:00
Luuzzi 22b28b7b35 1_7_10 -> 1_7_2. Also wrapper fixes 2025-06-26 23:23:17 +03:00
Luuzzi 9e7de426c0 fix incorrect shifts(get, set) in Chunk_v1_7 2025-06-26 13:17:53 +03:00
retrooper 77abb65bab Merge pull request #1264 from booky10/feat/1.21.7-support
1.21.7 support
2025-06-26 08:50:49 +02:00
Luuzzi a5188e5d78 added support for 1.7.2-1.7.5, seems it works fine 🤔 2025-06-26 07:03:53 +03:00
Luuzzi cce0ac2d7b fix spawn position for versions lower than 1.8 2025-06-26 06:27:49 +03:00
booky10andSteaf23 001f6b9fd7 Fix InputControl encoding
Co-authored-by: Steaf23 <steafmobile@gmail.com>
2025-06-26 03:44:27 +02:00
booky10 0395378726 Update registries for 1.21.7 2025-06-26 03:09:57 +02:00
booky10 31fe7a89d9 Add 1.21.7 protocol constants 2025-06-26 03:03:38 +02:00
booky d8b47495e4 Merge pull request #1258 from dawon/bugfix/fix-waypoint-info-types
Fix WaypointInfo types
2025-06-20 14:36:29 +02:00
Jakub Zacek cba4603ad8 Fix WaypointInfo types 2025-06-20 13:55:48 +02:00
booky10 f37c74d0d9 Convert PacketEventsEncoder to simple ChannelOutboundHandlerAdapter
This allows cancelling packets without throwing exceptions around

Fixes https://github.com/retrooper/packetevents/issues/1256
2025-06-19 19:34:27 +02:00
booky10 2085dfb84b Skip generating useless CancelPacketException stacktrace 2025-06-19 19:33:40 +02:00
booky10 cdad13d5c5 Fix WrapperPlayClientEntityAction actions for 1.21.6+
Fixes https://github.com/retrooper/packetevents/issues/1254
2025-06-19 19:12:35 +02:00
retrooper 95b50a44e9 Merge pull request #1255 from Cyramek/direction-fix 2025-06-19 17:30:31 +02:00
cyramek 78f630b5c1 fix direction vector being different from vanilla 2025-06-19 16:58:27 +02:00
retrooper 08d000ea82 Merge pull request #1234 from huanmeng-qwq/impl/advancements
Implement WrapperPlayServerUpdateAdvancements
2025-06-19 12:19:42 +02:00
booky10 28c4fdc7ce Merge branch '2.0' into fix/attempt-fixing-random-login-race-condition-injection-issues 2025-06-19 02:58:42 +02:00
booky10 96c81a69ae Fix compatibility with netty v4.0 (e.g. used by minecraft 1.8) 2025-06-19 02:58:21 +02:00
booky10 83720c6a81 Fix race condition on login for versions older than 1.20.5 2025-06-19 02:48:09 +02:00
booky10 c95acffab6 Resolve user in loginevent for 1.20.5+ 2025-06-19 02:01:37 +02:00
booky10 c2beb331f1 Implement support for resolving player connection through transferCookieConnection field
This makes it possible to get the connection info from a player object much sooner than otherwise
2025-06-19 01:57:07 +02:00
booky10 2667431ec9 Don't resolve entity id getter method by name 2025-06-18 23:19:23 +02:00
booky10 21ce0f4d34 Small cleanup to other advancement classes 2025-06-18 23:00:40 +02:00
booky10 21c1a7dfa8 Clean up Advancement class
- Removes version parameter from read method
- Convert comments to javadoc
- Add constructor for constructing Advancement without criteria list parameter
- Reorder getters/setters
2025-06-18 23:00:25 +02:00
booky10 518a995e8e Add abstraction class for criterion value in AdvancementProgress 2025-06-18 22:58:49 +02:00
booky10 e20e0854ab Remove unused ClientAsset 2025-06-18 22:58:28 +02:00
booky10 7c3cde51f0 Reformat WrapperPlayServerUpdateAdvancements
- Convert comments to javadoc
- Reorder getter/setter
- Don't make "showAdvancements" field nullable
2025-06-18 22:33:28 +02:00
booky10 cc18a7ad08 Don't register debug listener 2025-06-18 22:28:49 +02:00
booky10 35fa135e9e Fix formatting of Advancement/AdvancementDisplay 2025-06-18 22:26:52 +02:00
booky10 c68fe76156 Merge branch '2.0' into impl/advancements 2025-06-18 22:23:57 +02:00
retrooper 80846cfea2 Merge pull request #1247 from booky10/feat/1.21.6-support
1.21.6 support
2025-06-18 22:03:28 +02:00
retrooper 1a1b03c1f5 i'm not religious, but god bless aboookyrica 2025-06-18 22:01:26 +02:00
booky10 c411a1925b Also support void promises for sponge 2025-06-18 21:46:08 +02:00
booky10 d8b4f5b1b6 Account for void promises while writing on spigot platform 2025-06-18 21:37:16 +02:00
booky10 486c9a493a Add hydration block state property 2025-06-18 21:02:04 +02:00
booky10 b1ed98f53d Fix fabric connection error 2025-06-18 21:01:53 +02:00
ShortyDev ca8ca782fc refactor TaskWrapper into interface and implementation classes 2025-06-18 20:10:49 +02:00
booky10 c75f039c99 Update adventure to v4.23.0 2025-06-18 19:08:38 +02:00
booky10 c1324fe7fe Update adventure to v4.22.0 2025-06-17 18:06:52 +02:00
booky10 781d4a7c82 Add new ui sound category 2025-06-17 18:06:52 +02:00
retrooper 590479adda patch: ensure consistent naming of #getGameMode and #setGameMode 2025-06-17 16:48:37 +02:00
retrooper df2c50ccfc patch: ensure code can compile 2025-06-17 13:50:49 +02:00
retrooper f5b60ea3f2 feat: changed WrapperPlayServerUpdateAdvancements design; updated it to 1.21.5; relocated advancement classes to advancements folder; (requires some testing still) 2025-06-17 13:45:56 +02:00
booky10 c95194f147 Fix test errors 2025-06-16 05:16:03 +02:00
booky10 56a643f8d0 Implement item attribute display for 1.21.6 2025-06-16 04:54:42 +02:00
booky10 7daed688e0 Update equippable component to 1.21.6 2025-06-16 04:28:11 +02:00
booky10 f3782dffe1 Finish implement dialog bodies 2025-06-16 04:21:09 +02:00
booky10 b06063ebf7 Finish implement dialog inputs 2025-06-16 03:53:28 +02:00
booky10 6cb3d301d8 Finish implementing dialog types 2025-06-16 03:16:39 +02:00
booky10 1aab738dd5 Implement dialog actions 2025-06-16 02:44:07 +02:00
booky10 0aafad8b58 Some more dialog progress 2025-06-13 17:04:21 +02:00
huanmeng-qwq 910d77252e fix: Advancement#read & write 2025-06-13 21:59:52 +08:00
retrooper 524e6ca16d patch: added copyright notice to update advancements wrapper 2025-06-13 15:15:58 +02:00
retrooper 1aa88d05bf feat: more progress to WrapperPlayServerUpdateAdvancements; updating to 1.21.5 (incomplete) 2025-06-13 15:11:40 +02:00
huanmeng-qwq 70271f3694 update 2025-06-13 11:52:41 +08:00
booky10 62201ae3fa Start implementing dialogs 2025-06-11 17:55:36 +02:00
booky10 8ce56fc346 Quick fabric module update 2025-06-11 16:45:44 +02:00
booky10 8029fd1b4e Update block and item tags for 1.21.6 2025-06-11 16:39:27 +02:00
booky10 de19712dbb Add missing WrapperConfigServerPing 2025-06-11 16:33:12 +02:00
booky10 1d41037bdd Implement WrapperPlayClientChangeGameMode 2025-06-11 16:26:53 +02:00
booky10 a98b8c5604 Implement WrapperPlayServerWaypoint 2025-06-11 16:24:47 +02:00
booky10 7d5d2682b7 Implement waypoint api 2025-06-11 16:21:36 +02:00
booky10 2b5f8027f0 Implement new clientbound show dialog packet wrappers partially 2025-06-11 15:45:09 +02:00
booky10 1e37351b48 Implement new clientbound clear dialog packet wrappers 2025-06-11 15:40:49 +02:00
booky10 70c8aad74e Implement new serverbound custom click action packet wrappers 2025-06-11 15:38:03 +02:00
booky10 5527546f05 Update existing packet wrappers to 1.21.6 2025-06-11 15:18:56 +02:00
booky10 56671341ae Update packet type mappings for 1.21.6 2025-06-11 15:03:11 +02:00
booky10 41ea688ff3 Update registries for 1.21.6 2025-06-11 14:54:16 +02:00
booky10 004195144d Implement new cloud height for dimension types 2025-06-11 14:22:55 +02:00
booky10 962aefba17 Add new 1.21.6 version constants 2025-06-11 14:13:15 +02:00
huanmeng-qwq 88ec7a583d remove final modifier 2025-05-28 10:36:09 +08:00
huanmeng-qwq 2303d362d7 add setter 2025-05-28 10:32:34 +08:00
retrooper da0e95fa03 Merge pull request #1238 from booky10/fix/enchantment-refs
Fix issues with enchantment loading
2025-05-25 11:56:07 +02:00
booky10 c98bfad8b8 Merge branch '2.0' into fix/enchantment-refs 2025-05-25 04:59:33 +02:00
booky10 3dfb8389dc Bump gradle wrapper validation action to v4
I hope this fixes these random errors while building
2025-05-25 04:57:03 +02:00
booky10 7c74dd2e05 Allocate new buffer when re-encoding clientbound buffers with a limited capacity
Bungee now limits the maximum capacity of bytebufs, presumably because of https://github.com/SpigotMC/BungeeCord/commit/1279cca971b2d32b6bd75103d3a555fbbd629392

This now allocates a completely new bytebuf to ensure we don't run into the maximum bytebuf capacity

Fixes https://github.com/retrooper/packetevents/issues/1227
2025-05-25 04:56:21 +02:00
booky10 05eabbf667 Decode enchantment type exclusive set as mapped entity ref set on registry synchronization 2025-05-25 04:22:12 +02:00
booky10 d1cafe2bcc Resolve self-reference registry after adding entries to registry
Only relevant to enchantments for now
2025-05-25 03:57:49 +02:00
booky10 26078fcb59 Implement MappedEntityRefSet 2025-05-25 03:44:03 +02:00
booky10 3d602b9f96 Fix item reading/writing for 1.13/1.13.1
Just for future reference, so I don't have to remap + decompile these jars again:
* 1.12.2 logic: https://haste.pinofett.de/degt0ejhbr.java
* 1.13/1.13.1 logic: https://haste.pinofett.de/omr31l9mv9.java
* 1.13.2 logic: https://haste.pinofett.de/iul6y7vvny.java
2025-05-25 02:57:11 +02:00
huanmeng-qwq df4f9e425e update 2025-05-24 14:44:41 +08:00
huanmeng-qwq efb9766388 convert time to Optional 2025-05-23 18:17:27 +08:00
huanmeng-qwq ab0ad68d43 update 2025-05-23 18:12:38 +08:00
huanmeng-qwq 1be8db5ff4 update 2025-05-23 18:09:36 +08:00
huanmeng-qwq 1f68ee1f46 convert showAdvances to Optional 2025-05-23 18:00:13 +08:00
huanmeng-qwq e7c6ae4726 Implement WrapperPlayServerStatistics 2025-05-23 17:48:09 +08:00
huanmeng-qwq 5db1671895 Implement WrapperPlayServerUpdateAdvancements 2025-05-23 17:47:49 +08:00
retrooper 023a0da619 packetevents description change 2025-05-16 15:46:40 +02:00
retrooper 51863fa435 bump version to 2.8.1 snapshot 2025-05-15 15:20:19 +02:00
retrooper f46ec64e60 update: 2.8.0 release 2025-05-15 14:33:04 +02:00
retrooper f0d7a8e84d patch: fix tropical fish pattern mappings 2025-05-15 14:12:49 +02:00
retrooper ac4fac85ed Merge pull request #1220 from Loyisa/2.0
fix: minecraft:air isn't empty in <1.11
2025-05-14 23:49:46 +02:00
retrooper 8f274e0695 Merge pull request #1224 from Bram1903/fix/legacy-item-damage
Fixed: ItemStack#getDamageValue & ItemStack#setDamageValue
2025-05-14 13:03:45 +02:00
Bram cd0892ffe4 Fixed: ItemStack#getDamageValue & ItemStack#setDamageValue on version 1.12.2 and below 2025-05-11 20:42:43 +02:00
Loyisa f9398b58f7 fix: minecraft:air isn't empty in 1.8 2025-05-06 18:43:51 +08:00
booky10 9c9f5cf41d Fix missing saddle EquipmentSlotGroup 2025-05-03 17:50:21 +02:00
retrooper 5983395561 chore: update adventure to 4.21.0 (for 1.21.5 support) 2025-05-01 13:35:53 +02:00
retrooper 686bb4fd3f Merge pull request #1216 from Axionize/fix/teleport-flags
Fix Setting RelativeFlags
2025-05-01 13:31:24 +02:00
retrooper ff4ac7eefc Merge pull request #1162 from Rubenicos/fix/field-lookup
Fix recursive field lookup
2025-04-30 21:04:16 +02:00
retrooper 20b52fbcd9 Merge pull request #1212 from Beaness/patch-1
Add missing copy fields to spawn player wrapper
2025-04-30 21:01:33 +02:00
Axionize 424fd149e7 Fix setting relativeflags 2025-04-30 14:24:34 -04:00
Beanes e372f4f30a Add missing copy fields to spawn player wrapper 2025-04-28 21:11:59 +02:00
retrooper b520a2ea99 Merge pull request #1205 from booky10/feat/versioned-itemstacks
Add version and registry context to ItemStacks
2025-04-28 17:51:48 +02:00
booky10 4e4174b7d3 Add version and registry context to ItemStacks
As logic related to ItemStack has changed quite a lot throughout the versions, this now adds a version (and registry) field to ItemStacks
These fields are populated by packetevents automatically when reading ItemStacks

Using this new version, this properly updates the ItemStack api methods to how vanilla handles stuff now
Additionally, this should fix issues related to modern handling of item amounts breaking legacy negative stack sizes
(E.g. see https://github.com/retrooper/packetevents/pull/1192 and https://github.com/retrooper/packetevents/pull/1062)
2025-04-19 04:54:21 +02:00
booky10 0931f7c9e7 Merge remote-tracking branch 'upstream/2.0' into 2.0 2025-04-18 23:33:58 +02:00
booky10 4faf97cdb4 Increase bytebuf capacity when writing zero-byte-suffix for chunk data
See https://github.com/retrooper/packetevents/issues/1202#issuecomment-2816226784 for more info

Fixes #1202
2025-04-18 23:33:30 +02:00
booky 71fa7be70d Merge pull request #1158 from spring-dependency-management/spring-dependency-management-patch-1
Check classes before copying from last
2025-04-18 23:16:33 +02:00
booky a7cb0ce6bf Merge pull request #1177 from Axionize/refactor/eliminate-static-ProtocolManager-USERS-&-CHANNELS-use
Eliminate usage of static ProtocolManager fields which should be accessed on an instance basis
2025-04-18 20:03:04 +02:00
booky10 8fa1b820d4 Don't iterate over all channels when disconnecting a channel without a UUID 2025-04-18 19:09:01 +02:00
booky10 05f42bc9d5 Mark internal fields/methods as internal 2025-04-18 19:08:14 +02:00
booky10 b635dcbe54 Merge branch '2.0' into refactor/eliminate-static-ProtocolManager-USERS-&-CHANNELS-use 2025-04-18 19:01:42 +02:00
booky10 a1def4170c Check if last wrapper is an instance of this wrapper when copying 2025-04-18 18:59:02 +02:00
booky 53f1fc495b Merge pull request #1191 from Axionize/feat/runtime-obselete-annotation
Add new RuntimeObsolete annotation used for checking if a field is obsolete at runtime via reflection
2025-04-18 18:55:37 +02:00
booky10 17086d3017 Add registry #getByNameOrThrow/#getByIdOrThrow api 2025-04-18 18:30:56 +02:00
booky10 d604e9d6af Fix nbt encoding/decoding of MappedEntitySet tags 2025-04-18 18:25:56 +02:00
booky 76aba6fb8d Merge pull request #1159 from spring-dependency-management/spring-dependency-management-patch-2
Add getWrapperClass() to packet type
2025-04-18 18:04:37 +02:00
booky10 5e8ad3e6e2 Add missing wrapper class for structure block packet 2025-04-18 18:00:58 +02:00
booky10 2f780a22a0 Merge branch '2.0' into spring-dependency-management-patch-2 2025-04-18 17:57:47 +02:00
booky 7549b22604 Merge pull request #1192 from ManInMyVan/fix/itemstack-type-getter
make itemstack type getter always return type
2025-04-18 17:48:32 +02:00
booky 8083725b96 Merge pull request #1197 from Luuzzi/2.0
fixed a floating-point issue in .nbt files
2025-04-18 15:31:21 +02:00
booky 3e624ebde5 Merge pull request #1203 from Bram1903/fix/NullDisconnectLog
[Fix] Disconnected `null` due to invalid packet console log
2025-04-18 15:11:19 +02:00
booky 16f031c585 Merge pull request #1204 from MachineBreaker/patch-1
Remove server version check for SelectBundleItem selectedItemIndex check
2025-04-18 13:56:27 +02:00
MachineBreaker 32f7d0b68b Actually remove the version check since its useless 2025-04-18 07:35:36 -04:00
MachineBreaker 8a3a418d05 Use correct server version for SelectBundleItem selectedItemIndex check 2025-04-18 07:33:54 -04:00
Bram 3a76049868 Fixed: Disconnected null due to invalid packet 2025-04-18 13:06:57 +02:00
booky10 e7495c2e85 Remove ingredient from TrimMaterial for 1.21.5 2025-04-14 18:54:45 +02:00
booky10 a2726516b3 Fix 1.21.5 player chat message writing 2025-04-14 18:50:36 +02:00
booky10 bf57fef29c Remove template item from TrimPattern for 1.21.5 2025-04-14 18:06:43 +02:00
retrooper a9679cd5b2 Merge pull request #1199 from bridgelol/patch-1
chore: bump adventure to 4.20.0
2025-04-12 14:39:52 +02:00
Bridge 8e3eba761d chore: bump adventure to 4.20.0 2025-04-12 14:02:04 +02:00
retrooper b4ef9b90b9 patch: slight change to project description 2025-04-12 09:35:39 +02:00
Luuzzi b2ccbe0bed fixed a floating-point issue in .nbt files 2025-04-11 09:49:35 +03:00
ManInMyVan 1913c6603e make itemstack type getter always return type 2025-04-07 17:25:52 -06:00
Axionize 9eafaaab7d Add new RuntimeObsolete annotation used for checking if a field is obsolete at runtime via reflection 2025-04-07 18:05:40 -04:00
booky e672aa2b92 Merge pull request #1190 from retrooper/revert-1180-fix/fix-goat-horn-cooldown
Revert "Fix Goat Horn Cooldown"
2025-04-07 23:02:46 +02:00
retrooper 1ba1ec17fa Revert "Fix Goat Horn Cooldown" 2025-04-07 18:02:46 +02:00
booky10 288b0a5bed Fix instrument component for versions older than 1.21.5 2025-04-07 15:40:56 +02:00
booky10 2bc4056c9c Don't use MappedEntity instance for extracting TypesBuilderData when defining in registry
Fixes https://github.com/retrooper/packetevents/issues/1187
2025-04-07 15:28:31 +02:00
retrooper 1c0b85a689 Merge pull request #1180 from Axionize/fix/fix-goat-horn-cooldown
Fix Goat Horn Cooldown
2025-04-06 13:59:41 +02:00
retrooper 51e2538ea4 patch: slight changing of messaging 2025-04-06 13:36:12 +02:00
booky10 47645e4ea0 Fix backwards compatibility packet wrapper creation in chunk reader 2025-04-05 18:25:40 +02:00
booky10 5aa121db9a Update entity types to 1.21.5
Fixes https://github.com/retrooper/packetevents/issues/1186
2025-04-05 14:06:32 +02:00
spring-dependency-management c32300cd04 rebase on 1.21.5 2025-04-05 02:01:15 +01:00
retrooper 0d9b183ea1 feat: support earlier access of player object (as soon as JOIN_GAME packet) on spigot 2025-04-04 23:16:42 +02:00
retrooper a215fd9b4d add .kotlin from buildSrc to gitignore 2025-04-04 21:00:30 +02:00
retrooper 2ffb9335b3 Merge pull request #1174 from booky10/feat/1.21.5-support
1.21.5 support
2025-04-04 20:57:35 +02:00
retrooper d9ddf4e598 feat: bump version up to 2.8.0-SNAPSHOT 2025-04-04 20:52:14 +02:00
retrooper eb3b9593be patch: add missing copyright statement 2025-04-04 20:31:42 +02:00
booky e49b989025 Merge pull request #1139 from ytnoos/fix-wrappers
Fixed some wrappers
2025-04-01 14:37:40 +02:00
booky fdd7947728 Merge pull request #1171 from Axionize/fix/mark-embedded-channels-as-fake
Mark embedded channels as fake
2025-04-01 14:28:45 +02:00
booky cc4b69acf5 Merge pull request #1166 from ManInMyVan/fix/trial-spawner-requiresCorrectTool
fix trial spawner requiresCorrectTool
2025-04-01 14:27:37 +02:00
booky 3139282035 Merge pull request #1176 from ManInMyVan/fix/sus-gravel-sand-requiresCorrectTool
fix suspicious gravel and sand requiresCorrectTool
2025-04-01 14:26:38 +02:00
booky10 9a721c79d5 Don't write entity type tags below 1.14 2025-03-31 18:55:24 +02:00
booky10 5c4ccc544c Fix a lot of random registry issues 2025-03-31 18:47:52 +02:00
booky10 751b93c51f Setup registry registration check
Validates that all registry entries have been defined
2025-03-31 18:16:20 +02:00
booky10 1a0c9da630 Add more command argument type mappings 2025-03-31 18:02:45 +02:00
booky10 383a680a70 Fix legacy support for attributes 2025-03-31 17:47:40 +02:00
booky10 83e600c301 Fix Chunk_v1_9 writing on proxy 2025-03-31 17:41:25 +02:00
booky10 f69eb78aa4 Small legacy palette improvements 2025-03-31 17:41:11 +02:00
booky10 c046bd5a9d Use correct server version when reading/writing Chunk_v1_9
Fixes errors on proxies
2025-03-31 17:32:42 +02:00
booky10 8740a5ed0f Don't skip prefix of zero-bytes if it doesn't exist
Thanks ViaVersion!
2025-03-31 17:19:09 +02:00
booky10 9e89b0a5c7 Fix WrapperPlayServerTeams 1.21.5 reading 2025-03-31 17:15:07 +02:00
booky10 5b45f3c634 Fix entity data type names 2025-03-31 17:02:12 +02:00
booky10 a95250f4f7 Save bits per entry in data palette
If the amount of bits gets changed while constructing the palette, the storage would have the wrong length of data
Instead, be safe and get the amount of bits from the palette after its construction
2025-03-31 16:55:44 +02:00
booky10 fb31dab995 Small chunk palette cleanup
Also adds back proper resizing to block state list palettes
2025-03-31 16:32:18 +02:00
booky10 d3aba54f69 Handle 1.21.5 broken mojang zero byte suffix
See https://bugs.mojang.com/browse/MC-296121
2025-03-31 16:31:32 +02:00
booky10 e823e17f69 Fix hover event text reading 2025-03-31 15:40:02 +02:00
booky10 98e46dd38a Add remaining components types for 1.21.5 2025-03-31 15:08:43 +02:00
booky10 405caec719 Merge branch '2.0' into feat/1.21.5-support 2025-03-31 13:59:01 +02:00
booky10 c32b1b90b1 Default model type of chicken/cow/pig variants to normal 2025-03-31 13:58:10 +02:00
booky 2272315d83 Merge pull request #1181 from AoElite/conversion-fix
Keep block property order to fix conversions
2025-03-31 07:32:54 +02:00
AoElite dfd8eccf87 add a basic test for material conversions 2025-03-31 00:32:32 -04:00
AoElite b826fbc197 block data property order needs to be preserved 2025-03-31 00:32:27 -04:00
booky10 878c7a96d6 Update adventure nbt serializer to 1.21.5 2025-03-30 23:06:31 +02:00
booky10 3a1474c5a6 Add per-version adventure serializers
Required for changes done to click/hover events in 1.21.5
2025-03-30 22:45:40 +02:00
booky10 0f94fc8216 Fix unbreakable item component legacy handling 2025-03-30 21:50:41 +02:00
booky10 445893d664 Fix ItemEquippable reading for 1.21.5 2025-03-30 21:46:30 +02:00
booky10 e8cc99fa0d Add can_destroy_blocks_in_creative field to tool item component for 1.21.5 2025-03-30 21:45:51 +02:00
booky10 9948837294 Ensure base components get fully read 2025-03-30 21:40:38 +02:00
booky10 3e0191aa17 Remove chunk data palette length prefix for 1.21.5 2025-03-30 21:23:17 +02:00
booky10 8a3ee34e28 Small cleanup for chunk palette resizing 2025-03-30 21:10:45 +02:00
booky10 ae317c535b Merge remote-tracking branch 'origin/feat/1.21.5-support' into feat/1.21.5-support 2025-03-30 20:07:13 +02:00
booky10 2949af533f Refactor chunk data reading/writing
This deprecates NetStreamInput/NetStreamOutput as they just duplicate PacketWrapper api and do not carry as much context as a PacketWrapper, which is required for proper proxy support

This is a pretty big change to how chunk reading/writing currently works and should therefore be tested on a lot of versions
2025-03-30 20:05:20 +02:00
retrooper e90f377c61 patch: imports of certain test files were removed by ide (for some odd reason) 2025-03-30 19:26:12 +02:00
retrooper 088ded2190 patch: add forgotten copyright statements 2025-03-30 19:20:26 +02:00
Axionize 93a6e3f5ed Fix Goat Horn Cooldown
Cooldown Length: 7.0 seconds
Resource Group: minecraft:goat_horn
Encoded String: QOAAAAETbWluZWNyYWZ0OmdvYXRfaG9ybg==

See: https://github.com/retrooper/packetevents/pull/1180#issuecomment-2764633510
2025-03-30 12:37:35 -04:00
booky10 63a6b158eb Verify reader index change when reading length-prefixed item component patches 2025-03-30 16:25:52 +02:00
booky10 c471b691f7 Update smithing trim slot display to 1.21.5 2025-03-30 16:14:23 +02:00
booky10 b2c4bb8928 Add new test block related block entity types for 1.21.5 2025-03-30 15:53:48 +02:00
booky10 253d5f968e Merge branch '2.0' into feat/1.21.5-support 2025-03-30 14:47:46 +02:00
booky10andAxionize 533274fd45 Fix WrappedBlockState stringification
Co-authored-by: Axionize <154778082+axionize@users.noreply.github.com>

Closes #1179
2025-03-30 14:45:24 +02:00
booky10 4a35ebf7eb Bump fabric loom, parchment mappings and fabric loader 2025-03-30 05:21:26 +02:00
booky10 9dd45ffc48 Update gradle wrapper to v8.13 2025-03-30 05:16:36 +02:00
booky10 1e8bee4179 Fix workflow distribution config
This should've errored long ago, adopt is already gone since summer 2021
2025-03-30 05:08:53 +02:00
booky10 b367e1da91 Fix static mapped entity constructors 2025-03-30 05:03:41 +02:00
booky10 2808e35234 Add equipOnInteract field to equippable component 2025-03-30 04:59:41 +02:00
booky10 df7b69249b Correctly implement "EitherHolder" 2025-03-30 04:52:49 +02:00
booky10 6650ee5d64 Update tooltip show flag in remaining components 2025-03-30 04:23:03 +02:00
booky10 c75e137bd0 Add type parameter to EntityData
Yes, this is a compile-time breaking change
2025-03-30 04:15:31 +02:00
booky10 57d00aaa4e Update entity data serializers to 1.21.5 2025-03-30 04:11:11 +02:00
booky10 e8a95aeb8e Update wolf variant encoding to 1.21.5 2025-03-30 03:51:18 +02:00
booky10 2fcdce578d Fix wolf variant default registry 2025-03-30 03:46:09 +02:00
booky10 ac729a30e3 Implement cat variant registry 2025-03-30 03:43:34 +02:00
booky10 2b626d38b1 Fully implement pig, frog, cow and chicken variant registries 2025-03-30 03:41:02 +02:00
booky10 a5d3633088 Implement wolf sound variant registry 2025-03-30 03:17:05 +02:00
booky10 c79cea2b42 Add registry synchronization todos 2025-03-30 01:54:00 +01:00
booky10 9c4e438099 Add new 1.21.5 particle types 2025-03-30 01:51:19 +01:00
booky10 7572eeb5ca Add more new item components 2025-03-30 01:49:46 +01:00
booky10 b78f8369f4 Implement basic component matcher support for adventure predicate item component 2025-03-30 01:30:30 +01:00
booky10 881898d788 Add potion duration scale item component 2025-03-30 00:48:20 +01:00
booky10 c355dbf1fc Add blocks attack item component 2025-03-30 00:47:48 +01:00
booky10 17262757ce Add weapon component 2025-03-30 00:30:19 +01:00
booky10 e890fcd7e5 Add new tooltip display component 2025-03-30 00:23:25 +01:00
booky10 90ff84471f Update unbreakable data component 2025-03-30 00:12:26 +01:00
booky10 963643bdeb Update creative inventory item packet to 1.21.5 2025-03-30 00:00:30 +01:00
booky10 12c2c307eb Implement length-prefixed item data component serialization 2025-03-29 23:57:46 +01:00
booky10 a4fefad9e6 Refactor item stack serialization to separate class 2025-03-29 23:15:29 +01:00
booky10 9bb7b6e458 Update WrapperPlayClientClickWindow to 1.21.5 2025-03-29 22:44:27 +01:00
booky10 18ed3fb529 Add initial HashedStack structure 2025-03-29 22:44:21 +01:00
booky10 6c70181d77 Implement support for new heightmap encoding in 1.21.5 2025-03-29 22:16:19 +01:00
booky10 ed848d93d3 Add WrapperPlayServerTestInstanceBlockStatus 2025-03-29 21:58:22 +01:00
booky10 db30205fa6 Add WrapperPlayClientSetStructureBlock 2025-03-29 21:54:08 +01:00
booky10 d33cb38f15 Add new 1.21.5 block state properties 2025-03-29 21:38:04 +01:00
booky10 1371809b37 Update sound events to 1.21.5 2025-03-29 21:29:37 +01:00
booky10 3a24bed6fb Update item tags for 1.21.5 2025-03-29 21:24:52 +01:00
booky10 ab5f4ee049 Update block tags for 1.21.5 2025-03-29 21:24:48 +01:00
booky10 da8bdd9384 Add new 1.21.5 state type constants 2025-03-29 21:16:57 +01:00
booky10 7e398fe45a Add new 1.21.5 item type constants 2025-03-29 21:16:53 +01:00
booky10 1f6314a262 Update item type base components 2025-03-29 21:10:17 +01:00
booky10 2c238c251e Update block state mappings 2025-03-29 21:10:09 +01:00
booky10 0018d60f9c Merge branch '2.0' into feat/1.21.5-support 2025-03-29 20:36:56 +01:00
booky10andAmmo f9670a71b1 Update last seen messages to 1.21.5
Co-authored-by: Ammo <ammo@slne.dev>
2025-03-29 20:36:32 +01:00
booky10 bede82c866 Add some more javadoc comments regarding new 1.21.5 additions 2025-03-29 20:35:20 +01:00
Ammo d5cca6490f feat: Update clientbound player team packet to use enums for name tag visibility and collision rule 2025-03-29 20:31:12 +01:00
Ammo 8f920cd6cc feat: Validate selectedItemIndex in WrapperPlayClientSelectBundleItem 2025-03-29 20:26:39 +01:00
Ammo 06eb3f4b90 chore: Update Minecraft version to 1.21.5 in gradle.properties of fabric to have access to nms classes 2025-03-29 20:24:53 +01:00
booky10 e57002768b Finish WrapperPlayClientTestInstanceBlockAction 2025-03-29 20:23:39 +01:00
booky10 a85de1cef2 Small chat message read/write cleanup 2025-03-29 20:23:33 +01:00
Axionize 39d45d8d1f Remove usage of direct external/public static references to ProtocolManager.CHANNELS and ProtocolManager.USERS
Fields will remain accessible for backwards compatibility in the unlikely case of a developer meddling these values in their own code.

All usage of both these fields is now wrapped in interface methods which can be overwritten by other ProtocolManagers.
2025-03-29 03:56:34 -04:00
retrooper 1bb6268a62 feat: add support for 1.21.5 in chat message packet 2025-03-28 20:46:53 +01:00
retrooper 4c87f3fce1 feat: set test block wrapper added 2025-03-28 20:12:49 +01:00
retrooper 86358c3fe9 Merge pull request #1148 from booky10/feat/lazy-loaded-registries
Registry cleanup and lazy-loaded block state mappings
2025-03-28 19:33:33 +01:00
ManInMyVan 34846df85b fix suspicious gravel and sand requiresCorrectTool 2025-03-27 20:19:04 -06:00
booky10 5b214e4187 Add 1.21.5 resource_selector command argument parser 2025-03-25 21:03:35 +01:00
booky10 5280f26e00 Setup 1.21.5 packet ids 2025-03-25 21:00:31 +01:00
booky10 8226aed28e Add 1.21.5 client and server version constants 2025-03-25 20:39:05 +01:00
Axionize ec4496f837 Add EmbeddedChannel as a FakeChannel name
- This prevents Carpet mod players from not fully existing/being invisible
- EmbeddedChannel is a standard netty channel used to mock/simulate a netty channel, and isn't used for actual player connections on any platform
2025-03-23 03:54:36 -04:00
booky10 91730fdb46 Add javadoc to User#getConnectionState
See https://github.com/retrooper/packetevents/issues/1170
2025-03-19 20:18:19 +01:00
ytnoos c892a15c5a Fixed write for 1.7 WrapperPlayClientTabComplete 2025-03-16 14:15:39 +01:00
ytnoos 2fc6613df0 Added WrapperPlayClientEditBook setters 2025-03-16 14:15:11 +01:00
ytnoos cf0a3115f0 Merge remote-tracking branch 'upstream/2.0' into fix-wrappers 2025-03-16 14:12:42 +01:00
ManInMyVan 513b970c4d fix trial spawner requiresCorrectTool 2025-03-14 11:59:52 -06:00
Rubén 2b03bbce7c Fix recursive field lookup 2025-03-08 12:14:06 -06:00
spring-dependency-management 319568d92a oops 2025-03-06 19:10:27 +00:00
spring-dependency-management f666047ae5 Some missing oops 2025-03-06 16:56:13 +00:00
spring-dependency-management e86beec90f add interface 2025-03-06 16:55:55 +00:00
spring-dependency-management 3d416fc961 Add getWrapperClass() to packet type 2025-03-06 16:47:50 +00:00
spring-dependency-management 2cd2f5d7f9 Check classes before copying 2025-03-06 15:35:31 +00:00
booky10 688e32d9a6 Merge branch '2.0' into feat/lazy-loaded-registries 2025-03-02 19:01:45 +01:00
booky ef49276809 Merge pull request #1155 from booky10/fix/bungee-injection-v2
Support bungee's new combined compressor
2025-03-02 19:00:13 +01:00
booky a3116dc2a6 Merge pull request #1149 from Axionize/fix/fabric-call-user-login-event
Fire UserJoinEvent() on Fabric
2025-03-02 18:57:54 +01:00
booky 3fda55bc39 Merge pull request #1134 from Axionize/fix/painting-registry-id-mappigns
Make PE painting IDs consistent
2025-03-02 18:54:59 +01:00
booky f78294afb4 Merge pull request #1140 from ytnoos/exceptiong-handling
Improved exception handling
2025-03-02 18:47:42 +01:00
booky 0a30904217 Merge pull request #1138 from ytnoos/propagate-exception
Propagate exception while reading NBT
2025-03-02 18:42:10 +01:00
booky 8a1506ee53 Merge pull request #1135 from Axionize/feat/cache-values-of-direction-for-fast-int-to-enum
Add new methods to Direction Enum and optimize by caching values array
2025-03-02 18:39:25 +01:00
booky10 795798de41 Read any number tag as enchantment level
Previously, packetevents would have only parsed shorts as the enchantment level
2025-03-02 18:30:56 +01:00
booky10 fed7c147d8 Support bungee's new combined compressor
See: https://github.com/SpigotMC/BungeeCord/commit/774a6fd68c8fbbb99b6bbe8c0060820f8c3b059e

Bungee combined both the frame encoder and the compressor, which makes handling compression a lot easier
This should still support both the old and the new compression setup
2025-03-02 03:39:00 +01:00
booky10 5cdb80c002 Account for null in-flight connection in velocity
Fixes https://github.com/retrooper/packetevents/issues/1142
2025-02-28 22:46:29 +01:00
booky10 57add57796 Try to do less server version lookups
Every call to do a server version lookup will return an invalid value for proxy servers
2025-02-28 22:45:18 +01:00
Axionize f7a72713e1 Fire UserJoinEvent() on Fabric 2025-02-28 15:27:55 -05:00
booky10 2c0a5346f4 Fix error when trying to load mappings for invalid mapping version 2025-02-28 20:47:15 +01:00
booky10 3627cd4d5a Reset reader index before resetting writer index
The writer index can't be smaller than the reader index according to netty buffers
2025-02-28 20:03:48 +01:00
booky10 6f39702af7 Ensure mapping data gets unloaded from all registries via test 2025-02-28 20:01:23 +01:00
booky10 fe316a4368 Small refactor to ClassStructureTest 2025-02-28 19:49:27 +01:00
booky10 e026ef8181 Move anonymous map decoration type class implementation to outer class 2025-02-28 19:39:54 +01:00
booky10 d9e78b71a6 Convert hard-coded villager professions to a registry 2025-02-28 19:36:49 +01:00
booky10 92fc265333 Convert hard-coded score format types to a registry 2025-02-28 19:32:56 +01:00
booky10 d75137fe5f Convert hard-coded villager types to a registry 2025-02-28 17:55:38 +01:00
booky10 3d90acad8e Fix class structure of mapped entity implementations 2025-02-28 17:48:03 +01:00
booky10 dc3c168d84 Implement class structure test
This ensures consistent usage of annotations and common method/field names for registry-related stuff
2025-02-28 17:47:01 +01:00
booky10 8a5d4fc3e0 Use a single buffer for parsing an item component map 2025-02-28 16:35:02 +01:00
booky10 8cbfde0c3f Convert particle types to a registry 2025-02-28 16:26:20 +01:00
booky10 9dc5908c5e Fix mapping file names in remaining registries 2025-02-28 16:17:29 +01:00
booky10 3bdab06db4 Convert sound events to a registry 2025-02-28 16:15:56 +01:00
booky10 e08b5f69bf Convert legacy recipe serializers to a registry 2025-02-28 16:12:22 +01:00
booky10 f6e76b65b6 Convert potions to a registry 2025-02-28 16:08:39 +01:00
booky10 bbf8749f1e Convert position source types to a registry 2025-02-28 16:06:50 +01:00
booky10 d4f7f64fc6 Convert entity types to a registry
Also refactor entity type instance checking logic
2025-02-27 22:53:43 +01:00
booky10 4a9cd4b8aa Convert entity data types to a registry
Also refactor reader/writer handling logic
2025-02-27 21:08:13 +01:00
booky10 83ae030352 Convert state types to a registry 2025-02-27 19:00:54 +01:00
booky10 88b3b00c43 Convert command argument parsers to a registry 2025-02-27 18:51:19 +01:00
booky10 3b9c3632ad Implement new item base components storage format 2025-02-27 18:47:09 +01:00
booky10 e8a8f0d0a3 Implement new mappings storage format for data mappings 2025-02-27 18:37:52 +01:00
booky10 113b4a84c2 Refactor how mappings are stored
These changes were done to split the block state mappings up into multiple files to prevent lazy-loading having to skip over the entire file for modern versions and to align mapping file names with vanilla registry names

Additionally, this also splits item base components into multiple files to prepare for lazy loading them too, as they will probably also constantly grow in size with each new release
2025-02-27 18:27:03 +01:00
booky10 a9a6c11402 Move each mappings file to a separate directory 2025-02-27 16:41:38 +01:00
booky10 2cb427e06d Small refactor for state data cache map 2025-02-24 17:56:17 +01:00
booky10 22bea4e7b0 Ensure loading of WrappedBlockState on all platforms 2025-02-24 17:43:13 +01:00
booky10 6703db2528 Add system property to force eager loading of all block state mappings 2025-02-24 17:41:21 +01:00
booky10 44223018b0 Implement lazy loading of block state mappings 2025-02-24 17:30:34 +01:00
booky10 d7b677c4db Convert block state map-in-map to map-in-array 2025-02-24 15:56:42 +01:00
retrooper e531e434b6 updated velocity to 3.4.0-SNAPSHOT, fixing build errors 2025-02-17 11:33:27 +01:00
booky10 97dcbc606e Fix login packet fields being read in wrong order
Fixes #1086
2025-02-13 16:11:18 +01:00
Axionize 4d55df1569 Add getting method for VALUES array and makes it private 2025-02-13 07:51:17 -05:00
ytnoos a028653207 Invert handshaking state check 2025-02-12 14:36:50 +01:00
Axionize 0d92230183 Add new methods to Direction enum and optimize by caching values array 2025-02-12 08:34:47 -05:00
ytnoos 5c6c41e62f Improved excpetiong handling 2025-02-12 12:51:43 +01:00
ytnoos 88ff380bbd Fixed WrapperPlayClientEditBook for <1.17.1 2025-02-12 12:31:30 +01:00
ytnoos 8dd207ccec Fixed WrapperPlayClientTabComplete for 1.7 2025-02-12 12:24:26 +01:00
ytnoos 73426fb7bf Propagate exception while reading NBT 2025-02-12 12:23:09 +01:00
Axionize 3f13e4374a Make PE painting IDs consistent
Modern Minecraft sends paintings over the network with ids not representing registration order, but rather alphabetical order.

This commit reorders the painting mappings to all be done in alphabetical order so the index IDs match up with vanilla.
2025-02-10 17:48:44 -05:00
retrooper 478a3e56c3 Merge pull request #1128 from booky10/feat/more-packet-user-utils
Add missing send/write/receive packet utils to User
2025-01-31 23:52:31 +01:00
booky10 699594090a Add missing send/write/receive packet utils to User 2025-01-31 12:09:34 +01:00
booky10 2a137b0059 Fix potted eye blossom blocking/solid flags 2025-01-23 15:32:11 +01:00
booky10 81c53d3c4c Mark resin brick wall as "shape exceeds cube" 2025-01-23 15:30:37 +01:00
booky c824f9c835 Merge pull request #1108 from spring-dependency-management/fix-fence
Fix pale oak materials
2025-01-23 14:44:07 +01:00
booky10 e1df40710e Fix incorrect shadow color deserialization/serialization
Previously, packetevents expected shadow color to be serialized as a hex string
Vanilla serializes shadow colors as a single integer instead
2025-01-18 20:13:45 +01:00
booky 6507a73042 Merge pull request #1110 from AoElite/2.0
add method to user to write packets silently
2025-01-12 03:09:12 +01:00
AoElite 6a99936110 add method to user to write packets silently 2025-01-11 21:04:04 -05:00
spring-dependency-management 93441ece77 Fix sapling, hanging sign, button, and moss carpet 2025-01-07 23:56:34 +00:00
spring-dependency-management f5776682ce Fix pale oak hanging sign 2025-01-07 23:49:35 +00:00
spring-dependency-management be264f3d81 Fix pale oak wall sign 2025-01-07 23:48:07 +00:00
spring-dependency-management 8fcef1d834 Fix pale oak sign 2025-01-07 23:46:55 +00:00
spring-dependency-management 8210bb32da Sapling is of type plant, not wood 2025-01-07 23:43:30 +00:00
spring-dependency-management 8b3ddb7b47 Fix pale oak pressure plate 2025-01-07 23:39:02 +00:00
spring-dependency-management dcb3e5e1cd .isShapeExceedsCube(true) for pale oak 2025-01-07 23:35:05 +00:00
retrooper 3d2a872de1 Merge pull request #1105
Keep Alive Version Check from V_1_12 to V_1_12_2
2025-01-06 00:25:07 +01:00
retrooper 61f5158279 patch: version check correction in WrapperPlayServerKeepAlive 2025-01-06 00:21:45 +01:00
scienziato1pazzo ce481cfdb0 fixed keep alive 2025-01-04 00:01:55 +01:00
retrooper 3d5c294f64 update wiki vg link 2024-12-23 20:03:14 +01:00
retrooper 4f0678d782 Merge pull request #1098 from divinepablo/patch-1
Update protocol link
2024-12-23 20:02:07 +01:00
divine 9b1f7a372c Update protocol link
wiki.vg merged with minecraft.wiki
2024-12-23 12:33:31 -05:00
retrooper 9a1ee3d888 update to adventure 4.18.0 2024-12-23 10:34:20 +01:00
retrooper 4f20680d5b Revert "Temporarily revert shadow color support"
This reverts commit 0be838c58f.
2024-12-23 10:20:31 +01:00
retrooper dd5a25eb66 Merge pull request #1097 from HaHaWTH/fix/folia-scheduling 2024-12-23 00:20:29 +01:00
HaHaWTH 3a3f8c498c Use correct scheduler for tasks
In some rare cases, player may be teleported during join and kick will fail
2024-12-22 13:55:28 -08:00
booky f603b49a3e Merge pull request #1053 from Axionize/fix-legacy-grass-and-tallgrass-mappings
Fix legacy mappings for grass and tallgrass variants
2024-12-22 06:34:54 +01:00
booky 52e182e7f0 Merge pull request #1058 from ManInMyVan/player-digging-face-id
add faceid to WrapperPlayClientPlayerDigging
2024-12-22 06:29:59 +01:00
booky10 7cc925120e Add some missing entity type ids for 1.8 through 1.11 2024-12-22 05:57:15 +01:00
booky10 603cb07c27 Fix wrong skeleton entity type id for versions older than 1.11
Fixes #1068
2024-12-22 05:57:14 +01:00
booky 7b5019ba87 Merge pull request #1047 from Axionize/coral-tags
Extend coral plant blocktags
2024-12-22 05:21:26 +01:00
libraryaddictandbooky10 40f6b2fca4 Fix incorrect sound mappings for 1.19.4
Closes #1059

I didn't merge the original PR as it breaks sound mappings for 1.19.3

Co-authored-by: booky10 <boooky10@gmail.com>
2024-12-22 05:15:35 +01:00
booky10 1e50c5d6cb Fix jukebox playable item component reading/writing
Packetevents didn't account for a jukebox song referring to a registry entry and always assumed it was an inlined jukebox song

See https://github.com/GrimAnticheat/Grim/issues/1892
2024-12-18 20:44:44 +01:00
booky10 d46db268f8 Fix damage event packet wrapper not using network synchronized registries 2024-12-16 20:16:59 +01:00
retrooper 8f5b549b84 bump version up to 2.7.1 snapshot 2024-12-10 22:47:54 +01:00
retrooper 476c61ed47 bump version up to 2.7.0 release 2024-12-10 21:34:52 +01:00
retrooper 4b6bfbc08b Merge pull request #1085 from booky10/workaround/revert-shadow-color-support
Temporarily revert shadow color support
2024-12-10 20:52:44 +01:00
booky10 0be838c58f Temporarily revert shadow color support
Will be un-reverted when adventure v4.18.0 gets released
2024-12-10 20:32:19 +01:00
Axionize 770a9cd996 Fix CORAL_PLANTS blocktag and add new ALIVE_CORAL_PLANTS and DEAD_CORAL_PLANTS blocktags 2024-12-07 02:37:53 -05:00
Axionize 6afe377b55 Fix legacy mappings for shortgrass item returning tallgrass 2024-12-07 02:33:57 -05:00
Axionize fad73d2814 Fix legacy mappings for grass and tallgrass variants 2024-12-07 02:33:32 -05:00
booky10 d6c81f32cd Fix shadow color adventure support check 2024-12-04 18:03:46 +01:00
booky10 5d2104dd91 Merge pull request #1076 from mfnalex/feat/fix-npe-nbtinterpret
fix NPE for nbtInterpret
2024-12-04 18:00:55 +01:00
retrooper 969ce9d6a3 Merge pull request #1081 from Tecnio/2.0
bugfix: Added input validation for window click
2024-12-04 16:37:18 +01:00
Tecnio 55b456cb95 bugfix: Added input validation for window click 2024-12-04 18:34:40 +03:00
booky10 062ffc18f9 Merge pull request #1078 from AoElite/biomefix
fix npe if music tag isn't present on older versions
2024-12-04 12:32:42 +01:00
AoElite 95cbd40655 fix npe if music tag isn't present on older versions 2024-12-04 05:38:55 -05:00
retrooper 70d94137dd Merge pull request #1049 from booky10/feat/1.21.4-support
1.21.4 support
2024-12-03 22:50:55 +01:00
mfnalex bbea70d1db fix NPE for nbtInterpret 2024-12-03 20:23:31 +01:00
booky10 b5e5b752a4 Bump fabric version info 2024-12-03 18:42:39 +01:00
retrooper 28b4dd8e08 bump version up to 2.7.0 SNAPSHOT 2024-12-03 18:33:07 +01:00
retrooper 1ae92a8b9d correction to comments mistakenly referring to 1.21.5 2024-12-03 17:57:29 +01:00
booky10 00bbea33f6 Bump fabric minecraft version to 1.21.4-rc3 2024-12-02 23:10:59 +01:00
booky10 3fd3c397a6 Rename attribute constants to remove "type" prefix 2024-12-02 22:56:33 +01:00
booky10 f1f95a0aac Fix name of equipment asset mapping file reference 2024-12-02 22:20:25 +01:00
booky10 6e90a3e376 Update serverbound packet type mappings 2024-12-02 22:05:26 +01:00
booky10 41d51453a5 Update mappings for all changed registries 2024-12-02 22:01:06 +01:00
booky10andBeanes c74f8b2559 Add precision loss fix while writing, not while reading
This fixes *slightly* incorrect velocity values being provided in the wrapper, while still writing the correct short value

Co-authored-by: Beanes <sikyserver@gmail.com>
2024-12-02 21:45:35 +01:00
booky10 be2eb6a8ce Update generated block tags and item tags 2024-12-02 21:40:45 +01:00
Beanesandbooky10 9819db60cd Work around loss of precision when unpacking entity velocity
Solution was discussed on discord (https://discord.com/channels/721686193061888071/721686193515003966/1313231483225378946)

Closes #1074

Co-authored-by: booky10 <boooky10@gmail.com>
2024-12-02 21:26:55 +01:00
booky10 2a86e0d355 Update trim material structure to 1.21.4 2024-12-02 21:05:12 +01:00
booky10 4a209a342e Update biome music nbt structure to 1.21.4 2024-12-02 20:46:22 +01:00
booky10 33e5b58e3b Update custom model data component to 1.21.4 2024-12-02 20:21:21 +01:00
booky10 fd11bd24a9 Add new player loaded packet type and wrapper 2024-11-30 12:48:06 +01:00
booky10 8c1f14de57 Add wrappers for new pick item packets 2024-11-30 12:46:27 +01:00
booky10 bc615355c8 Add 1.21.4 serverbound packet type constants 2024-11-30 12:42:02 +01:00
booky10 28730806f9 Small javadoc notice for ParticleTrailData duration 2024-11-29 15:23:31 +01:00
booky10 4ec975fcd1 Update block state properties to 1.21.4 2024-11-29 15:20:55 +01:00
booky10 b6ce588e10 Add new item consumable use animation 2024-11-29 15:17:13 +01:00
booky10 a1510b5f6d Update equippable item component 2024-11-29 15:15:58 +01:00
booky10 913d527a64 Mark creaking transient entity type as obsolete 2024-11-29 15:13:51 +01:00
booky10 a1e250b521 Add new sound constants 2024-11-29 15:13:18 +01:00
booky10 887c107216 Add resin trim material constant 2024-11-29 15:12:15 +01:00
booky10 b6fb699a27 Add onground flag to WrapperPlayClientVehicleMove 2024-11-29 15:09:19 +01:00
booky10 575aa4619c Add initial support for shadow colors in component styles 2024-11-29 15:07:06 +01:00
booky10 3f787c0e35 Update particle types to 1.21.4 2024-11-29 14:41:37 +01:00
retrooper a0fc7f6978 Merge pull request #1065 from rafi67000/missingServerVersion
Add missing ServerVersion.V_1_9_1
2024-11-25 17:32:54 +01:00
rafi67000 2cd069ea72 Add missing ServerVersion.V_1_9_1 2024-11-24 22:13:00 +01:00
retrooper d4b4b24e3c WrapperPlayServerResourcePackSend#setPrompt added 2024-11-17 16:35:30 +01:00
retrooper dca7daec04 Merge pull request #1044 from ShreyasAyyengar/2.0
fix: NPC objects to have unique server team names.
2024-11-14 19:43:35 +01:00
booky10 b686eb467f Fix javadoc warnings 2024-11-13 15:16:01 +01:00
booky10 d1f0618c0e Merge branch '2.0' into feat/1.21.4-support 2024-11-13 14:28:59 +01:00
Shreyas Ayyengar ce06511b52 fix: initial team name not longer than 16 characters. 2024-11-11 14:41:56 -08:00
Shreyas Ayyengar a2b0c0f28e fix: truncate team name for versions older than V_1_18 2024-11-10 10:13:20 -08:00
ManInMyVan 0666097934 add faceid to WrapperPlayClientPlayerDigging 2024-11-08 16:52:35 -07:00
retrooper da71044fc4 rename BlockFace#getHorizontalId to adhere to naming convention 2024-11-08 14:47:41 +01:00
booky10 4167c949fe Merge pull request #1048 from Axionize/blockface-get-horizontal
add getHorizontalID
2024-11-07 16:02:57 +01:00
booky10 6f490a7e93 Merge pull request #1057 from booky10/fix/potion-contents-component
Fix potion contents item component for 1.21.2/1.21.3
2024-11-07 16:01:51 +01:00
booky10 b14dfc710a Fix potion contents item component for 1.21.2/1.21.3 2024-11-06 23:36:07 +01:00
You 1877bae091 add getHorizontalID 2024-11-04 22:27:29 -05:00
retrooper 4cf7069254 Bump version up to 2.6.1-SNAPSHOT 2024-11-03 21:31:26 +01:00
booky10 6e2da40aa5 Update block and item tags for 24w44a 2024-11-03 18:37:18 +01:00
booky10 dae7c2e90b Update item types for 24w44a 2024-11-03 18:37:11 +01:00
booky10 04db0ba88d Update state types for 24w44a 2024-11-03 18:37:06 +01:00
booky10 b348af9581 Update WrapperPlayServerHeldItemChange to 24w44a 2024-10-30 15:23:16 +01:00
booky10 aedb43b487 Update WrapperPlayServerPlayerInfoUpdate to 24w44a 2024-10-30 15:21:07 +01:00
booky10 3b86806d8e Update WrapperPlayServerParticle to 24w44a 2024-10-30 15:17:18 +01:00
booky10 c4cc09d8e0 Add 1.21.4 version constants 2024-10-30 15:14:51 +01:00
Shreyas Ayyengar 1a3b2471b3 refactor: add get/set for teamName 2024-10-28 11:19:55 -07:00
ShreyasAyyengar 3a004572c1 fix: NPC objects to have unique server team names. 2024-10-29 01:59:16 +08:00
651 changed files with 2573195 additions and 1945194 deletions

No files matched your search

+2 -2
View File
@@ -13,13 +13,13 @@ 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
with:
java-version: '21'
distribution: 'adopt'
distribution: 'temurin'
cache: 'gradle'
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
settings-path: ${{ github.workspace }} # location for the settings.xml file
+51
View File
@@ -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
+3
View File
@@ -123,3 +123,6 @@ run/
.project
.settings/
.classpath
# Build Source Kotlin
/buildSrc/.kotlin/
+263
View File
@@ -0,0 +1,263 @@
!!!!! 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
!!!!!
+4 -6
View File
@@ -1,7 +1,7 @@
<!--suppress HtmlDeprecatedAttribute -->
<div align="center">
<h2><i>packetevents</i></h2>
<h3><i>Precision meets performance—a powerful tool for mastering Minecraft packet manipulation with speed and finesse.</i></h3>
<h2><i>PacketEvents</i></h2>
<h3><i>A powerful networking library for Minecraft packet processing and manipulation.</i></h3>
<a href="https://github.com/retrooper/packetevents/actions"><img src="https://img.shields.io/github/actions/workflow/status/retrooper/packetevents/gradle-publish.yml?style=for-the-badge&logo=github"></a>
<a href="https://discord.gg/DVHxPPxHZc"><img src="https://img.shields.io/discord/721686193061888071?color=5562e9&logo=discord&logoColor=white&style=for-the-badge"></a>
<img src="https://img.shields.io/github/license/retrooper/packetevents?style=for-the-badge&logo=github">
@@ -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,14 +28,12 @@
<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>\
<i>small portions of their code into our work.</i>
[Protocol Documentation for the Minecraft Java Edition](https://wiki.vg/Protocol)\
[Protocol Documentation for the Minecraft Java Edition](https://minecraft.wiki/w/Minecraft_Wiki:Projects/wiki.vg_merge/Protocol)\
[ViaVersion](https://github.com/ViaVersion/ViaVersion)\
[ProtocolSupport](https://github.com/ProtocolSupport/ProtocolSupport)\
[adventure](https://github.com/KyoriPowered/adventure)\
+13 -66
View File
@@ -1,6 +1,6 @@
import com.github.retrooper.compression.strategy.JsonArrayCompressionStrategy
import com.github.retrooper.compression.strategy.JsonObjectCompressionStrategy
import com.github.retrooper.compression.strategy.JsonToNbtStrategy
import com.github.retrooper.compression.strategy.dir.JsonBase64DataDirStrategy
import com.github.retrooper.compression.strategy.dir.JsonRegistryCompressionDirStrategy
import com.github.retrooper.compression.strategy.dir.JsonToNbtDirStrategy
import com.github.retrooper.excludeAdventure
plugins {
@@ -39,76 +39,21 @@ dependencies {
testImplementation(testlibs.slf4j)
testImplementation(testlibs.bundles.junit)
testImplementation(libs.netty)
testImplementation(libs.classgraph)
}
mappingCompression {
mappingDirectory = rootDir.resolve("mappings")
outDirectory = project.layout.buildDirectory.dir("mappings/generated/assets/mappings")
with<JsonToNbtStrategy> {
compress("block/legacy_block_mappings.json")
compress("block/modern_block_mappings.json")
compress("enchantment/enchantment_type_data.json")
compress("item/item_base_components.json")
compress("stats/statistics.json")
compress("world/biome_data.json")
with<JsonToNbtDirStrategy> {
compress("data")
}
with<JsonArrayCompressionStrategy> {
compress("attribute/attribute_mappings.json")
compress("block/block_entity_type_mappings.json")
compress("block/block_type_mappings.json")
compress("chat/chat_type_mappings.json")
compress("command/argument_parser_mappings.json")
compress("damage/damagetype_mappings.json")
compress("enchantment/effect_component_type.json")
compress("entity/entity_data_type_mappings.json")
compress("entity/painting_mappings.json")
compress("entity/wolf_variant_mappings.json")
compress("item/consume_effect_type_mappings.json")
compress("item/item_armor_material_mappings.json")
compress("item/item_banner_pattern_mappings.json")
compress("item/item_component_mappings.json")
compress("item/item_instrument_mappings.json")
compress("item/item_jukebox_song_mappings.json")
compress("item/item_map_decoration_type_mappings.json")
compress("item/item_potion_mappings.json")
compress("item/item_trim_material_mappings.json")
compress("item/item_trim_pattern_mappings.json")
compress("item/recipe_book_category.json")
compress("item/recipe_display_types.json")
compress("item/recipe_serializer_mappings.json")
compress("item/recipe_slot_display_types.json")
compress("particle/particle_type_mappings.json")
compress("sound/sound_mappings.json")
compress("world/biome_mappings.json")
compress("world/world_position_source_mappings.json")
with<JsonBase64DataDirStrategy> {
compress("item_base_components")
}
with<JsonObjectCompressionStrategy> {
compress("enchantment/enchantment_type_mappings.json")
compress("entity/entity_effect_mappings.json")
compress("entity/entity_type_mappings.json")
compress("entity/legacy_entity_type_mappings.json")
compress("item/item_type_mappings.json")
compress("world/dimension_type_mappings.json")
with<JsonRegistryCompressionDirStrategy> {
compress("registries")
}
}
@@ -145,7 +90,9 @@ tasks {
shadowJar {
exclude {
val path = it.path
path.startsWith("net/kyori") && !path.startsWith("net/kyori/adventure/text/serializer") && !path.startsWith("net/kyori/option")
path.startsWith("net/kyori") && !path.startsWith("net/kyori/adventure/text/serializer") && !path.startsWith(
"net/kyori/option"
)
}
}
}
@@ -0,0 +1,28 @@
package com.github.retrooper.packetevents.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.Documented;
/**
* Marks an API element as obsolete and makes this information available
* at runtime via reflection. Use in conjunction with an IDE-recognized
* annotation like @ApiStatus.Obsolete if IDE warnings are also desired.
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD}) // Adjust targets as needed
public @interface RuntimeObsolete {
/**
* Specifies in which version the API became obsolete.
* Should generally match the value in the corresponding @ApiStatus.Obsolete annotation.
*/
String since() default "";
/**
* Optional: Add a reason or replacement suggestion.
*/
String reason() default "";
}
@@ -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,15 @@ 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.
*/
public ConnectionState getConnectionState() {
return connectionState;
}
@@ -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;
}
}
@@ -35,6 +35,8 @@ public interface ChannelInjector {
void setPlayer(Object channel, Object player);
boolean isPlayerSet(Object channel);
boolean isProxy();
default PacketSide getPacketSide() {
@@ -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() {
@@ -65,10 +67,12 @@ public class InternalPacketListener extends PacketListenerAbstract {
//Map username with channel
synchronized (channel) {
ProtocolManager.CHANNELS.put(profile.getUUID(), channel);
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());
}
@@ -19,10 +19,12 @@
package com.github.retrooper.packetevents.manager.player;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.event.ProtocolPacketEvent;
import com.github.retrooper.packetevents.protocol.ConnectionState;
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;
public interface PlayerManager {
@@ -34,7 +36,17 @@ public interface PlayerManager {
User getUser(@NotNull Object player);
default ConnectionState getConnectionState(@NotNull Object player) {
/**
* <strong>WARNING</strong>: Usage of this method should be avoided. Please use either
* {@link User#getDecoderState()} or {@link User#getEncoderState()}.<br>
* To access the specific state a packet event was sent/received in, use {@link ProtocolPacketEvent#getConnectionState()}.
* <p>
* Since 1.20.2, the Minecraft protocol allows the decoder/encoder connection states to de-sync.
*
* @throws IllegalStateException if encoder/decoder connection states do not match
*/
@ApiStatus.Obsolete
default ConnectionState getConnectionState(@NotNull Object player) throws IllegalStateException {
return getUser(player).getConnectionState();
}
@@ -33,8 +33,10 @@ import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
public interface ProtocolManager {
@ApiStatus.Internal
Map<UUID, Object> CHANNELS = new ConcurrentHashMap<>();
// Use SocketAddress because ProtocolLib wraps Channels with NettyChannelProxy class
@ApiStatus.Internal
Map<Object, User> USERS = new ConcurrentHashMap<>();
default Collection<User> getUsers() {
@@ -150,11 +152,13 @@ public interface ProtocolManager {
return USERS.get(pipeline);
}
@ApiStatus.Internal
default User removeUser(Object channel) {
Object pipeline = ChannelHelper.getPipeline(channel);
return USERS.remove(pipeline);
}
@ApiStatus.Internal
default void setUser(Object channel, User user) {
synchronized (channel) {
Object pipeline = ChannelHelper.getPipeline(channel);
@@ -166,4 +170,23 @@ public interface ProtocolManager {
default Object getChannel(UUID uuid) {
return CHANNELS.get(uuid);
}
@ApiStatus.Internal
default void setChannel(UUID uuid, Object channel) {
CHANNELS.put(uuid, channel);
}
@ApiStatus.Internal
default void removeChannel(Object channel) {
CHANNELS.values().remove(channel);
}
@ApiStatus.Internal
default void removeChannelById(UUID uuid) {
CHANNELS.remove(uuid);
}
default boolean hasChannel(Object channel) {
return CHANNELS.containsValue(channel);
}
}
@@ -32,9 +32,10 @@ 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_2(109), V_1_9_4(110),
V_1_9(107), V_1_9_1(108), V_1_9_2(109), V_1_9_4(110),
//1.10 and 1.10.1 are redundant
V_1_10(210), V_1_10_1(210), V_1_10_2(210),
V_1_11(315), V_1_11_2(316),
@@ -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(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);
@@ -31,4 +31,6 @@ public interface ByteBufAllocationOperator {
Object compositeBuffer();
Object compositeBuffer(int maxNumComponents);
Object emptyBuffer();
}
@@ -239,6 +239,19 @@ public class ByteBufHelper {
return PacketEvents.getAPI().getNettyManager().getByteBufOperator().resetWriterIndex(buffer);
}
public static Object allocateNewBuffer(Object buffer) {
return PacketEvents.getAPI().getNettyManager().getByteBufOperator().allocateNewBuffer(buffer);
}
public static int getByteSize(int value) {
for (int i = 1; i < 5; ++i) {
if ((value & -1 << i * 7) == 0) {
return i;
}
}
return 5;
}
public static int readVarInt(Object buffer) {
int value = 0;
int length = 0;
@@ -74,6 +74,8 @@ public interface ByteBufOperator {
Object markWriterIndex(Object buffer);
Object resetWriterIndex(Object buffer);
Object allocateNewBuffer(Object buffer);
default float readFloat(Object buffer) {
return Float.intBitsToFloat(readInt(buffer));
}
@@ -52,4 +52,8 @@ public class UnpooledByteBufAllocationHelper {
public static Object compositeBuffer(int maxNumComponents) {
return PacketEvents.getAPI().getNettyManager().getByteBufAllocationOperator().compositeBuffer(maxNumComponents);
}
public static Object emptyBuffer() {
return PacketEvents.getAPI().getNettyManager().getByteBufAllocationOperator().emptyBuffer();
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
}
@@ -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,
;
}
@@ -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();
}
@@ -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);
}
@@ -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();
}
}
@@ -26,8 +26,7 @@ import org.jetbrains.annotations.Nullable;
public final class Attributes {
private static final VersionedRegistry<Attribute> REGISTRY = new VersionedRegistry<>(
"attribute", "attribute/attribute_mappings");
private static final VersionedRegistry<Attribute> REGISTRY = new VersionedRegistry<>("attribute");
private Attributes() {
}
@@ -50,7 +49,7 @@ public final class Attributes {
if (normedName.startsWith(ResourceLocation.VANILLA_NAMESPACE + ":generic.")
|| normedName.startsWith(ResourceLocation.VANILLA_NAMESPACE + ":player.")
|| normedName.startsWith(ResourceLocation.VANILLA_NAMESPACE + ":zombie.")) {
normedName = normedName.substring(name.indexOf('.') + 1);
normedName = normedName.substring(normedName.indexOf('.') + 1);
}
return REGISTRY.getByName(normedName);
}
@@ -59,82 +58,314 @@ public final class Attributes {
return REGISTRY.getById(version, id);
}
public static final Attribute GENERIC_ARMOR = define("armor",
public static final Attribute ARMOR = define("armor",
"generic", 0d, 0d, 30d);
public static final Attribute GENERIC_ARMOR_TOUGHNESS = define("armor_toughness",
public static final Attribute ARMOR_TOUGHNESS = define("armor_toughness",
"generic", 0d, 0d, 20d);
public static final Attribute GENERIC_ATTACK_DAMAGE = define("attack_damage",
public static final Attribute ATTACK_DAMAGE = define("attack_damage",
"generic", 2d, 0d, 2048d);
public static final Attribute GENERIC_ATTACK_KNOCKBACK = define("attack_knockback",
public static final Attribute ATTACK_KNOCKBACK = define("attack_knockback",
"generic", 0d, 0d, 5d);
public static final Attribute GENERIC_ATTACK_SPEED = define("attack_speed",
public static final Attribute ATTACK_SPEED = define("attack_speed",
"generic", 4d, 0d, 1024d);
public static final Attribute GENERIC_FLYING_SPEED = define("flying_speed",
public static final Attribute FLYING_SPEED = define("flying_speed",
"generic", 0.4d, 0d, 1024d);
public static final Attribute GENERIC_FOLLOW_RANGE = define("follow_range",
public static final Attribute FOLLOW_RANGE = define("follow_range",
"generic", 32d, 0d, 2048d);
@ApiStatus.Obsolete // renamed in 1.20.5
public static final Attribute HORSE_JUMP_STRENGTH = define("horse.jump_strength",
null, 0.7d, 0d, 2d);
public static final Attribute GENERIC_KNOCKBACK_RESISTANCE = define("knockback_resistance",
public static final Attribute KNOCKBACK_RESISTANCE = define("knockback_resistance",
"generic", 0d, 0d, 1d);
public static final Attribute GENERIC_LUCK = define("luck",
public static final Attribute LUCK = define("luck",
"generic", 0d, -1024d, 1024d);
public static final Attribute GENERIC_MAX_HEALTH = define("max_health",
public static final Attribute MAX_HEALTH = define("max_health",
"generic", 20d, 1d, 1024d);
public static final Attribute GENERIC_MOVEMENT_SPEED = define("movement_speed",
public static final Attribute MOVEMENT_SPEED = define("movement_speed",
"generic", 0.7d, 0d, 1024d);
public static final Attribute ZOMBIE_SPAWN_REINFORCEMENTS = define("spawn_reinforcements",
public static final Attribute SPAWN_REINFORCEMENTS = define("spawn_reinforcements",
"zombie", 0d, 0d, 1d);
// Added in 1.20.2
public static final Attribute GENERIC_MAX_ABSORPTION = define("max_absorption",
/**
* Added with 1.20.2
*/
public static final Attribute MAX_ABSORPTION = define("max_absorption",
"generic", 0d, 0d, 2048d);
// Added in 1.20.5
public static final Attribute PLAYER_BLOCK_BREAK_SPEED = define("block_break_speed",
/**
* Added with 1.20.5
*/
public static final Attribute BLOCK_BREAK_SPEED = define("block_break_speed",
"player", 1d, 0d, 1024d);
public static final Attribute PLAYER_BLOCK_INTERACTION_RANGE = define("block_interaction_range",
/**
* Added with 1.20.5
*/
public static final Attribute BLOCK_INTERACTION_RANGE = define("block_interaction_range",
"player", 4.5d, 0d, 64d);
public static final Attribute PLAYER_ENTITY_INTERACTION_RANGE = define("entity_interaction_range",
/**
* Added with 1.20.5
*/
public static final Attribute ENTITY_INTERACTION_RANGE = define("entity_interaction_range",
"player", 3d, 0d, 64d);
public static final Attribute GENERIC_FALL_DAMAGE_MULTIPLIER = define("fall_damage_multiplier",
/**
* Added with 1.20.5
*/
public static final Attribute FALL_DAMAGE_MULTIPLIER = define("fall_damage_multiplier",
"generic", 1d, 0d, 100d);
public static final Attribute GENERIC_GRAVITY = define("gravity",
/**
* Added with 1.20.5
*/
public static final Attribute GRAVITY = define("gravity",
"generic", 0.08d, -1d, 1d);
public static final Attribute GENERIC_JUMP_STRENGTH = define("jump_strength",
/**
* Added with 1.20.5
*/
public static final Attribute JUMP_STRENGTH = define("jump_strength",
"generic", 0.42d, 0d, 32d);
public static final Attribute GENERIC_SAFE_FALL_DISTANCE = define("safe_fall_distance",
/**
* Added with 1.20.5
*/
public static final Attribute SAFE_FALL_DISTANCE = define("safe_fall_distance",
"generic", 3d, 0d, 1024d);
public static final Attribute GENERIC_SCALE = define("scale",
/**
* Added with 1.20.5
*/
public static final Attribute SCALE = define("scale",
"generic", 1d, 1d / 16d, 16d);
public static final Attribute GENERIC_STEP_HEIGHT = define("step_height",
/**
* Added with 1.20.5
*/
public static final Attribute STEP_HEIGHT = define("step_height",
"generic", 0.6d, 0d, 10d);
// Added in 1.21
public static final Attribute GENERIC_BURNING_TIME = define("burning_time",
/**
* Added with 1.21
*/
public static final Attribute BURNING_TIME = define("burning_time",
"generic", 0d, 1d, 1024d);
public static final Attribute GENERIC_EXPLOSION_KNOCKBACK_RESISTANCE = define("explosion_knockback_resistance",
/**
* Added with 1.21
*/
public static final Attribute EXPLOSION_KNOCKBACK_RESISTANCE = define("explosion_knockback_resistance",
"generic", 0d, 0d, 1d);
public static final Attribute PLAYER_MINING_EFFICIENCY = define("mining_efficiency",
/**
* Added with 1.21
*/
public static final Attribute MINING_EFFICIENCY = define("mining_efficiency",
"player", 0d, 0d, 1024d);
public static final Attribute GENERIC_MOVEMENT_EFFICIENCY = define("movement_efficiency",
/**
* Added with 1.21
*/
public static final Attribute MOVEMENT_EFFICIENCY = define("movement_efficiency",
"generic", 0d, 0d, 1d);
public static final Attribute GENERIC_OXYGEN_BONUS = define("oxygen_bonus",
/**
* Added with 1.21
*/
public static final Attribute OXYGEN_BONUS = define("oxygen_bonus",
"generic", 0d, 0d, 1024d);
public static final Attribute PLAYER_SNEAKING_SPEED = define("sneaking_speed",
/**
* Added with 1.21
*/
public static final Attribute SNEAKING_SPEED = define("sneaking_speed",
"player", 0.3d, 0d, 1d);
public static final Attribute PLAYER_SUBMERGED_MINING_SPEED = define("submerged_mining_speed",
/**
* Added with 1.21
*/
public static final Attribute SUBMERGED_MINING_SPEED = define("submerged_mining_speed",
"player", 0.2d, 0d, 20d);
public static final Attribute PLAYER_SWEEPING_DAMAGE_RATIO = define("sweeping_damage_ratio",
/**
* Added with 1.21
*/
public static final Attribute SWEEPING_DAMAGE_RATIO = define("sweeping_damage_ratio",
"player", 0d, 0d, 1d);
public static final Attribute GENERIC_WATER_MOVEMENT_EFFICIENCY = define("water_movement_efficiency",
/**
* Added with 1.21
*/
public static final Attribute WATER_MOVEMENT_EFFICIENCY = define("water_movement_efficiency",
"generic", 0d, 0d, 1d);
// added with 1.21.2
/**
* Added with 1.21.2
*/
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}
*/
@ApiStatus.Obsolete
public static final Attribute HORSE_JUMP_STRENGTH = define("horse.jump_strength",
null, 0.7d, 0d, 2d);
/**
* All attribute "type" prefixes were removed with 1.21.2
*/
@Deprecated
public static final Attribute GENERIC_ARMOR = ARMOR;
/**
* All attribute "type" prefixes were removed with 1.21.2
*/
@Deprecated
public static final Attribute GENERIC_ARMOR_TOUGHNESS = ARMOR_TOUGHNESS;
/**
* All attribute "type" prefixes were removed with 1.21.2
*/
@Deprecated
public static final Attribute GENERIC_ATTACK_DAMAGE = ATTACK_DAMAGE;
/**
* All attribute "type" prefixes were removed with 1.21.2
*/
@Deprecated
public static final Attribute GENERIC_ATTACK_KNOCKBACK = ATTACK_KNOCKBACK;
/**
* All attribute "type" prefixes were removed with 1.21.2
*/
@Deprecated
public static final Attribute GENERIC_ATTACK_SPEED = ATTACK_SPEED;
/**
* All attribute "type" prefixes were removed with 1.21.2
*/
@Deprecated
public static final Attribute GENERIC_FLYING_SPEED = FLYING_SPEED;
/**
* All attribute "type" prefixes were removed with 1.21.2
*/
@Deprecated
public static final Attribute GENERIC_FOLLOW_RANGE = FOLLOW_RANGE;
/**
* All attribute "type" prefixes were removed with 1.21.2
*/
@Deprecated
public static final Attribute GENERIC_KNOCKBACK_RESISTANCE = KNOCKBACK_RESISTANCE;
/**
* All attribute "type" prefixes were removed with 1.21.2
*/
@Deprecated
public static final Attribute GENERIC_LUCK = LUCK;
/**
* All attribute "type" prefixes were removed with 1.21.2
*/
@Deprecated
public static final Attribute GENERIC_MAX_HEALTH = MAX_HEALTH;
/**
* All attribute "type" prefixes were removed with 1.21.2
*/
@Deprecated
public static final Attribute GENERIC_MOVEMENT_SPEED = MOVEMENT_SPEED;
/**
* All attribute "type" prefixes were removed with 1.21.2
*/
@Deprecated
public static final Attribute ZOMBIE_SPAWN_REINFORCEMENTS = SPAWN_REINFORCEMENTS;
/**
* All attribute "type" prefixes were removed with 1.21.2
*/
@Deprecated
public static final Attribute GENERIC_MAX_ABSORPTION = MAX_ABSORPTION;
/**
* All attribute "type" prefixes were removed with 1.21.2
*/
@Deprecated
public static final Attribute PLAYER_BLOCK_BREAK_SPEED = BLOCK_BREAK_SPEED;
/**
* All attribute "type" prefixes were removed with 1.21.2
*/
@Deprecated
public static final Attribute PLAYER_BLOCK_INTERACTION_RANGE = BLOCK_INTERACTION_RANGE;
/**
* All attribute "type" prefixes were removed with 1.21.2
*/
@Deprecated
public static final Attribute PLAYER_ENTITY_INTERACTION_RANGE = ENTITY_INTERACTION_RANGE;
/**
* All attribute "type" prefixes were removed with 1.21.2
*/
@Deprecated
public static final Attribute GENERIC_FALL_DAMAGE_MULTIPLIER = FALL_DAMAGE_MULTIPLIER;
/**
* All attribute "type" prefixes were removed with 1.21.2
*/
@Deprecated
public static final Attribute GENERIC_GRAVITY = GRAVITY;
/**
* All attribute "type" prefixes were removed with 1.21.2
*/
@Deprecated
public static final Attribute GENERIC_JUMP_STRENGTH = JUMP_STRENGTH;
/**
* All attribute "type" prefixes were removed with 1.21.2
*/
@Deprecated
public static final Attribute GENERIC_SAFE_FALL_DISTANCE = SAFE_FALL_DISTANCE;
/**
* All attribute "type" prefixes were removed with 1.21.2
*/
@Deprecated
public static final Attribute GENERIC_SCALE = SCALE;
/**
* All attribute "type" prefixes were removed with 1.21.2
*/
@Deprecated
public static final Attribute GENERIC_STEP_HEIGHT = STEP_HEIGHT;
/**
* All attribute "type" prefixes were removed with 1.21.2
*/
@Deprecated
public static final Attribute GENERIC_BURNING_TIME = BURNING_TIME;
/**
* All attribute "type" prefixes were removed with 1.21.2
*/
@Deprecated
public static final Attribute GENERIC_EXPLOSION_KNOCKBACK_RESISTANCE = EXPLOSION_KNOCKBACK_RESISTANCE;
/**
* All attribute "type" prefixes were removed with 1.21.2
*/
@Deprecated
public static final Attribute PLAYER_MINING_EFFICIENCY = MINING_EFFICIENCY;
/**
* All attribute "type" prefixes were removed with 1.21.2
*/
@Deprecated
public static final Attribute GENERIC_MOVEMENT_EFFICIENCY = MOVEMENT_EFFICIENCY;
/**
* All attribute "type" prefixes were removed with 1.21.2
*/
@Deprecated
public static final Attribute GENERIC_OXYGEN_BONUS = OXYGEN_BONUS;
/**
* All attribute "type" prefixes were removed with 1.21.2
*/
@Deprecated
public static final Attribute PLAYER_SNEAKING_SPEED = SNEAKING_SPEED;
/**
* All attribute "type" prefixes were removed with 1.21.2
*/
@Deprecated
public static final Attribute PLAYER_SUBMERGED_MINING_SPEED = SUBMERGED_MINING_SPEED;
/**
* All attribute "type" prefixes were removed with 1.21.2
*/
@Deprecated
public static final Attribute PLAYER_SWEEPING_DAMAGE_RATIO = SWEEPING_DAMAGE_RATIO;
/**
* All attribute "type" prefixes were removed with 1.21.2
*/
@Deprecated
public static final Attribute GENERIC_WATER_MOVEMENT_EFFICIENCY = WATER_MOVEMENT_EFFICIENCY;
static {
REGISTRY.unloadMappings();
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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);
}
}
@@ -22,6 +22,7 @@ import com.github.retrooper.packetevents.protocol.mapper.AbstractMappedEntity;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.resources.ResourceLocation;
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
public class StaticAttribute extends AbstractMappedEntity implements Attribute {
@@ -31,21 +32,24 @@ public class StaticAttribute extends AbstractMappedEntity implements Attribute {
private final double minValue;
private final double maxValue;
StaticAttribute(
TypesBuilderData data, String legacyPrefix,
@ApiStatus.Internal
public StaticAttribute(
@Nullable TypesBuilderData data, String legacyPrefix,
double defaultValue, double minValue, double maxValue
) {
super(data);
this.defaultValue = defaultValue;
this.minValue = minValue;
this.maxValue = maxValue;
this.legacyName = legacyPrefix == null ? null : new ResourceLocation(
this.legacyName = legacyPrefix == null || data == null ? null : new ResourceLocation(
data.getName().getNamespace(), legacyPrefix + "." + data.getName().getKey());
}
@Override
public ResourceLocation getName(ClientVersion version) {
assert this.data != null; // not marked as nullable in ctor
if (this.data == null) {
throw new UnsupportedOperationException();
}
return version.isNewerThanOrEquals(ClientVersion.V_1_21_2) || this.legacyName == null
? this.data.getName() : this.legacyName;
}
@@ -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);
}
}
@@ -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.getNBTSerializer().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.getNBTSerializer()
.serializeStyle(decoration.style));
compound.setTag("style", wrapper.getSerializers()
.nbt().serializeStyle(decoration.style, wrapper));
}
return compound;
}
@@ -31,8 +31,7 @@ import static com.github.retrooper.packetevents.protocol.chat.ChatTypeDecoration
public final class ChatTypes {
private static final VersionedRegistry<ChatType> REGISTRY = new VersionedRegistry<>(
"chat_type", "chat/chat_type_mappings");
private static final VersionedRegistry<ChatType> REGISTRY = new VersionedRegistry<>("chat_type");
private ChatTypes() {
}
@@ -1,5 +1,6 @@
package com.github.retrooper.packetevents.protocol.chat;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
import java.io.DataOutput;
@@ -86,12 +87,23 @@ public class LastSeenMessages {
}
public static class Update {
private final int offset;
private final BitSet acknowledged;
private final byte checksum;
/**
* Checksum has been added with 1.21.5
*/
@ApiStatus.Obsolete
public Update(int offset, BitSet acknowledged) {
this(offset, acknowledged, (byte) 0);
}
public Update(int offset, BitSet acknowledged, byte checksum) {
this.offset = offset;
this.acknowledged = acknowledged;
this.checksum = checksum;
}
public int getOffset() {
@@ -101,5 +113,12 @@ public class LastSeenMessages {
public BitSet getAcknowledged() {
return acknowledged;
}
/**
* Added with 1.21.5
*/
public byte getChecksum() {
return this.checksum;
}
}
}
@@ -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;
@@ -19,58 +19,56 @@
package com.github.retrooper.packetevents.protocol.chat;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.mapper.MappedEntity;
import com.github.retrooper.packetevents.protocol.mapper.AbstractMappedEntity;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.resources.ResourceLocation;
import com.github.retrooper.packetevents.util.mappings.MappingHelper;
import com.github.retrooper.packetevents.util.mappings.TypesBuilder;
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
import com.github.retrooper.packetevents.util.mappings.VersionedRegistry;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import org.jetbrains.annotations.ApiStatus;
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.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.Function;
public class Parsers {
@NullMarked
public final class Parsers {
private static final List<Parser> ALL_PARSERS = new ArrayList<>(); // support for old methods
private static final Map<String, Parser> PARSER_MAP = new HashMap<>();
private static final Map<Byte, Map<Integer, Parser>> PARSER_ID_MAP = new HashMap<>();
private static final TypesBuilder TYPES_BUILDER = new TypesBuilder("command/argument_parser_mappings");
private static final VersionedRegistry<Parser> REGISTRY = new VersionedRegistry<>("command_argument_type");
private Parsers() {
}
@ApiStatus.Internal
public static Parser define(String key) {
return define(key, null, null);
}
@ApiStatus.Internal
public static Parser define(String key, @Nullable Reader reader, @Nullable Writer writer) {
TypesBuilderData data = TYPES_BUILDER.define(key);
Parser parser = new Parser(data, reader, writer);
ALL_PARSERS.add(parser);
MappingHelper.registerMapping(TYPES_BUILDER, PARSER_MAP, PARSER_ID_MAP, parser);
return parser;
return REGISTRY.define(key, data -> new Parser(data, reader, writer));
}
// with key
public static Parser getByName(String name) {
return PARSER_MAP.get(name);
return REGISTRY.getByName(name);
}
public static Parser getById(ClientVersion version, int id) {
int index = TYPES_BUILDER.getDataIndex(version);
Map<Integer, Parser> idMap = PARSER_ID_MAP.get((byte) index);
return idMap.get(id);
return REGISTRY.getById(version, id);
}
public static List<Parser> getParsers() {
return Collections.unmodifiableList(ALL_PARSERS);
return new ArrayList<>(REGISTRY.getEntries());
}
public static VersionedRegistry<Parser> getRegistry() {
return REGISTRY;
}
public static final Parser BRIGADIER_BOOL = define("brigadier:bool", null, null);
@@ -152,8 +150,8 @@ public class Parsers {
public static final Parser STYLE = define("style", null, null);
public static final Parser MESSAGE = define("message", null, null);
public static final Parser NBT_COMPOUND_TAG = define("nbt_compound_tag", null, null);
@Deprecated
public static final Parser NBT = NBT_COMPOUND_TAG;
@ApiStatus.Obsolete
public static final Parser NBT = define("nbt", null, null);
public static final Parser NBT_TAG = define("nbt_tag", null, null);
public static final Parser NBT_PATH = define("nbt_path", null, null);
public static final Parser OBJECTIVE = define("objective", null, null);
@@ -214,8 +212,25 @@ public class Parsers {
public static final Parser LOOT_MODIFIER = define("loot_modifier", null, null);
public static final Parser UUID = define("uuid", null, null);
/**
* Added with 1.21.5
*/
public static final Parser RESOURCE_SELECTOR = define("resource_selector",
wrapper -> Collections.singletonList(wrapper.readIdentifier()),
(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 {
TYPES_BUILDER.unloadFileMappings();
REGISTRY.unloadMappings();
}
@FunctionalInterface
@@ -224,9 +239,8 @@ public class Parsers {
@FunctionalInterface
public interface Writer extends BiConsumer<PacketWrapper<?>, List<Object>> {}
public static final class Parser implements MappedEntity {
public static final class Parser extends AbstractMappedEntity {
private final TypesBuilderData data;
private final Reader reader;
private final Writer writer;
@@ -239,8 +253,9 @@ public class Parsers {
);
}
private Parser(TypesBuilderData data, @Nullable Reader reader, Writer writer) {
this.data = data;
@ApiStatus.Internal
public Parser(@Nullable TypesBuilderData data, @Nullable Reader reader, @Nullable Writer writer) {
super(data);
this.reader = reader;
this.writer = writer;
}
@@ -257,24 +272,5 @@ public class Parsers {
this.writer.accept(wrapper, properties);
}
}
@Override
public ResourceLocation getName() {
return this.data.getName();
}
@Override
public int getId(ClientVersion version) {
int index = TYPES_BUILDER.getDataIndex(version);
return this.data.getData()[index];
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Parser) {
return this.getName().equals(((Parser) obj).getName());
}
return false;
}
}
}
@@ -20,6 +20,7 @@ package com.github.retrooper.packetevents.protocol.chat;
import com.github.retrooper.packetevents.protocol.mapper.AbstractMappedEntity;
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.UnknownNullability;
@@ -39,6 +40,7 @@ public class StaticChatType extends AbstractMappedEntity implements ChatType {
this(null, chatDecoration, null, narrationDecoration, null);
}
@ApiStatus.Internal
public StaticChatType(
@Nullable TypesBuilderData data,
ChatTypeDecoration chatDecoration,
@@ -56,6 +58,7 @@ public class StaticChatType extends AbstractMappedEntity implements ChatType {
this(null, chatDecoration, overlayDecoration, narrationDecoration, narrationPriority);
}
@ApiStatus.Internal
public StaticChatType(
@Nullable TypesBuilderData data,
@UnknownNullability("only nullable for 1.19") ChatTypeDecoration chatDecoration,
@@ -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;
}
}
@@ -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();
}
@@ -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);
}
@@ -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();
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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();
}
}
@@ -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);
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
@@ -10,7 +10,6 @@ import org.jetbrains.annotations.Nullable;
import java.time.Instant;
import java.util.Optional;
import java.util.UUID;
//We'll extend ChatMessage_v1_16 for now, hopefully no breaking changes in the future
public class ChatMessage_v1_19_3 extends ChatMessage_v1_16 {
int index;
byte[] signature;
@@ -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.chat.message;
import com.github.retrooper.packetevents.protocol.chat.ChatType;
import com.github.retrooper.packetevents.protocol.chat.LastSeenMessages;
import com.github.retrooper.packetevents.protocol.chat.filter.FilterMask;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.Nullable;
import java.time.Instant;
import java.util.UUID;
//We'll extend ChatMessage_v1_19_3 for now, hopefully no breaking changes in the future
public class ChatMessage_v1_21_5 extends ChatMessage_v1_19_3 {
int globalIndex;
public ChatMessage_v1_21_5(int globalIndex, UUID senderUUID, int index, byte[] signature, String plainContent,
Instant timestamp, long salt, LastSeenMessages.Packed lastSeenMessagesPacked, @Nullable Component unsignedChatContent,
FilterMask filterMask, ChatType.Bound chatFormatting) {
super(senderUUID, index, signature, plainContent, timestamp, salt, lastSeenMessagesPacked, unsignedChatContent, filterMask, chatFormatting);
this.globalIndex = globalIndex;
}
public int getGlobalIndex() {
return this.globalIndex;
}
public void setGlobalIndex(int globalIndex) {
this.globalIndex = globalIndex;
}
}
@@ -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.message.reader.impl;
import com.github.retrooper.packetevents.protocol.chat.ChatType;
import com.github.retrooper.packetevents.protocol.chat.LastSeenMessages;
import com.github.retrooper.packetevents.protocol.chat.filter.FilterMask;
import com.github.retrooper.packetevents.protocol.chat.message.ChatMessage;
import com.github.retrooper.packetevents.protocol.chat.message.ChatMessage_v1_21_5;
import com.github.retrooper.packetevents.protocol.chat.message.reader.ChatMessageProcessor;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.NotNull;
import java.time.Instant;
import java.util.UUID;
public class ChatMessageProcessor_v1_21_5 implements ChatMessageProcessor {
@Override
public ChatMessage readChatMessage(@NotNull PacketWrapper<?> wrapper) {
int globalIndex = wrapper.readVarInt();
UUID senderUUID = wrapper.readUUID();
int index = wrapper.readVarInt();
byte[] signature = wrapper.readOptional((w) -> w.readBytes(256));
String plainContent = wrapper.readString(256);
Instant timestamp = wrapper.readTimestamp();
long salt = wrapper.readLong();
LastSeenMessages.Packed lastSeenMessagesPacked = wrapper.readLastSeenMessagesPacked();
Component unsignedChatContent = wrapper.readOptional(PacketWrapper::readComponent);
FilterMask filterMask = wrapper.readFilterMask();
ChatType.Bound chatType = wrapper.readChatTypeBoundNetwork();
return new ChatMessage_v1_21_5(globalIndex, senderUUID, index, signature, plainContent, timestamp, salt, lastSeenMessagesPacked, unsignedChatContent, filterMask, chatType);
}
@Override
public void writeChatMessage(@NotNull PacketWrapper<?> wrapper, @NotNull ChatMessage data) {
ChatMessage_v1_21_5 newData = (ChatMessage_v1_21_5) data;
wrapper.writeVarInt(newData.getGlobalIndex());
wrapper.writeUUID(newData.getSenderUUID());
wrapper.writeVarInt(newData.getIndex());
wrapper.writeOptional(newData.getSignature(), PacketWrapper::writeBytes);
wrapper.writeString(newData.getPlainContent());
wrapper.writeTimestamp(newData.getTimestamp());
wrapper.writeLong(newData.getSalt());
wrapper.writeLastSeenMessagesPacked(newData.getLastSeenMessagesPacked());
wrapper.writeOptional(newData.getUnsignedChatContent().orElse(null), PacketWrapper::writeComponent);
wrapper.writeFilterMask(newData.getFilterMask());
wrapper.writeChatTypeBoundNetwork(newData.getChatFormatting());
}
}
@@ -26,6 +26,7 @@ import com.github.retrooper.packetevents.protocol.nbt.NBTNumber;
import com.github.retrooper.packetevents.protocol.nbt.NBTType;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.util.MathUtil;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import net.kyori.adventure.util.RGBLike;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Range;
@@ -56,6 +57,24 @@ public class Color implements RGBLike {
this((rgb >> 16) & BIT_MASK, (rgb >> 8) & BIT_MASK, rgb & BIT_MASK);
}
public static Color read(PacketWrapper<?> wrapper) {
return new Color(wrapper.readInt());
}
public static void write(PacketWrapper<?> wrapper, Color color) {
wrapper.writeInt(color.asRGB());
}
public static Color 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());
@@ -18,6 +18,7 @@
package com.github.retrooper.packetevents.protocol.color;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import net.kyori.adventure.util.RGBLike;
import org.jetbrains.annotations.NotNull;
@@ -54,6 +55,8 @@ public enum DyeColor implements RGBLike {
BLACK(new Color(0x1d1d21), new Color(0x0), new Color(0x1e1b1b), 29);
private static final DyeColor[] COLORS = values();
private final Color textureDiffuseColor;
private final Color textColor;
@@ -70,6 +73,14 @@ public enum DyeColor implements RGBLike {
this.mapColorId = mapColorId;
}
public static DyeColor read(PacketWrapper<?> wrapper) {
return wrapper.readEnum(COLORS);
}
public static void write(PacketWrapper<?> wrapper, DyeColor color) {
wrapper.writeEnum(color);
}
public @NotNull Color color() {
return this.textureDiffuseColor;
}
@@ -100,4 +111,4 @@ public enum DyeColor implements RGBLike {
public int mapColorId() {
return this.mapColorId;
}
}
}
@@ -31,6 +31,10 @@ public class ComponentPredicate implements Predicate<IComponentMap> {
private List<ComponentValue<?>> requiredComponents;
public ComponentPredicate() {
this(new ArrayList<>());
}
public ComponentPredicate(List<ComponentValue<?>> requiredComponents) {
this.requiredComponents = requiredComponents;
}
@@ -22,6 +22,9 @@ import com.github.retrooper.packetevents.protocol.mapper.MappedEntity;
import com.github.retrooper.packetevents.protocol.nbt.NBT;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import org.jetbrains.annotations.ApiStatus;
import java.util.function.Function;
public interface ComponentType<T> extends MappedEntity {
@@ -33,6 +36,9 @@ public interface ComponentType<T> extends MappedEntity {
NBT encode(T value, ClientVersion version);
@ApiStatus.Internal
<Z> ComponentType<Z> legacyMap(Function<T, Z> mapper, Function<Z, T> unmapper);
interface Decoder<T> {
T decode(NBT nbt, ClientVersion version);
@@ -19,6 +19,30 @@
package com.github.retrooper.packetevents.protocol.component;
import com.github.retrooper.packetevents.protocol.color.DyeColor;
import com.github.retrooper.packetevents.protocol.component.builtin.AxolotlVariantComponent;
import com.github.retrooper.packetevents.protocol.component.builtin.CatCollarComponent;
import com.github.retrooper.packetevents.protocol.component.builtin.CatVariantComponent;
import com.github.retrooper.packetevents.protocol.component.builtin.ChickenVariantComponent;
import com.github.retrooper.packetevents.protocol.component.builtin.CowVariantComponent;
import com.github.retrooper.packetevents.protocol.component.builtin.FoxVariantComponent;
import com.github.retrooper.packetevents.protocol.component.builtin.FrogVariantComponent;
import com.github.retrooper.packetevents.protocol.component.builtin.HorseVariantComponent;
import com.github.retrooper.packetevents.protocol.component.builtin.LlamaVariantComponent;
import com.github.retrooper.packetevents.protocol.component.builtin.MooshroomVariantComponent;
import com.github.retrooper.packetevents.protocol.component.builtin.PaintingVariantComponent;
import com.github.retrooper.packetevents.protocol.component.builtin.ParrotVariantComponent;
import com.github.retrooper.packetevents.protocol.component.builtin.PigVariantComponent;
import com.github.retrooper.packetevents.protocol.component.builtin.RabbitVariantComponent;
import com.github.retrooper.packetevents.protocol.component.builtin.SalmonSizeComponent;
import com.github.retrooper.packetevents.protocol.component.builtin.SheepColorComponent;
import com.github.retrooper.packetevents.protocol.component.builtin.ShulkerColorComponent;
import com.github.retrooper.packetevents.protocol.component.builtin.TropicalFishBaseColorComponent;
import com.github.retrooper.packetevents.protocol.component.builtin.TropicalFishPatternColorComponent;
import com.github.retrooper.packetevents.protocol.component.builtin.TropicalFishPatternComponent;
import com.github.retrooper.packetevents.protocol.component.builtin.VillagerVariantComponent;
import com.github.retrooper.packetevents.protocol.component.builtin.WolfCollarComponent;
import com.github.retrooper.packetevents.protocol.component.builtin.WolfSoundVariantComponent;
import com.github.retrooper.packetevents.protocol.component.builtin.WolfVariantComponent;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ArmorTrim;
import com.github.retrooper.packetevents.protocol.component.builtin.item.BannerLayers;
import com.github.retrooper.packetevents.protocol.component.builtin.item.BundleContents;
@@ -31,9 +55,12 @@ import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemAdv
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemAttributeModifiers;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemBees;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemBlockStateProperties;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemBlocksAttacks;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemBreakSound;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemConsumable;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemContainerContents;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemContainerLoot;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemCustomModelData;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemDamageResistant;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemDeathProtection;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemDyeColor;
@@ -41,6 +68,7 @@ import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemEnc
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemEnchantments;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemEquippable;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemFireworks;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemInstrument;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemJukeboxPlayable;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemLock;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemLore;
@@ -48,20 +76,27 @@ import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemMap
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemMapPostProcessingState;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemModel;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemPotionContents;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemPotionDurationScale;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemProfile;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemProvidesBannerPatterns;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemProvidesTrimMaterial;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemRarity;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemRecipes;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemRepairable;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemTool;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemTooltipDisplay;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemTooltipStyle;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemUnbreakable;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemUseCooldown;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemUseRemainder;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemWeapon;
import com.github.retrooper.packetevents.protocol.component.builtin.item.LodestoneTracker;
import com.github.retrooper.packetevents.protocol.component.builtin.item.PotDecorations;
import com.github.retrooper.packetevents.protocol.component.builtin.item.SuspiciousStewEffects;
import com.github.retrooper.packetevents.protocol.component.builtin.item.WritableBookContent;
import com.github.retrooper.packetevents.protocol.component.builtin.item.WrittenBookContent;
import com.github.retrooper.packetevents.protocol.item.instrument.Instrument;
import com.github.retrooper.packetevents.protocol.mapper.MaybeMappedEntity;
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.resources.ResourceLocation;
@@ -83,8 +118,7 @@ import java.util.Collection;
*/
public final class ComponentTypes {
private static final VersionedRegistry<ComponentType<?>> REGISTRY = new VersionedRegistry<>(
"data_component_type", "item/item_component_mappings");
private static final VersionedRegistry<ComponentType<?>> REGISTRY = new VersionedRegistry<>("data_component_type");
private ComponentTypes() {
}
@@ -121,8 +155,14 @@ public final class ComponentTypes {
PacketWrapper::readVarInt, PacketWrapper::writeVarInt);
public static final ComponentType<Integer> DAMAGE = define("damage",
PacketWrapper::readVarInt, PacketWrapper::writeVarInt);
public static final ComponentType<Boolean> UNBREAKABLE = define("unbreakable",
PacketWrapper::readBoolean, PacketWrapper::writeBoolean);
public static final ComponentType<ItemUnbreakable> UNBREAKABLE_MODERN = define("unbreakable",
ItemUnbreakable::read, ItemUnbreakable::write);
/**
* Changed in 1.21.5
*/
@Deprecated
public static final ComponentType<Boolean> UNBREAKABLE = UNBREAKABLE_MODERN.legacyMap(
ItemUnbreakable::isShowInTooltip, ItemUnbreakable::new);
public static final ComponentType<Component> CUSTOM_NAME = define("custom_name",
PacketWrapper::readComponent, PacketWrapper::writeComponent);
public static final ComponentType<Component> ITEM_NAME = define("item_name",
@@ -139,10 +179,24 @@ public final class ComponentTypes {
ItemAdventurePredicate::read, ItemAdventurePredicate::write);
public static final ComponentType<ItemAttributeModifiers> ATTRIBUTE_MODIFIERS = define("attribute_modifiers",
ItemAttributeModifiers::read, ItemAttributeModifiers::write);
public static final ComponentType<Integer> CUSTOM_MODEL_DATA = define("custom_model_data",
PacketWrapper::readVarInt, PacketWrapper::writeVarInt);
public static final ComponentType<ItemCustomModelData> CUSTOM_MODEL_DATA_LISTS = define("custom_model_data",
ItemCustomModelData::read, ItemCustomModelData::write);
/**
* Rewritten in 1.21.4
*/
@Deprecated
public static final ComponentType<Integer> CUSTOM_MODEL_DATA = CUSTOM_MODEL_DATA_LISTS.legacyMap(
ItemCustomModelData::getLegacyId, ItemCustomModelData::new);
/**
* Removed with 1.21.5
*/
@ApiStatus.Obsolete
public static final ComponentType<Dummy> HIDE_ADDITIONAL_TOOLTIP = define("hide_additional_tooltip",
Dummy::dummyRead, Dummy::dummyWrite);
/**
* Removed with 1.21.5
*/
@ApiStatus.Obsolete
public static final ComponentType<Dummy> HIDE_TOOLTIP = define("hide_tooltip",
Dummy::dummyRead, Dummy::dummyWrite);
public static final ComponentType<Integer> REPAIR_COST = define("repair_cost",
@@ -197,8 +251,12 @@ public final class ComponentTypes {
PacketWrapper::readNBT, PacketWrapper::writeNBT);
public static final ComponentType<NBTCompound> BLOCK_ENTITY_DATA = define("block_entity_data",
PacketWrapper::readNBT, PacketWrapper::writeNBT);
public static final ComponentType<Instrument> INSTRUMENT = define("instrument",
Instrument::read, Instrument::write);
public static final ComponentType<ItemInstrument> ITEM_INSTRUMENT = define("instrument",
ItemInstrument::read, ItemInstrument::write);
@Deprecated
public static final ComponentType<Instrument> INSTRUMENT = ITEM_INSTRUMENT.legacyMap(
inst -> inst.getInstrument().getValue(),
inst -> new ItemInstrument(new MaybeMappedEntity<>(inst)));
public static final ComponentType<Integer> OMINOUS_BOTTLE_AMPLIFIER = define("ominous_bottle_amplifier",
PacketWrapper::readVarInt, PacketWrapper::writeVarInt);
public static final ComponentType<ItemRecipes> RECIPES = define("recipes",
@@ -258,6 +316,162 @@ public final class ComponentTypes {
public static final ComponentType<ItemTooltipStyle> TOOLTIP_STYLE = define("tooltip_style",
ItemTooltipStyle::read, ItemTooltipStyle::write);
/**
* Added with 1.21.5
*/
public static final ComponentType<ItemTooltipDisplay> TOOLTIP_DISPLAY = define("tooltip_display",
ItemTooltipDisplay::read, ItemTooltipDisplay::write);
/**
* Added with 1.21.5
*/
public static final ComponentType<ItemWeapon> WEAPON = define("weapon",
ItemWeapon::read, ItemWeapon::write);
/**
* Added with 1.21.5
*/
public static final ComponentType<ItemBlocksAttacks> BLOCKS_ATTACKS = define("blocks_attacks",
ItemBlocksAttacks::read, ItemBlocksAttacks::write);
/**
* Added with 1.21.5
*/
public static final ComponentType<ItemPotionDurationScale> POTION_DURATION_SCALE = define("potion_duration_scale",
ItemPotionDurationScale::read, ItemPotionDurationScale::write);
/**
* Added with 1.21.5
*/
public static final ComponentType<ItemProvidesTrimMaterial> PROVIDES_TRIM_MATERIAL = define("provides_trim_material",
ItemProvidesTrimMaterial::read, ItemProvidesTrimMaterial::write);
/**
* Added with 1.21.5
*/
public static final ComponentType<ItemProvidesBannerPatterns> PROVIDES_BANNER_PATTERNS = define("provides_banner_patterns",
ItemProvidesBannerPatterns::read, ItemProvidesBannerPatterns::write);
/**
* Added with 1.21.5
*/
public static final ComponentType<ItemBreakSound> BREAK_SOUND = define("break_sound",
ItemBreakSound::read, ItemBreakSound::write);
/**
* Added with 1.21.5
*/
public static final ComponentType<VillagerVariantComponent> VILLAGER_VARIANT = define("villager/variant",
VillagerVariantComponent::read, VillagerVariantComponent::write);
/**
* Added with 1.21.5
*/
public static final ComponentType<WolfVariantComponent> WOLF_VARIANT = define("wolf/variant",
WolfVariantComponent::read, WolfVariantComponent::write);
/**
* Added with 1.21.5
*/
public static final ComponentType<WolfSoundVariantComponent> WOLF_SOUND_VARIANT = define("wolf/sound_variant",
WolfSoundVariantComponent::read, WolfSoundVariantComponent::write);
/**
* Added with 1.21.5
*/
public static final ComponentType<WolfCollarComponent> WOLF_COLLAR = define("wolf/collar",
WolfCollarComponent::read, WolfCollarComponent::write);
/**
* Added with 1.21.5
*/
public static final ComponentType<FoxVariantComponent> FOX_VARIANT = define("fox/variant",
FoxVariantComponent::read, FoxVariantComponent::write);
/**
* Added with 1.21.5
*/
public static final ComponentType<SalmonSizeComponent> SALMON_SIZE = define("salmon/size",
SalmonSizeComponent::read, SalmonSizeComponent::write);
/**
* Added with 1.21.5
*/
public static final ComponentType<ParrotVariantComponent> PARROT_VARIANT = define("parrot/variant",
ParrotVariantComponent::read, ParrotVariantComponent::write);
/**
* Added with 1.21.5
*/
public static final ComponentType<TropicalFishPatternComponent> TROPICAL_FISH_PATTERN = define("tropical_fish/pattern",
TropicalFishPatternComponent::read, TropicalFishPatternComponent::write);
/**
* Added with 1.21.5
*/
public static final ComponentType<TropicalFishBaseColorComponent> TROPICAL_FISH_BASE_COLOR = define("tropical_fish/base_color",
TropicalFishBaseColorComponent::read, TropicalFishBaseColorComponent::write);
/**
* Added with 1.21.5
*/
public static final ComponentType<TropicalFishPatternColorComponent> TROPICAL_FISH_PATTERN_COLOR = define("tropical_fish/pattern_color",
TropicalFishPatternColorComponent::read, TropicalFishPatternColorComponent::write);
/**
* Added with 1.21.5
*/
public static final ComponentType<MooshroomVariantComponent> MOOSHROOM_VARIANT = define("mooshroom/variant",
MooshroomVariantComponent::read, MooshroomVariantComponent::write);
/**
* Added with 1.21.5
*/
public static final ComponentType<RabbitVariantComponent> RABBIT_VARIANT = define("rabbit/variant",
RabbitVariantComponent::read, RabbitVariantComponent::write);
/**
* Added with 1.21.5
*/
public static final ComponentType<PigVariantComponent> PIG_VARIANT = define("pig/variant",
PigVariantComponent::read, PigVariantComponent::write);
/**
* Added with 1.21.5
*/
public static final ComponentType<CowVariantComponent> COW_VARIANT = define("cow/variant",
CowVariantComponent::read, CowVariantComponent::write);
/**
* Added with 1.21.5
*/
public static final ComponentType<ChickenVariantComponent> CHICKEN_VARIANT = define("chicken/variant",
ChickenVariantComponent::read, ChickenVariantComponent::write);
/**
* Added with 1.21.5
*/
public static final ComponentType<FrogVariantComponent> FROG_VARIANT = define("frog/variant",
FrogVariantComponent::read, FrogVariantComponent::write);
/**
* Added with 1.21.5
*/
public static final ComponentType<HorseVariantComponent> HORSE_VARIANT = define("horse/variant",
HorseVariantComponent::read, HorseVariantComponent::write);
/**
* Added with 1.21.5
*/
public static final ComponentType<PaintingVariantComponent> PAINTING_VARIANT = define("painting/variant",
PaintingVariantComponent::read, PaintingVariantComponent::write);
/**
* Added with 1.21.5
*/
public static final ComponentType<LlamaVariantComponent> LLAMA_VARIANT = define("llama/variant",
LlamaVariantComponent::read, LlamaVariantComponent::write);
/**
* Added with 1.21.5
*/
public static final ComponentType<AxolotlVariantComponent> AXOLOTL_VARIANT = define("axolotl/variant",
AxolotlVariantComponent::read, AxolotlVariantComponent::write);
/**
* Added with 1.21.5
*/
public static final ComponentType<CatVariantComponent> CAT_VARIANT = define("cat/variant",
CatVariantComponent::read, CatVariantComponent::write);
/**
* Added with 1.21.5
*/
public static final ComponentType<CatCollarComponent> CAT_COLLAR = define("cat/collar",
CatCollarComponent::read, CatCollarComponent::write);
/**
* Added with 1.21.5
*/
public static final ComponentType<SheepColorComponent> SHEEP_COLOR = define("sheep/color",
SheepColorComponent::read, SheepColorComponent::write);
/**
* Added with 1.21.5
*/
public static final ComponentType<ShulkerColorComponent> SHULKER_COLOR = define("shulker/color",
ShulkerColorComponent::read, ShulkerColorComponent::write);
/**
* Returns an immutable view of the component types.
*
@@ -32,8 +32,7 @@ import org.jetbrains.annotations.Nullable;
*/
public final class EnchantEffectComponentTypes {
private static final VersionedRegistry<ComponentType<?>> REGISTRY = new VersionedRegistry<>(
"enchantment_effect_component_type", "enchantment/effect_component_type");
private static final VersionedRegistry<ComponentType<?>> REGISTRY = new VersionedRegistry<>("enchantment_effect_component_type");
private EnchantEffectComponentTypes() {
}
@@ -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.component;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public final class HashedComponentPatchMap {
private final Map<ComponentType<?>, Integer> addedComponents;
private final Set<ComponentType<?>> removedComponents;
public HashedComponentPatchMap(Map<ComponentType<?>, Integer> addedComponents, Set<ComponentType<?>> removedComponents) {
this.addedComponents = addedComponents;
this.removedComponents = removedComponents;
}
public static HashedComponentPatchMap read(PacketWrapper<?> wrapper) {
Map<ComponentType<?>, Integer> addedComponents = wrapper.readMap(ew ->
ew.readMappedEntity(ComponentTypes.getRegistry()), PacketWrapper::readInt);
Set<ComponentType<?>> removedComponents = wrapper.readCollection(HashSet::new, ew ->
ew.readMappedEntity(ComponentTypes.getRegistry()));
return new HashedComponentPatchMap(addedComponents, removedComponents);
}
public static void write(PacketWrapper<?> wrapper, HashedComponentPatchMap map) {
wrapper.writeMap(map.addedComponents, PacketWrapper::writeMappedEntity, PacketWrapper::writeInt);
wrapper.writeCollection(map.removedComponents, PacketWrapper::writeMappedEntity);
}
public Map<ComponentType<?>, Integer> getAddedComponents() {
return this.addedComponents;
}
public Set<ComponentType<?>> getRemovedComponents() {
return this.removedComponents;
}
}
@@ -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();
@@ -25,8 +25,11 @@ 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 java.util.function.Function;
public class StaticComponentType<T> extends AbstractMappedEntity implements ComponentType<T> {
private final @Nullable Reader<T> reader;
@@ -34,6 +37,7 @@ public class StaticComponentType<T> extends AbstractMappedEntity implements Comp
private final @Nullable Decoder<T> decoder;
private final @Nullable Encoder<T> encoder;
@ApiStatus.Internal
public StaticComponentType(
@Nullable TypesBuilderData data,
@Nullable Reader<T> reader,
@@ -42,6 +46,7 @@ public class StaticComponentType<T> extends AbstractMappedEntity implements Comp
this(data, reader, writer, null, null);
}
@ApiStatus.Internal
public StaticComponentType(
@Nullable TypesBuilderData data,
@Nullable Decoder<T> decoder,
@@ -50,6 +55,7 @@ public class StaticComponentType<T> extends AbstractMappedEntity implements Comp
this(data, null, null, decoder, encoder);
}
@ApiStatus.Internal
public StaticComponentType(
@Nullable TypesBuilderData data,
@Nullable Reader<T> reader,
@@ -91,4 +97,13 @@ public class StaticComponentType<T> extends AbstractMappedEntity implements Comp
}
throw new UnsupportedOperationException();
}
@Override
public <Z> ComponentType<Z> legacyMap(Function<T, Z> mapper, Function<Z, T> unmapper) {
Reader<Z> reader = this.reader != null ? wrapper -> mapper.apply(this.reader.apply(wrapper)) : null;
Writer<Z> writer = this.writer != null ? (wrapper, value) -> this.writer.accept(wrapper, unmapper.apply(value)) : null;
Decoder<Z> decoder = this.decoder != null ? (nbt, version) -> mapper.apply(this.decoder.decode(nbt, version)) : null;
Encoder<Z> encoder = this.encoder != null ? (value, version) -> this.encoder.encode(unmapper.apply(value), version) : null;
return new StaticComponentType<>(this.data, reader, writer, decoder, encoder);
}
}
@@ -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.component.builtin;
import com.github.retrooper.packetevents.protocol.entity.axolotl.AxolotlVariant;
import com.github.retrooper.packetevents.protocol.entity.axolotl.AxolotlVariants;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.Objects;
public class AxolotlVariantComponent {
private AxolotlVariant variant;
public AxolotlVariantComponent(AxolotlVariant variant) {
this.variant = variant;
}
public static AxolotlVariantComponent read(PacketWrapper<?> wrapper) {
AxolotlVariant type = wrapper.readMappedEntity(AxolotlVariants.getRegistry());
return new AxolotlVariantComponent(type);
}
public static void write(PacketWrapper<?> wrapper, AxolotlVariantComponent component) {
wrapper.writeMappedEntity(component.variant);
}
public AxolotlVariant getVariant() {
return this.variant;
}
public void setVariant(AxolotlVariant variant) {
this.variant = variant;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof AxolotlVariantComponent)) return false;
AxolotlVariantComponent that = (AxolotlVariantComponent) obj;
return this.variant.equals(that.variant);
}
@Override
public int hashCode() {
return Objects.hashCode(this.variant);
}
}
@@ -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.component.builtin;
import com.github.retrooper.packetevents.protocol.color.DyeColor;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.Objects;
public class CatCollarComponent {
private DyeColor color;
public CatCollarComponent(DyeColor color) {
this.color = color;
}
public static CatCollarComponent read(PacketWrapper<?> wrapper) {
DyeColor type = DyeColor.read(wrapper);
return new CatCollarComponent(type);
}
public static void write(PacketWrapper<?> wrapper, CatCollarComponent component) {
DyeColor.write(wrapper, component.color);
}
public DyeColor getDyeColor() {
return this.color;
}
public void setDyeColor(DyeColor color) {
this.color = color;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof CatCollarComponent)) return false;
CatCollarComponent that = (CatCollarComponent) obj;
return this.color.equals(that.color);
}
@Override
public int hashCode() {
return Objects.hashCode(this.color);
}
}
@@ -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.component.builtin;
import com.github.retrooper.packetevents.protocol.entity.cat.CatVariant;
import com.github.retrooper.packetevents.protocol.entity.cat.CatVariants;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.Objects;
public class CatVariantComponent {
private CatVariant variant;
public CatVariantComponent(CatVariant variant) {
this.variant = variant;
}
public static CatVariantComponent read(PacketWrapper<?> wrapper) {
CatVariant type = wrapper.readMappedEntity(CatVariants.getRegistry());
return new CatVariantComponent(type);
}
public static void write(PacketWrapper<?> wrapper, CatVariantComponent component) {
wrapper.writeMappedEntity(component.variant);
}
public CatVariant getVariant() {
return this.variant;
}
public void setVariant(CatVariant variant) {
this.variant = variant;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof CatVariantComponent)) return false;
CatVariantComponent that = (CatVariantComponent) obj;
return this.variant.equals(that.variant);
}
@Override
public int hashCode() {
return Objects.hashCode(this.variant);
}
}
@@ -0,0 +1,65 @@
/*
* 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.component.builtin;
import com.github.retrooper.packetevents.protocol.entity.chicken.ChickenVariant;
import com.github.retrooper.packetevents.protocol.entity.chicken.ChickenVariants;
import com.github.retrooper.packetevents.protocol.mapper.MaybeMappedEntity;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.Objects;
public class ChickenVariantComponent {
private MaybeMappedEntity<ChickenVariant> variant;
public ChickenVariantComponent(MaybeMappedEntity<ChickenVariant> variant) {
this.variant = variant;
}
public static ChickenVariantComponent read(PacketWrapper<?> wrapper) {
MaybeMappedEntity<ChickenVariant> variant = MaybeMappedEntity.read(wrapper,
ChickenVariants.getRegistry(), ChickenVariant::read);
return new ChickenVariantComponent(variant);
}
public static void write(PacketWrapper<?> wrapper, ChickenVariantComponent component) {
MaybeMappedEntity.write(wrapper, component.variant, ChickenVariant::write);
}
public MaybeMappedEntity<ChickenVariant> getVariant() {
return this.variant;
}
public void setVariant(MaybeMappedEntity<ChickenVariant> variant) {
this.variant = variant;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof ChickenVariantComponent)) return false;
ChickenVariantComponent that = (ChickenVariantComponent) obj;
return this.variant.equals(that.variant);
}
@Override
public int hashCode() {
return Objects.hashCode(this.variant);
}
}
@@ -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.component.builtin;
import com.github.retrooper.packetevents.protocol.entity.cow.CowVariant;
import com.github.retrooper.packetevents.protocol.entity.cow.CowVariants;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.Objects;
public class CowVariantComponent {
private CowVariant variant;
public CowVariantComponent(CowVariant variant) {
this.variant = variant;
}
public static CowVariantComponent read(PacketWrapper<?> wrapper) {
CowVariant type = wrapper.readMappedEntity(CowVariants.getRegistry());
return new CowVariantComponent(type);
}
public static void write(PacketWrapper<?> wrapper, CowVariantComponent component) {
wrapper.writeMappedEntity(component.variant);
}
public CowVariant getVariant() {
return this.variant;
}
public void setVariant(CowVariant variant) {
this.variant = variant;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof CowVariantComponent)) return false;
CowVariantComponent that = (CowVariantComponent) obj;
return this.variant.equals(that.variant);
}
@Override
public int hashCode() {
return Objects.hashCode(this.variant);
}
}
@@ -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.component.builtin;
import com.github.retrooper.packetevents.protocol.entity.fox.FoxVariant;
import com.github.retrooper.packetevents.protocol.entity.fox.FoxVariants;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.Objects;
public class FoxVariantComponent {
private FoxVariant variant;
public FoxVariantComponent(FoxVariant variant) {
this.variant = variant;
}
public static FoxVariantComponent read(PacketWrapper<?> wrapper) {
FoxVariant type = wrapper.readMappedEntity(FoxVariants.getRegistry());
return new FoxVariantComponent(type);
}
public static void write(PacketWrapper<?> wrapper, FoxVariantComponent component) {
wrapper.writeMappedEntity(component.variant);
}
public FoxVariant getVariant() {
return this.variant;
}
public void setVariant(FoxVariant variant) {
this.variant = variant;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof FoxVariantComponent)) return false;
FoxVariantComponent that = (FoxVariantComponent) obj;
return this.variant.equals(that.variant);
}
@Override
public int hashCode() {
return Objects.hashCode(this.variant);
}
}
@@ -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.component.builtin;
import com.github.retrooper.packetevents.protocol.entity.frog.FrogVariant;
import com.github.retrooper.packetevents.protocol.entity.frog.FrogVariants;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.Objects;
public class FrogVariantComponent {
private FrogVariant variant;
public FrogVariantComponent(FrogVariant variant) {
this.variant = variant;
}
public static FrogVariantComponent read(PacketWrapper<?> wrapper) {
FrogVariant variant = wrapper.readMappedEntity(FrogVariants.getRegistry());
return new FrogVariantComponent(variant);
}
public static void write(PacketWrapper<?> wrapper, FrogVariantComponent component) {
wrapper.writeMappedEntity(component.variant);
}
public FrogVariant getVariant() {
return this.variant;
}
public void setVariant(FrogVariant variant) {
this.variant = variant;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof FrogVariantComponent)) return false;
FrogVariantComponent that = (FrogVariantComponent) obj;
return this.variant.equals(that.variant);
}
@Override
public int hashCode() {
return Objects.hashCode(this.variant);
}
}
@@ -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.component.builtin;
import com.github.retrooper.packetevents.protocol.entity.horse.HorseVariant;
import com.github.retrooper.packetevents.protocol.entity.horse.HorseVariants;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.Objects;
public class HorseVariantComponent {
private HorseVariant variant;
public HorseVariantComponent(HorseVariant variant) {
this.variant = variant;
}
public static HorseVariantComponent read(PacketWrapper<?> wrapper) {
HorseVariant variant = wrapper.readMappedEntity(HorseVariants.getRegistry());
return new HorseVariantComponent(variant);
}
public static void write(PacketWrapper<?> wrapper, HorseVariantComponent component) {
wrapper.writeMappedEntity(component.variant);
}
public HorseVariant getVariant() {
return this.variant;
}
public void setVariant(HorseVariant variant) {
this.variant = variant;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof HorseVariantComponent)) return false;
HorseVariantComponent that = (HorseVariantComponent) obj;
return this.variant.equals(that.variant);
}
@Override
public int hashCode() {
return Objects.hashCode(this.variant);
}
}
@@ -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.component.builtin;
import com.github.retrooper.packetevents.protocol.entity.llama.LlamaVariant;
import com.github.retrooper.packetevents.protocol.entity.llama.LlamaVariants;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.Objects;
public class LlamaVariantComponent {
private LlamaVariant variant;
public LlamaVariantComponent(LlamaVariant variant) {
this.variant = variant;
}
public static LlamaVariantComponent read(PacketWrapper<?> wrapper) {
LlamaVariant type = wrapper.readMappedEntity(LlamaVariants.getRegistry());
return new LlamaVariantComponent(type);
}
public static void write(PacketWrapper<?> wrapper, LlamaVariantComponent component) {
wrapper.writeMappedEntity(component.variant);
}
public LlamaVariant getVariant() {
return this.variant;
}
public void setVariant(LlamaVariant variant) {
this.variant = variant;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof LlamaVariantComponent)) return false;
LlamaVariantComponent that = (LlamaVariantComponent) obj;
return this.variant.equals(that.variant);
}
@Override
public int hashCode() {
return Objects.hashCode(this.variant);
}
}
@@ -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.component.builtin;
import com.github.retrooper.packetevents.protocol.entity.mooshroom.MooshroomVariant;
import com.github.retrooper.packetevents.protocol.entity.mooshroom.MooshroomVariants;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.Objects;
public class MooshroomVariantComponent {
private MooshroomVariant variant;
public MooshroomVariantComponent(MooshroomVariant variant) {
this.variant = variant;
}
public static MooshroomVariantComponent read(PacketWrapper<?> wrapper) {
MooshroomVariant type = wrapper.readMappedEntity(MooshroomVariants.getRegistry());
return new MooshroomVariantComponent(type);
}
public static void write(PacketWrapper<?> wrapper, MooshroomVariantComponent component) {
wrapper.writeMappedEntity(component.variant);
}
public MooshroomVariant getVariant() {
return this.variant;
}
public void setVariant(MooshroomVariant variant) {
this.variant = variant;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof MooshroomVariantComponent)) return false;
MooshroomVariantComponent that = (MooshroomVariantComponent) obj;
return this.variant.equals(that.variant);
}
@Override
public int hashCode() {
return Objects.hashCode(this.variant);
}
}
@@ -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.component.builtin;
import com.github.retrooper.packetevents.protocol.world.painting.PaintingVariant;
import com.github.retrooper.packetevents.protocol.world.painting.PaintingVariants;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.Objects;
public class PaintingVariantComponent {
private PaintingVariant variant;
public PaintingVariantComponent(PaintingVariant variant) {
this.variant = variant;
}
public static PaintingVariantComponent read(PacketWrapper<?> wrapper) {
PaintingVariant variant = wrapper.readMappedEntity(PaintingVariants.getRegistry());
return new PaintingVariantComponent(variant);
}
public static void write(PacketWrapper<?> wrapper, PaintingVariantComponent component) {
wrapper.writeMappedEntity(component.variant);
}
public PaintingVariant getVariant() {
return this.variant;
}
public void setVariant(PaintingVariant variant) {
this.variant = variant;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof PaintingVariantComponent)) return false;
PaintingVariantComponent that = (PaintingVariantComponent) obj;
return this.variant.equals(that.variant);
}
@Override
public int hashCode() {
return Objects.hashCode(this.variant);
}
}
@@ -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.component.builtin;
import com.github.retrooper.packetevents.protocol.entity.parrot.ParrotVariant;
import com.github.retrooper.packetevents.protocol.entity.parrot.ParrotVariants;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.Objects;
public class ParrotVariantComponent {
private ParrotVariant variant;
public ParrotVariantComponent(ParrotVariant variant) {
this.variant = variant;
}
public static ParrotVariantComponent read(PacketWrapper<?> wrapper) {
ParrotVariant type = wrapper.readMappedEntity(ParrotVariants.getRegistry());
return new ParrotVariantComponent(type);
}
public static void write(PacketWrapper<?> wrapper, ParrotVariantComponent component) {
wrapper.writeMappedEntity(component.variant);
}
public ParrotVariant getVariant() {
return this.variant;
}
public void setVariant(ParrotVariant variant) {
this.variant = variant;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof ParrotVariantComponent)) return false;
ParrotVariantComponent that = (ParrotVariantComponent) obj;
return this.variant.equals(that.variant);
}
@Override
public int hashCode() {
return Objects.hashCode(this.variant);
}
}
@@ -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.component.builtin;
import com.github.retrooper.packetevents.protocol.entity.pig.PigVariant;
import com.github.retrooper.packetevents.protocol.entity.pig.PigVariants;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.Objects;
public class PigVariantComponent {
private PigVariant variant;
public PigVariantComponent(PigVariant variant) {
this.variant = variant;
}
public static PigVariantComponent read(PacketWrapper<?> wrapper) {
PigVariant type = wrapper.readMappedEntity(PigVariants.getRegistry());
return new PigVariantComponent(type);
}
public static void write(PacketWrapper<?> wrapper, PigVariantComponent component) {
wrapper.writeMappedEntity(component.variant);
}
public PigVariant getVariant() {
return this.variant;
}
public void setVariant(PigVariant variant) {
this.variant = variant;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof PigVariantComponent)) return false;
PigVariantComponent that = (PigVariantComponent) obj;
return this.variant.equals(that.variant);
}
@Override
public int hashCode() {
return Objects.hashCode(this.variant);
}
}
@@ -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.component.builtin;
import com.github.retrooper.packetevents.protocol.entity.rabbit.RabbitVariant;
import com.github.retrooper.packetevents.protocol.entity.rabbit.RabbitVariants;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.Objects;
public class RabbitVariantComponent {
private RabbitVariant variant;
public RabbitVariantComponent(RabbitVariant variant) {
this.variant = variant;
}
public static RabbitVariantComponent read(PacketWrapper<?> wrapper) {
RabbitVariant type = wrapper.readMappedEntity(RabbitVariants.getRegistry());
return new RabbitVariantComponent(type);
}
public static void write(PacketWrapper<?> wrapper, RabbitVariantComponent component) {
wrapper.writeMappedEntity(component.variant);
}
public RabbitVariant getVariant() {
return this.variant;
}
public void setVariant(RabbitVariant variant) {
this.variant = variant;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof RabbitVariantComponent)) return false;
RabbitVariantComponent that = (RabbitVariantComponent) obj;
return this.variant.equals(that.variant);
}
@Override
public int hashCode() {
return Objects.hashCode(this.variant);
}
}
@@ -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.component.builtin;
import com.github.retrooper.packetevents.protocol.entity.salmon.SalmonVariant;
import com.github.retrooper.packetevents.protocol.entity.salmon.SalmonVariants;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.Objects;
public class SalmonSizeComponent {
private SalmonVariant variant;
public SalmonSizeComponent(SalmonVariant variant) {
this.variant = variant;
}
public static SalmonSizeComponent read(PacketWrapper<?> wrapper) {
SalmonVariant type = wrapper.readMappedEntity(SalmonVariants.getRegistry());
return new SalmonSizeComponent(type);
}
public static void write(PacketWrapper<?> wrapper, SalmonSizeComponent component) {
wrapper.writeMappedEntity(component.variant);
}
public SalmonVariant getVariant() {
return this.variant;
}
public void setVariant(SalmonVariant variant) {
this.variant = variant;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof SalmonSizeComponent)) return false;
SalmonSizeComponent that = (SalmonSizeComponent) obj;
return this.variant.equals(that.variant);
}
@Override
public int hashCode() {
return Objects.hashCode(this.variant);
}
}
@@ -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.component.builtin;
import com.github.retrooper.packetevents.protocol.color.DyeColor;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.Objects;
public class SheepColorComponent {
private DyeColor color;
public SheepColorComponent(DyeColor color) {
this.color = color;
}
public static SheepColorComponent read(PacketWrapper<?> wrapper) {
DyeColor type = DyeColor.read(wrapper);
return new SheepColorComponent(type);
}
public static void write(PacketWrapper<?> wrapper, SheepColorComponent component) {
DyeColor.write(wrapper, component.color);
}
public DyeColor getDyeColor() {
return this.color;
}
public void setDyeColor(DyeColor color) {
this.color = color;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof SheepColorComponent)) return false;
SheepColorComponent that = (SheepColorComponent) obj;
return this.color.equals(that.color);
}
@Override
public int hashCode() {
return Objects.hashCode(this.color);
}
}
@@ -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.component.builtin;
import com.github.retrooper.packetevents.protocol.color.DyeColor;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.Objects;
public class ShulkerColorComponent {
private DyeColor color;
public ShulkerColorComponent(DyeColor color) {
this.color = color;
}
public static ShulkerColorComponent read(PacketWrapper<?> wrapper) {
DyeColor type = DyeColor.read(wrapper);
return new ShulkerColorComponent(type);
}
public static void write(PacketWrapper<?> wrapper, ShulkerColorComponent component) {
DyeColor.write(wrapper, component.color);
}
public DyeColor getDyeColor() {
return this.color;
}
public void setDyeColor(DyeColor color) {
this.color = color;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof ShulkerColorComponent)) return false;
ShulkerColorComponent that = (ShulkerColorComponent) obj;
return this.color.equals(that.color);
}
@Override
public int hashCode() {
return Objects.hashCode(this.color);
}
}
@@ -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.component.builtin;
import com.github.retrooper.packetevents.protocol.color.DyeColor;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.Objects;
public class TropicalFishBaseColorComponent {
private DyeColor color;
public TropicalFishBaseColorComponent(DyeColor color) {
this.color = color;
}
public static TropicalFishBaseColorComponent read(PacketWrapper<?> wrapper) {
DyeColor type = DyeColor.read(wrapper);
return new TropicalFishBaseColorComponent(type);
}
public static void write(PacketWrapper<?> wrapper, TropicalFishBaseColorComponent component) {
DyeColor.write(wrapper, component.color);
}
public DyeColor getDyeColor() {
return this.color;
}
public void setDyeColor(DyeColor color) {
this.color = color;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof TropicalFishBaseColorComponent)) return false;
TropicalFishBaseColorComponent that = (TropicalFishBaseColorComponent) obj;
return this.color.equals(that.color);
}
@Override
public int hashCode() {
return Objects.hashCode(this.color);
}
}
@@ -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.component.builtin;
import com.github.retrooper.packetevents.protocol.color.DyeColor;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.Objects;
public class TropicalFishPatternColorComponent {
private DyeColor color;
public TropicalFishPatternColorComponent(DyeColor color) {
this.color = color;
}
public static TropicalFishPatternColorComponent read(PacketWrapper<?> wrapper) {
DyeColor type = DyeColor.read(wrapper);
return new TropicalFishPatternColorComponent(type);
}
public static void write(PacketWrapper<?> wrapper, TropicalFishPatternColorComponent component) {
DyeColor.write(wrapper, component.color);
}
public DyeColor getDyeColor() {
return this.color;
}
public void setDyeColor(DyeColor color) {
this.color = color;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof TropicalFishPatternColorComponent)) return false;
TropicalFishPatternColorComponent that = (TropicalFishPatternColorComponent) obj;
return this.color.equals(that.color);
}
@Override
public int hashCode() {
return Objects.hashCode(this.color);
}
}
@@ -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.component.builtin;
import com.github.retrooper.packetevents.protocol.entity.tropicalfish.TropicalFishPattern;
import com.github.retrooper.packetevents.protocol.entity.tropicalfish.TropicalFishPatterns;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.Objects;
public class TropicalFishPatternComponent {
private TropicalFishPattern variant;
public TropicalFishPatternComponent(TropicalFishPattern variant) {
this.variant = variant;
}
public static TropicalFishPatternComponent read(PacketWrapper<?> wrapper) {
TropicalFishPattern type = wrapper.readMappedEntity(TropicalFishPatterns.getRegistry());
return new TropicalFishPatternComponent(type);
}
public static void write(PacketWrapper<?> wrapper, TropicalFishPatternComponent component) {
wrapper.writeMappedEntity(component.variant);
}
public TropicalFishPattern getVariant() {
return this.variant;
}
public void setVariant(TropicalFishPattern variant) {
this.variant = variant;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof TropicalFishPatternComponent)) return false;
TropicalFishPatternComponent that = (TropicalFishPatternComponent) obj;
return this.variant.equals(that.variant);
}
@Override
public int hashCode() {
return Objects.hashCode(this.variant);
}
}
@@ -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.component.builtin;
import com.github.retrooper.packetevents.protocol.entity.villager.type.VillagerType;
import com.github.retrooper.packetevents.protocol.entity.villager.type.VillagerTypes;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.Objects;
public class VillagerVariantComponent {
private VillagerType villagerType;
public VillagerVariantComponent(VillagerType villagerType) {
this.villagerType = villagerType;
}
public static VillagerVariantComponent read(PacketWrapper<?> wrapper) {
VillagerType type = wrapper.readMappedEntity(VillagerTypes.getRegistry());
return new VillagerVariantComponent(type);
}
public static void write(PacketWrapper<?> wrapper, VillagerVariantComponent component) {
wrapper.writeMappedEntity(component.villagerType);
}
public VillagerType getVillagerType() {
return this.villagerType;
}
public void setVillagerType(VillagerType villagerType) {
this.villagerType = villagerType;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof VillagerVariantComponent)) return false;
VillagerVariantComponent that = (VillagerVariantComponent) obj;
return this.villagerType.equals(that.villagerType);
}
@Override
public int hashCode() {
return Objects.hashCode(this.villagerType);
}
}
@@ -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.component.builtin;
import com.github.retrooper.packetevents.protocol.color.DyeColor;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.Objects;
public class WolfCollarComponent {
private DyeColor color;
public WolfCollarComponent(DyeColor color) {
this.color = color;
}
public static WolfCollarComponent read(PacketWrapper<?> wrapper) {
DyeColor type = DyeColor.read(wrapper);
return new WolfCollarComponent(type);
}
public static void write(PacketWrapper<?> wrapper, WolfCollarComponent component) {
DyeColor.write(wrapper, component.color);
}
public DyeColor getDyeColor() {
return this.color;
}
public void setDyeColor(DyeColor color) {
this.color = color;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof WolfCollarComponent)) return false;
WolfCollarComponent that = (WolfCollarComponent) obj;
return this.color.equals(that.color);
}
@Override
public int hashCode() {
return Objects.hashCode(this.color);
}
}
@@ -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.component.builtin;
import com.github.retrooper.packetevents.protocol.entity.wolfvariant.WolfSoundVariant;
import com.github.retrooper.packetevents.protocol.entity.wolfvariant.WolfSoundVariants;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.Objects;
public class WolfSoundVariantComponent {
private WolfSoundVariant soundVariant;
public WolfSoundVariantComponent(WolfSoundVariant soundVariant) {
this.soundVariant = soundVariant;
}
public static WolfSoundVariantComponent read(PacketWrapper<?> wrapper) {
WolfSoundVariant type = wrapper.readMappedEntity(WolfSoundVariants.getRegistry());
return new WolfSoundVariantComponent(type);
}
public static void write(PacketWrapper<?> wrapper, WolfSoundVariantComponent component) {
wrapper.writeMappedEntity(component.soundVariant);
}
public WolfSoundVariant getSoundVariant() {
return this.soundVariant;
}
public void setSoundVariant(WolfSoundVariant soundVariant) {
this.soundVariant = soundVariant;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof WolfSoundVariantComponent)) return false;
WolfSoundVariantComponent that = (WolfSoundVariantComponent) obj;
return this.soundVariant.equals(that.soundVariant);
}
@Override
public int hashCode() {
return Objects.hashCode(this.soundVariant);
}
}
@@ -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.component.builtin;
import com.github.retrooper.packetevents.protocol.entity.wolfvariant.WolfVariant;
import com.github.retrooper.packetevents.protocol.entity.wolfvariant.WolfVariants;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.Objects;
public class WolfVariantComponent {
private WolfVariant variant;
public WolfVariantComponent(WolfVariant variant) {
this.variant = variant;
}
public static WolfVariantComponent read(PacketWrapper<?> wrapper) {
WolfVariant type = wrapper.readMappedEntity(WolfVariants.getRegistry());
return new WolfVariantComponent(type);
}
public static void write(PacketWrapper<?> wrapper, WolfVariantComponent component) {
wrapper.writeMappedEntity(component.variant);
}
public WolfVariant getVariant() {
return this.variant;
}
public void setVariant(WolfVariant variant) {
this.variant = variant;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof WolfVariantComponent)) return false;
WolfVariantComponent that = (WolfVariantComponent) obj;
return this.variant.equals(that.variant);
}
@Override
public int hashCode() {
return Objects.hashCode(this.variant);
}
}
@@ -18,9 +18,11 @@
package com.github.retrooper.packetevents.protocol.component.builtin.item;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.item.trimmaterial.TrimMaterial;
import com.github.retrooper.packetevents.protocol.item.trimpattern.TrimPattern;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import org.jetbrains.annotations.ApiStatus;
import java.util.Objects;
@@ -28,8 +30,20 @@ public class ArmorTrim {
private TrimMaterial material;
private TrimPattern pattern;
/**
* Removed in 1.21.5
*/
@ApiStatus.Obsolete
private boolean showInTooltip;
public ArmorTrim(TrimMaterial material, TrimPattern pattern) {
this(material, pattern, true);
}
/**
* {@link #showInTooltip} has been removed in 1.21.5
*/
@ApiStatus.Obsolete
public ArmorTrim(TrimMaterial material, TrimPattern pattern, boolean showInTooltip) {
this.material = material;
this.pattern = pattern;
@@ -39,14 +53,16 @@ public class ArmorTrim {
public static ArmorTrim read(PacketWrapper<?> wrapper) {
TrimMaterial material = TrimMaterial.read(wrapper);
TrimPattern pattern = TrimPattern.read(wrapper);
boolean showInTooltip = wrapper.readBoolean();
boolean showInTooltip = wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_5) || wrapper.readBoolean();
return new ArmorTrim(material, pattern, showInTooltip);
}
public static void write(PacketWrapper<?> wrapper, ArmorTrim trim) {
TrimMaterial.write(wrapper, trim.material);
TrimPattern.write(wrapper, trim.pattern);
wrapper.writeBoolean(trim.showInTooltip);
if (wrapper.getServerVersion().isOlderThan(ServerVersion.V_1_21_5)) {
wrapper.writeBoolean(trim.showInTooltip);
}
}
public TrimMaterial getMaterial() {
@@ -65,10 +81,18 @@ public class ArmorTrim {
this.pattern = pattern;
}
/**
* Removed in 1.21.5
*/
@ApiStatus.Obsolete
public boolean isShowInTooltip() {
return this.showInTooltip;
}
/**
* Removed in 1.21.5
*/
@ApiStatus.Obsolete
public void setShowInTooltip(boolean showInTooltip) {
this.showInTooltip = showInTooltip;
}
@@ -81,13 +81,13 @@ public class BannerLayers {
public static Layer read(PacketWrapper<?> wrapper) {
BannerPattern pattern = wrapper.readMappedEntityOrDirect(
BannerPatterns.getRegistry(), BannerPattern::readDirect);
DyeColor color = wrapper.readEnum(DyeColor.values());
DyeColor color = DyeColor.read(wrapper);
return new Layer(pattern, color);
}
public static void write(PacketWrapper<?> wrapper, Layer layer) {
wrapper.writeMappedEntityOrDirect(layer.pattern, BannerPattern::writeDirect);
wrapper.writeEnum(layer.color);
DyeColor.write(wrapper, layer.color);
}
public BannerPattern getPattern() {
@@ -18,23 +18,37 @@
package com.github.retrooper.packetevents.protocol.component.builtin.item;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.component.predicates.ComponentMatchers;
import com.github.retrooper.packetevents.protocol.mapper.MappedEntitySet;
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
// why do I have to implement this mess, I just want to deserialize items
public class ItemAdventurePredicate {
private List<BlockPredicate> predicates;
/**
* Removed with 1.21.5
*/
@ApiStatus.Obsolete
private boolean showInTooltip;
public ItemAdventurePredicate(List<BlockPredicate> predicates) {
this(predicates, true);
}
/**
* {@link #showInTooltip} has been removed in 1.21.5
*/
@ApiStatus.Obsolete
public ItemAdventurePredicate(List<BlockPredicate> predicates, boolean showInTooltip) {
this.predicates = predicates;
this.showInTooltip = showInTooltip;
@@ -42,13 +56,15 @@ public class ItemAdventurePredicate {
public static ItemAdventurePredicate read(PacketWrapper<?> wrapper) {
List<BlockPredicate> predicates = wrapper.readList(BlockPredicate::read);
boolean showInTooltip = wrapper.readBoolean();
boolean showInTooltip = wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_5) || wrapper.readBoolean();
return new ItemAdventurePredicate(predicates, showInTooltip);
}
public static void write(PacketWrapper<?> wrapper, ItemAdventurePredicate predicate) {
wrapper.writeList(predicate.predicates, BlockPredicate::write);
wrapper.writeBoolean(predicate.showInTooltip);
if (wrapper.getServerVersion().isOlderThan(ServerVersion.V_1_21_5)) {
wrapper.writeBoolean(predicate.showInTooltip);
}
}
public void addPredicate(BlockPredicate predicate) {
@@ -63,10 +79,18 @@ public class ItemAdventurePredicate {
this.predicates = predicates;
}
/**
* Removed with 1.21.5
*/
@ApiStatus.Obsolete
public boolean isShowInTooltip() {
return this.showInTooltip;
}
/**
* Removed with 1.21.5
*/
@ApiStatus.Obsolete
public void setShowInTooltip(boolean showInTooltip) {
this.showInTooltip = showInTooltip;
}
@@ -90,15 +114,29 @@ public class ItemAdventurePredicate {
private @Nullable MappedEntitySet<StateType.Mapped> blocks;
private @Nullable List<PropertyMatcher> properties;
private @Nullable NBTCompound nbt;
/**
* Added with 1.21.5
*/
private ComponentMatchers matchers;
public BlockPredicate(
@Nullable MappedEntitySet<StateType.Mapped> blocks,
@Nullable List<PropertyMatcher> properties,
@Nullable NBTCompound nbt
) {
this(blocks, properties, nbt, new ComponentMatchers());
}
public BlockPredicate(
@Nullable MappedEntitySet<StateType.Mapped> blocks,
@Nullable List<PropertyMatcher> properties,
@Nullable NBTCompound nbt,
ComponentMatchers matchers
) {
this.blocks = blocks;
this.properties = properties;
this.nbt = nbt;
this.matchers = matchers;
}
public static BlockPredicate read(PacketWrapper<?> wrapper) {
@@ -107,7 +145,9 @@ public class ItemAdventurePredicate {
List<PropertyMatcher> properties = wrapper.readOptional(
ew -> wrapper.readList(PropertyMatcher::read));
NBTCompound nbt = wrapper.readOptional(PacketWrapper::readNBT);
return new BlockPredicate(blocks, properties, nbt);
ComponentMatchers matchers = wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_5)
? ComponentMatchers.read(wrapper) : new ComponentMatchers();
return new BlockPredicate(blocks, properties, nbt, matchers);
}
public static void write(PacketWrapper<?> wrapper, BlockPredicate predicate) {
@@ -115,6 +155,9 @@ public class ItemAdventurePredicate {
wrapper.writeOptional(predicate.properties,
(ew, val) -> ew.writeList(val, PropertyMatcher::write));
wrapper.writeOptional(predicate.nbt, PacketWrapper::writeNBT);
if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_5)) {
ComponentMatchers.write(wrapper, predicate.matchers);
}
}
public @Nullable MappedEntitySet<StateType.Mapped> getBlocks() {
@@ -148,6 +191,20 @@ public class ItemAdventurePredicate {
this.nbt = nbt;
}
/**
* Added with 1.21.5
*/
public ComponentMatchers getMatchers() {
return this.matchers;
}
/**
* Added with 1.21.5
*/
public void setMatchers(ComponentMatchers matchers) {
this.matchers = matchers;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
@@ -155,12 +212,13 @@ public class ItemAdventurePredicate {
BlockPredicate that = (BlockPredicate) obj;
if (!Objects.equals(this.blocks, that.blocks)) return false;
if (!Objects.equals(this.properties, that.properties)) return false;
return Objects.equals(this.nbt, that.nbt);
if (!Objects.equals(this.nbt, that.nbt)) return false;
return this.matchers.equals(that.matchers);
}
@Override
public int hashCode() {
return Objects.hash(this.blocks, this.properties, this.nbt);
return Objects.hash(this.blocks, this.properties, this.nbt, this.matchers);
}
}
@@ -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;
@@ -37,6 +39,11 @@ public class ItemAttributeModifiers {
public static final ItemAttributeModifiers EMPTY = new ItemAttributeModifiers(
Collections.emptyList(), true) {
@Override
public void setModifiers(List<ModifierEntry> modifiers) {
throw new UnsupportedOperationException();
}
@Override
public void setShowInTooltip(boolean showInTooltip) {
throw new UnsupportedOperationException();
@@ -44,8 +51,20 @@ public class ItemAttributeModifiers {
};
private List<ModifierEntry> modifiers;
/**
* Removed in 1.21.5
*/
@ApiStatus.Obsolete
private boolean showInTooltip;
public ItemAttributeModifiers(List<ModifierEntry> modifiers) {
this(modifiers, true);
}
/**
* {@link #showInTooltip} has been removed in 1.21.5
*/
@ApiStatus.Obsolete
public ItemAttributeModifiers(List<ModifierEntry> modifiers, boolean showInTooltip) {
this.modifiers = modifiers;
this.showInTooltip = showInTooltip;
@@ -53,13 +72,15 @@ public class ItemAttributeModifiers {
public static ItemAttributeModifiers read(PacketWrapper<?> wrapper) {
List<ModifierEntry> modifiers = wrapper.readList(ModifierEntry::read);
boolean showInTooltip = wrapper.readBoolean();
boolean showInTooltip = wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_5) || wrapper.readBoolean();
return new ItemAttributeModifiers(modifiers, showInTooltip);
}
public static void write(PacketWrapper<?> wrapper, ItemAttributeModifiers modifiers) {
wrapper.writeList(modifiers.modifiers, ModifierEntry::write);
wrapper.writeBoolean(modifiers.showInTooltip);
if (wrapper.getServerVersion().isOlderThan(ServerVersion.V_1_21_5)) {
wrapper.writeBoolean(modifiers.showInTooltip);
}
}
public void addModifier(ModifierEntry modifier) {
@@ -74,10 +95,18 @@ public class ItemAttributeModifiers {
this.modifiers = modifiers;
}
/**
* Removed in 1.21.5
*/
@ApiStatus.Obsolete
public boolean isShowInTooltip() {
return this.showInTooltip;
}
/**
* Removed in 1.21.5
*/
@ApiStatus.Obsolete
public void setShowInTooltip(boolean showInTooltip) {
this.showInTooltip = showInTooltip;
}
@@ -106,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() {
@@ -294,7 +338,12 @@ public class ItemAttributeModifiers {
CHEST("chest"),
HEAD("head"),
ARMOR("armor"),
BODY("body");
BODY("body"),
/**
* Added with 1.21.5
*/
SADDLE("saddle"),
;
public static final Index<String, EquipmentSlotGroup> ID_INDEX = Index.create(
EquipmentSlotGroup.class, EquipmentSlotGroup::getId);
@@ -0,0 +1,294 @@
/*
* 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.component.builtin.item;
import com.github.retrooper.packetevents.protocol.mapper.MappedEntitySet;
import com.github.retrooper.packetevents.protocol.sound.Sound;
import com.github.retrooper.packetevents.protocol.world.damagetype.DamageType;
import com.github.retrooper.packetevents.protocol.world.damagetype.DamageTypes;
import com.github.retrooper.packetevents.resources.ResourceLocation;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Objects;
public class ItemBlocksAttacks {
private float blockDelaySeconds;
private float disableCooldownScale;
private List<DamageReduction> damageReductions;
private ItemDamageFunction itemDamage;
private @Nullable ResourceLocation bypassedBy;
private @Nullable Sound blockSound;
private @Nullable Sound disableSound;
public ItemBlocksAttacks(
float blockDelaySeconds, float disableCooldownScale, List<DamageReduction> damageReductions,
ItemDamageFunction itemDamage, @Nullable ResourceLocation bypassedBy,
@Nullable Sound blockSound, @Nullable Sound disableSound
) {
this.blockDelaySeconds = blockDelaySeconds;
this.disableCooldownScale = disableCooldownScale;
this.damageReductions = damageReductions;
this.itemDamage = itemDamage;
this.bypassedBy = bypassedBy;
this.blockSound = blockSound;
this.disableSound = disableSound;
}
public static ItemBlocksAttacks read(PacketWrapper<?> wrapper) {
float blockDelaySeconds = wrapper.readFloat();
float disableCooldownScale = wrapper.readFloat();
List<DamageReduction> damageReductions = wrapper.readList(DamageReduction::read);
ItemDamageFunction itemDamage = ItemDamageFunction.read(wrapper);
ResourceLocation bypassedBy = wrapper.readOptional(PacketWrapper::readIdentifier);
Sound blockSound = wrapper.readOptional(Sound::read);
Sound disableSound = wrapper.readOptional(Sound::read);
return new ItemBlocksAttacks(
blockDelaySeconds, disableCooldownScale, damageReductions,
itemDamage, bypassedBy, blockSound, disableSound);
}
public static void write(PacketWrapper<?> wrapper, ItemBlocksAttacks attack) {
wrapper.writeFloat(attack.blockDelaySeconds);
wrapper.writeFloat(attack.disableCooldownScale);
wrapper.writeList(attack.damageReductions, DamageReduction::write);
ItemDamageFunction.write(wrapper, attack.itemDamage);
wrapper.writeOptional(attack.bypassedBy, PacketWrapper::writeIdentifier);
wrapper.writeOptional(attack.blockSound, Sound::write);
wrapper.writeOptional(attack.disableSound, Sound::write);
}
public float getBlockDelaySeconds() {
return this.blockDelaySeconds;
}
public void setBlockDelaySeconds(float blockDelaySeconds) {
this.blockDelaySeconds = blockDelaySeconds;
}
public float getDisableCooldownScale() {
return this.disableCooldownScale;
}
public void setDisableCooldownScale(float disableCooldownScale) {
this.disableCooldownScale = disableCooldownScale;
}
public List<DamageReduction> getDamageReductions() {
return this.damageReductions;
}
public void setDamageReductions(List<DamageReduction> damageReductions) {
this.damageReductions = damageReductions;
}
public ItemDamageFunction getItemDamage() {
return this.itemDamage;
}
public void setItemDamage(ItemDamageFunction itemDamage) {
this.itemDamage = itemDamage;
}
public @Nullable ResourceLocation getBypassedBy() {
return this.bypassedBy;
}
public void setBypassedBy(@Nullable ResourceLocation bypassedBy) {
this.bypassedBy = bypassedBy;
}
public @Nullable Sound getBlockSound() {
return this.blockSound;
}
public void setBlockSound(@Nullable Sound blockSound) {
this.blockSound = blockSound;
}
public @Nullable Sound getDisableSound() {
return this.disableSound;
}
public void setDisableSound(@Nullable Sound disableSound) {
this.disableSound = disableSound;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof ItemBlocksAttacks)) return false;
ItemBlocksAttacks that = (ItemBlocksAttacks) obj;
if (Float.compare(that.blockDelaySeconds, this.blockDelaySeconds) != 0) return false;
if (Float.compare(that.disableCooldownScale, this.disableCooldownScale) != 0) return false;
if (!this.damageReductions.equals(that.damageReductions)) return false;
if (!this.itemDamage.equals(that.itemDamage)) return false;
if (!Objects.equals(this.bypassedBy, that.bypassedBy)) return false;
if (!Objects.equals(this.blockSound, that.blockSound)) return false;
return Objects.equals(this.disableSound, that.disableSound);
}
@Override
public int hashCode() {
return Objects.hash(this.blockDelaySeconds, this.disableCooldownScale, this.damageReductions, this.itemDamage, this.bypassedBy, this.blockSound, this.disableSound);
}
public static final class DamageReduction {
private float horizontalBlockingAngle;
private @Nullable MappedEntitySet<DamageType> type;
private float base;
private float factor;
public DamageReduction(float horizontalBlockingAngle, @Nullable MappedEntitySet<DamageType> type, float base, float factor) {
this.horizontalBlockingAngle = horizontalBlockingAngle;
this.type = type;
this.base = base;
this.factor = factor;
}
public static DamageReduction read(PacketWrapper<?> wrapper) {
float horizontalBlockingAngle = wrapper.readFloat();
MappedEntitySet<DamageType> type = wrapper.readOptional(ew ->
MappedEntitySet.read(ew, DamageTypes.getRegistry()));
float base = wrapper.readFloat();
float factor = wrapper.readFloat();
return new DamageReduction(horizontalBlockingAngle, type, base, factor);
}
public static void write(PacketWrapper<?> wrapper, DamageReduction reduction) {
wrapper.writeFloat(reduction.horizontalBlockingAngle);
wrapper.writeOptional(reduction.type, MappedEntitySet::write);
wrapper.writeFloat(reduction.base);
wrapper.writeFloat(reduction.factor);
}
public float getHorizontalBlockingAngle() {
return this.horizontalBlockingAngle;
}
public void setHorizontalBlockingAngle(float horizontalBlockingAngle) {
this.horizontalBlockingAngle = horizontalBlockingAngle;
}
public @Nullable MappedEntitySet<DamageType> getType() {
return this.type;
}
public void setType(@Nullable MappedEntitySet<DamageType> type) {
this.type = type;
}
public float getBase() {
return this.base;
}
public void setBase(float base) {
this.base = base;
}
public float getFactor() {
return this.factor;
}
public void setFactor(float factor) {
this.factor = factor;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof DamageReduction)) return false;
DamageReduction that = (DamageReduction) obj;
if (Float.compare(that.horizontalBlockingAngle, this.horizontalBlockingAngle) != 0) return false;
if (Float.compare(that.base, this.base) != 0) return false;
if (Float.compare(that.factor, this.factor) != 0) return false;
return Objects.equals(this.type, that.type);
}
@Override
public int hashCode() {
return Objects.hash(this.horizontalBlockingAngle, this.type, this.base, this.factor);
}
}
public static final class ItemDamageFunction {
private float threshold;
private float base;
private float factor;
public ItemDamageFunction(float threshold, float base, float factor) {
this.threshold = threshold;
this.base = base;
this.factor = factor;
}
public static ItemDamageFunction read(PacketWrapper<?> wrapper) {
float threshold = wrapper.readFloat();
float base = wrapper.readFloat();
float factor = wrapper.readFloat();
return new ItemDamageFunction(threshold, base, factor);
}
public static void write(PacketWrapper<?> wrapper, ItemDamageFunction function) {
wrapper.writeFloat(function.threshold);
wrapper.writeFloat(function.base);
wrapper.writeFloat(function.factor);
}
public float getThreshold() {
return this.threshold;
}
public void setThreshold(float threshold) {
this.threshold = threshold;
}
public float getBase() {
return this.base;
}
public void setBase(float base) {
this.base = base;
}
public float getFactor() {
return this.factor;
}
public void setFactor(float factor) {
this.factor = factor;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof ItemDamageFunction)) return false;
ItemDamageFunction that = (ItemDamageFunction) obj;
if (Float.compare(that.threshold, this.threshold) != 0) return false;
if (Float.compare(that.base, this.base) != 0) return false;
return Float.compare(that.factor, this.factor) == 0;
}
@Override
public int hashCode() {
return Objects.hash(this.threshold, this.base, this.factor);
}
}
}
@@ -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.component.builtin.item;
import com.github.retrooper.packetevents.protocol.sound.Sound;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.Objects;
public class ItemBreakSound {
private Sound sound;
public ItemBreakSound(Sound sound) {
this.sound = sound;
}
public static ItemBreakSound read(PacketWrapper<?> wrapper) {
Sound sound = Sound.read(wrapper);
return new ItemBreakSound(sound);
}
public static void write(PacketWrapper<?> wrapper, ItemBreakSound sound) {
Sound.write(wrapper, sound.sound);
}
public Sound getSound() {
return this.sound;
}
public void setSound(Sound sound) {
this.sound = sound;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof ItemBreakSound)) return false;
ItemBreakSound that = (ItemBreakSound) obj;
return this.sound.equals(that.sound);
}
@Override
public int hashCode() {
return Objects.hashCode(this.sound);
}
}
@@ -31,11 +31,11 @@ public class ItemConsumable {
private Animation animation;
private Sound sound;
private boolean consumeParticles;
private List<ConsumeEffect> effects;
private List<ConsumeEffect<?>> effects;
public ItemConsumable(
float consumeSeconds, Animation animation, Sound sound,
boolean consumeParticles, List<ConsumeEffect> effects
boolean consumeParticles, List<ConsumeEffect<?>> effects
) {
this.consumeSeconds = consumeSeconds;
this.animation = animation;
@@ -49,7 +49,7 @@ public class ItemConsumable {
Animation animation = wrapper.readEnum(Animation.values());
Sound sound = Sound.read(wrapper);
boolean consumeParticles = wrapper.readBoolean();
List<ConsumeEffect> effects = wrapper.readList(ConsumeEffect::readFull);
List<ConsumeEffect<?>> effects = wrapper.readList(ConsumeEffect::readFull);
return new ItemConsumable(consumeSeconds, animation, sound, consumeParticles, effects);
}
@@ -93,11 +93,11 @@ public class ItemConsumable {
this.consumeParticles = consumeParticles;
}
public List<ConsumeEffect> getEffects() {
public List<ConsumeEffect<?>> getEffects() {
return this.effects;
}
public void setEffects(List<ConsumeEffect> effects) {
public void setEffects(List<ConsumeEffect<?>> effects) {
this.effects = effects;
}
@@ -124,6 +124,7 @@ public class ItemConsumable {
}
public enum Animation {
NONE,
EAT,
DRINK,
@@ -134,5 +135,10 @@ public class ItemConsumable {
SPYGLASS,
TOOT_HORN,
BRUSH,
/**
* Added with 1.21.4
*/
BUNDLE,
;
}
}
@@ -0,0 +1,134 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.component.builtin.item;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.color.Color;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import org.jetbrains.annotations.ApiStatus;
import java.util.ArrayList;
import java.util.List;
/**
* Custom model data was completely rewritten with 1.21.4.
* <p>
* Before 1.21.4, this used to be a single integer.<br/>
* With 1.21.4, this is now a holder of many elements.
* <p>
* If possible, use {@link com.github.retrooper.packetevents.protocol.component.ComponentTypes#ITEM_MODEL}
* instead for specifying which model an item should have.
* <p>
* When working with legacy versions, the first element in the {@link #floats}
* will represent the legacy single integer, just like Mojang is handling this.
*/
public class ItemCustomModelData {
private List<Float> floats;
private List<Boolean> flags;
private List<String> strings;
private List<Color> colors;
public ItemCustomModelData(List<Float> floats, List<Boolean> flags, List<String> strings, List<Color> colors) {
this.floats = floats;
this.flags = flags;
this.strings = strings;
this.colors = colors;
}
public ItemCustomModelData(int legacyId) {
this.floats = new ArrayList<>(1);
this.flags = new ArrayList<>(0);
this.strings = new ArrayList<>(0);
this.colors = new ArrayList<>(0);
this.setLegacyId(legacyId);
}
public static ItemCustomModelData read(PacketWrapper<?> wrapper) {
if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_4)) {
return new ItemCustomModelData(
wrapper.readList(PacketWrapper::readFloat),
wrapper.readList(PacketWrapper::readBoolean),
wrapper.readList(PacketWrapper::readString),
wrapper.readList(Color::read));
} else {
return new ItemCustomModelData(wrapper.readVarInt());
}
}
public static void write(PacketWrapper<?> wrapper, ItemCustomModelData data) {
if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_4)) {
wrapper.writeList(data.floats, PacketWrapper::writeFloat);
wrapper.writeList(data.flags, PacketWrapper::writeBoolean);
wrapper.writeList(data.strings, PacketWrapper::writeString);
wrapper.writeList(data.colors, Color::write);
} else {
wrapper.writeVarInt(data.getLegacyId());
}
}
public List<Float> getFloats() {
return this.floats;
}
public void setFloats(List<Float> floats) {
this.floats = floats;
}
public List<Boolean> getFlags() {
return this.flags;
}
public void setFlags(List<Boolean> flags) {
this.flags = flags;
}
public List<String> getStrings() {
return this.strings;
}
public void setStrings(List<String> strings) {
this.strings = strings;
}
public List<Color> getColors() {
return this.colors;
}
public void setColors(List<Color> colors) {
this.colors = colors;
}
@ApiStatus.Obsolete
public int getLegacyId() {
if (!this.floats.isEmpty()) {
return this.floats.get(0).intValue();
}
return 0;
}
@ApiStatus.Obsolete
public void setLegacyId(int legacyId) {
if (this.flags.isEmpty()) {
this.floats.add((float) legacyId);
} else {
this.floats.set(0, (float) legacyId);
}
}
}
@@ -18,15 +18,29 @@
package com.github.retrooper.packetevents.protocol.component.builtin.item;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import org.jetbrains.annotations.ApiStatus;
import java.util.Objects;
public class ItemDyeColor {
private int rgb;
/**
* Removed in 1.21.5
*/
@ApiStatus.Obsolete
private boolean showInTooltip;
public ItemDyeColor(int rgb) {
this(rgb, true);
}
/**
* {@link #showInTooltip} has been removed in 1.21.5
*/
@ApiStatus.Obsolete
public ItemDyeColor(int rgb, boolean showInTooltip) {
this.rgb = rgb;
this.showInTooltip = showInTooltip;
@@ -34,13 +48,15 @@ public class ItemDyeColor {
public static ItemDyeColor read(PacketWrapper<?> wrapper) {
int rgb = wrapper.readInt();
boolean showInTooltip = wrapper.readBoolean();
boolean showInTooltip = wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_5) || wrapper.readBoolean();
return new ItemDyeColor(rgb, showInTooltip);
}
public static void write(PacketWrapper<?> wrapper, ItemDyeColor color) {
wrapper.writeInt(color.rgb);
wrapper.writeBoolean(color.showInTooltip);
if (wrapper.getServerVersion().isOlderThan(ServerVersion.V_1_21_5)) {
wrapper.writeBoolean(color.showInTooltip);
}
}
public int getRgb() {
@@ -51,10 +67,18 @@ public class ItemDyeColor {
this.rgb = rgb;
}
/**
* Removed in 1.21.5
*/
@ApiStatus.Obsolete
public boolean isShowInTooltip() {
return this.showInTooltip;
}
/**
* Removed in 1.21.5
*/
@ApiStatus.Obsolete
public void setShowInTooltip(boolean showInTooltip) {
this.showInTooltip = showInTooltip;
}
@@ -18,10 +18,12 @@
package com.github.retrooper.packetevents.protocol.component.builtin.item;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.item.enchantment.type.EnchantmentType;
import com.github.retrooper.packetevents.protocol.item.enchantment.type.EnchantmentTypes;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import org.jetbrains.annotations.ApiStatus;
import java.util.Collections;
import java.util.Iterator;
@@ -32,6 +34,11 @@ public class ItemEnchantments implements Iterable<Map.Entry<EnchantmentType, Int
public static final ItemEnchantments EMPTY = new ItemEnchantments(
Collections.emptyMap(), true) {
@Override
public void setEnchantments(Map<EnchantmentType, Integer> enchantments) {
throw new UnsupportedOperationException();
}
@Override
public void setShowInTooltip(boolean showInTooltip) {
throw new UnsupportedOperationException();
@@ -39,8 +46,20 @@ public class ItemEnchantments implements Iterable<Map.Entry<EnchantmentType, Int
};
private Map<EnchantmentType, Integer> enchantments;
/**
* Removed in 1.21.5
*/
@ApiStatus.Obsolete
private boolean showInTooltip;
public ItemEnchantments(Map<EnchantmentType, Integer> enchantments) {
this(enchantments, true);
}
/**
* Removed in 1.21.5
*/
@ApiStatus.Obsolete
public ItemEnchantments(Map<EnchantmentType, Integer> enchantments, boolean showInTooltip) {
this.enchantments = Collections.unmodifiableMap(enchantments);
this.showInTooltip = showInTooltip;
@@ -51,7 +70,7 @@ public class ItemEnchantments implements Iterable<Map.Entry<EnchantmentType, Int
ew -> wrapper.readMappedEntity(EnchantmentTypes.getRegistry()),
PacketWrapper::readVarInt
);
boolean showInTooltip = wrapper.readBoolean();
boolean showInTooltip = wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_5) || wrapper.readBoolean();
return new ItemEnchantments(enchantments, showInTooltip);
}
@@ -61,7 +80,9 @@ public class ItemEnchantments implements Iterable<Map.Entry<EnchantmentType, Int
(ew, enchantment) -> ew.writeVarInt(enchantment.getId(version)),
PacketWrapper::writeVarInt
);
wrapper.writeBoolean(enchantments.isShowInTooltip());
if (wrapper.getServerVersion().isOlderThan(ServerVersion.V_1_21_5)) {
wrapper.writeBoolean(enchantments.isShowInTooltip());
}
}
public int getEnchantmentLevel(EnchantmentType enchantment) {
@@ -92,10 +113,18 @@ public class ItemEnchantments implements Iterable<Map.Entry<EnchantmentType, Int
this.enchantments = enchantments;
}
/**
* Removed in 1.21.5
*/
@ApiStatus.Obsolete
public boolean isShowInTooltip() {
return this.showInTooltip;
}
/**
* Removed in 1.21.5
*/
@ApiStatus.Obsolete
public void setShowInTooltip(boolean showInTooltip) {
this.showInTooltip = showInTooltip;
}
@@ -18,13 +18,16 @@
package com.github.retrooper.packetevents.protocol.component.builtin.item;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
import com.github.retrooper.packetevents.protocol.mapper.MappedEntitySet;
import com.github.retrooper.packetevents.protocol.player.EquipmentSlot;
import com.github.retrooper.packetevents.protocol.sound.Sound;
import com.github.retrooper.packetevents.protocol.sound.Sounds;
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.Objects;
@@ -33,56 +36,124 @@ public class ItemEquippable {
private EquipmentSlot slot;
private Sound equipSound;
private @Nullable ResourceLocation model;
private @Nullable ResourceLocation assetId;
private @Nullable ResourceLocation cameraOverlay;
private @Nullable MappedEntitySet<EntityType> allowedEntities;
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(
EquipmentSlot slot,
Sound equipSound,
@Nullable ResourceLocation model,
@Nullable ResourceLocation assetId,
@Nullable ResourceLocation cameraOverlay,
@Nullable MappedEntitySet<EntityType> allowedEntities,
boolean dispensable,
boolean swappable,
boolean damageOnHurt
) {
this(slot, equipSound, assetId, cameraOverlay, allowedEntities,
dispensable, swappable, damageOnHurt, false);
}
@ApiStatus.Obsolete
public ItemEquippable(
EquipmentSlot slot,
Sound equipSound,
@Nullable ResourceLocation assetId,
@Nullable ResourceLocation cameraOverlay,
@Nullable MappedEntitySet<EntityType> allowedEntities,
boolean dispensable,
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;
this.model = model;
this.assetId = assetId;
this.cameraOverlay = cameraOverlay;
this.allowedEntities = allowedEntities;
this.dispensable = dispensable;
this.swappable = swappable;
this.damageOnHurt = damageOnHurt;
this.equipOnInteract = equipOnInteract;
this.canBeSheared = canBeSheared;
this.shearingSound = shearingSound;
}
public static ItemEquippable read(PacketWrapper<?> wrapper) {
EquipmentSlot slot = wrapper.readEnum(EquipmentSlot.values());
Sound equipSound = Sound.read(wrapper);
ResourceLocation model = wrapper.readOptional(PacketWrapper::readIdentifier);
ResourceLocation assetId = wrapper.readOptional(PacketWrapper::readIdentifier);
ResourceLocation cameraOverlay = wrapper.readOptional(PacketWrapper::readIdentifier);
MappedEntitySet<EntityType> allowedEntities = wrapper.readOptional(
ew -> MappedEntitySet.read(ew, EntityTypes::getById));
boolean dispensable = wrapper.readBoolean();
boolean swappable = wrapper.readBoolean();
boolean damageOnHurt = wrapper.readBoolean();
return new ItemEquippable(slot, equipSound, model,
cameraOverlay, allowedEntities, dispensable, swappable, damageOnHurt);
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, canBeSheared, shearingSound);
}
public static void write(PacketWrapper<?> wrapper, ItemEquippable equippable) {
wrapper.writeEnum(equippable.slot);
Sound.write(wrapper, equippable.equipSound);
wrapper.writeOptional(equippable.model, PacketWrapper::writeIdentifier);
wrapper.writeOptional(equippable.assetId, PacketWrapper::writeIdentifier);
wrapper.writeOptional(equippable.cameraOverlay, PacketWrapper::writeIdentifier);
wrapper.writeOptional(equippable.allowedEntities, MappedEntitySet::write);
wrapper.writeBoolean(equippable.dispensable);
wrapper.writeBoolean(equippable.swappable);
wrapper.writeBoolean(equippable.damageOnHurt);
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);
}
}
}
public EquipmentSlot getSlot() {
@@ -101,12 +172,12 @@ public class ItemEquippable {
this.equipSound = equipSound;
}
public @Nullable ResourceLocation getModel() {
return this.model;
public @Nullable ResourceLocation getAssetId() {
return this.assetId;
}
public void setModel(@Nullable ResourceLocation model) {
this.model = model;
public void setAssetId(@Nullable ResourceLocation assetId) {
this.assetId = assetId;
}
public @Nullable ResourceLocation getCameraOverlay() {
@@ -149,28 +220,82 @@ public class ItemEquippable {
this.damageOnHurt = damageOnHurt;
}
/**
* Added with 1.21.5
*/
public boolean isEquipOnInteract() {
return this.equipOnInteract;
}
/**
* Added with 1.21.5
*/
public void setEquipOnInteract(boolean equipOnInteract) {
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;
}
@Deprecated
public void setModel(@Nullable ResourceLocation assetId) {
this.assetId = assetId;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof ItemEquippable)) return false;
ItemEquippable that = (ItemEquippable) obj;
if (this.dispensable != that.dispensable) return false;
if (this.swappable != that.swappable) return false;
if (this.damageOnHurt != that.damageOnHurt) return false;
if (this.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 (!Objects.equals(this.model, that.model)) 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;
return Objects.equals(this.allowedEntities, that.allowedEntities);
if (!Objects.equals(this.allowedEntities, that.allowedEntities)) return false;
return this.shearingSound.equals(that.shearingSound);
}
@Override
public int hashCode() {
return Objects.hash(this.slot, this.equipSound, this.model, this.cameraOverlay, this.allowedEntities, this.dispensable, this.swappable, this.damageOnHurt);
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 + ", model=" + this.model + ", cameraOverlay=" + this.cameraOverlay + ", allowedEntities=" + this.allowedEntities + ", dispensable=" + this.dispensable + ", swappable=" + this.swappable + ", damageOnHurt=" + this.damageOnHurt + '}';
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 + '}';
}
}
@@ -0,0 +1,74 @@
/*
* 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.component.builtin.item;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.item.instrument.Instrument;
import com.github.retrooper.packetevents.protocol.item.instrument.Instruments;
import com.github.retrooper.packetevents.protocol.mapper.MaybeMappedEntity;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.Objects;
public class ItemInstrument {
private MaybeMappedEntity<Instrument> instrument;
public ItemInstrument(MaybeMappedEntity<Instrument> instrument) {
this.instrument = instrument;
}
public static ItemInstrument read(PacketWrapper<?> wrapper) {
MaybeMappedEntity<Instrument> instrument;
if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_5)) {
instrument = MaybeMappedEntity.read(wrapper, Instruments.getRegistry(), Instrument::read);
} else {
instrument = new MaybeMappedEntity<>(Instrument.read(wrapper));
}
return new ItemInstrument(instrument);
}
public static void write(PacketWrapper<?> wrapper, ItemInstrument instrument) {
if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_5)) {
MaybeMappedEntity.write(wrapper, instrument.instrument, Instrument::write);
} else {
Instrument.write(wrapper, instrument.instrument.getValueOrThrow());
}
}
public MaybeMappedEntity<Instrument> getInstrument() {
return this.instrument;
}
public void setInstrument(MaybeMappedEntity<Instrument> instrument) {
this.instrument = instrument;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof ItemInstrument)) return false;
ItemInstrument that = (ItemInstrument) obj;
return this.instrument.equals(that.instrument);
}
@Override
public int hashCode() {
return Objects.hashCode(this.instrument);
}
}
Loaded 100 of 651 files, more files were not shown because too many files have changed in this diff. Show more