Compare commits

..
262 Commits
Author SHA1 Message Date
retrooper a3739319af Release of PacketEvents 2.3.0 2024-05-08 23:35:28 +02:00
retrooper 5513c0f14b Merge pull request #759 from booky10/fix/joingame-1.16.1
Fix reading/writing of JoinGame packet on 1.16/1.16.1
2024-05-08 23:26:01 +02:00
retrooper 6869ac594f WrapperPlayServerSoundEffect fix attempt for 1.8 2024-05-08 23:24:50 +02:00
retrooper 1bad630ec1 Some fixes for block data conversions 2024-05-08 23:16:21 +02:00
AoElite ba21fa9a8b Merge pull request #756 from booky10/fix/spigot-dimension-conversion
Fix bukkit dimension conversion utility for 1.16 to 1.20.5
2024-05-07 19:35:25 -04:00
AoElite 7d01583cea Merge pull request #755 from booky10/fix/merchant-offers
Fix merchant offers packet wrapper for 1.19 to 1.20.5
2024-05-07 19:35:15 -04:00
booky10 90968ca195 Fix reading of JoinGame packet on 1.16/1.16.1 2024-05-07 21:10:51 +02:00
Abhigya 3e1cffee7e Merge pull request #758 from AbhigyaKrishna/2.0
fix: blockstate deserialization fix
2024-05-07 18:01:04 +05:30
AbhigyaKrishna d6564e6263 fix: blockstate deserialization fix 2024-05-07 17:59:26 +05:30
booky10 24b7b97c09 Fully fix bukkit dimension conversion for 1.16 to 1.20.5 2024-05-06 23:30:54 +02:00
booky10 bf0448ab15 Fix merchant offer reading/writing for 1.19 to 1.20.5 2024-05-06 18:36:46 +02:00
AoElite 6c3b66ef84 Merge pull request #754 from booky10/fix/itemstack-damageable-components
Check for components in ItemStack#isDamageableItem
2024-05-05 22:07:58 -04:00
AoElite 507281fd18 Merge pull request #753 from BlueTree242/2.0
Fix incorrect writing of Server Data packet 1.20.5+
2024-05-05 22:06:18 -04:00
booky10 c46c536ea9 Check for components in ItemStack#isDamageableItem 2024-05-05 23:27:27 +02:00
BlueTree242 fb15ac5742 Fix incorrect writing of Server Data packet 1.20.5+ 2024-05-05 22:28:03 +03:00
retrooper 427a305b61 Merge pull request #752 from booky10/fix/itemstack-enchanted
Fix ItemStack#isEnchanted check always returning true
2024-05-05 20:29:38 +02:00
retrooper ded4f5103f Prevent update checker from retrying. 2024-05-05 19:30:24 +02:00
booky10 004c1aadab Fix ItemStack#isEnchanted check always returning true 2024-05-05 18:53:02 +02:00
retrooper 2f0ffb163c Merge pull request #751 from booky10/feat/potion-definition-javadocs
Add definition javadocs to potions and potion types
2024-05-05 18:52:39 +02:00
booky10 be03ffe93f Add definition javadocs to potions and potion types 2024-05-05 18:49:40 +02:00
retrooper b943f195f3 Merge pull request #750 from booky10/fix/potion-types-pre1.20.5
Adjust potion type mappings so 1.20.1 and below works without manual adjustments
2024-05-05 18:45:22 +02:00
retrooper 31e7fba37d Merge pull request #744 from booky10/fix/nbt-component-types
Implement nbt-serialized component types
2024-05-05 18:39:48 +02:00
retrooper 14c75f19fb Merge pull request #749 from booky10/fix/1.20.5-particles
Update particle data to 1.20.5
2024-05-05 18:37:18 +02:00
booky10 3fef6fa51c Adjust potion type mappings so 1.20.1 and below works without manual adjustments 2024-05-05 18:20:32 +02:00
booky10 b6c62bb055 Clean up particle reading/writing 2024-05-05 17:31:51 +02:00
retrooper c3edd14b90 Fix ViaVersion errors when accessing protocol version. 2024-05-05 17:19:38 +02:00
booky10 7014999f65 Update particle data to 1.20.5
Also includes refactor to implement generics in particle type encoding/decoding
2024-05-05 16:41:46 +02:00
booky10 d3b32b4e22 Merge branch 'retrooper:2.0' into fix/nbt-component-types 2024-05-05 14:05:03 +02:00
retrooper b94a86e5fa PotionTypes mappings corrected on versions older than 1.20.2, and Bukkit potion type conversions fixed. 2024-05-05 08:12:31 +02:00
retrooper 9038fd149a Fix gradle-publish.yml indentation 2024-05-05 06:33:09 +02:00
retrooper 65cf7c0b92 Call user connect event on fabric 2024-05-05 06:18:50 +02:00
AoElite c1d2c6c049 Merge pull request #747 from booky10/workaround/known-world-heights
Work around 1.20.5 not sending known dimension types
2024-05-04 23:28:41 -04:00
booky10 b2a9b6a98c Work around 1.20.5 not sending known dimension types
The server no longer sends known registries to the vanilla client
This causes packetevents to no longer receive dimension type information, so fallback to vanilla defaults as a workaround
2024-05-05 05:10:07 +02:00
AoElite 1cf80df77a Merge pull request #746 from booky10/fix/state-type-mappings
Fix state type mappings
2024-05-04 22:42:28 -04:00
booky10 2606094a40 Also regenerate modern block mappings for 1.13 2024-05-05 04:41:28 +02:00
booky10 ddf014b852 Regenerate modern block mappings
All "false" boolean values were "true"
2024-05-05 04:35:44 +02:00
booky10 be2f392c91 Add state type id integrity tests 2024-05-05 04:35:43 +02:00
AoElite 91c370327b Merge pull request #745 from booky10/feat/itemstack-components-api
Implement components in more ItemStack methods
2024-05-04 22:13:57 -04:00
booky10 6dfdfc8363 Fallback to legacy max durability in ItemStack#getMaxDamage 2024-05-05 04:11:04 +02:00
booky10 e09c596020 Implement components in ItemStack#getMaxStackSize 2024-05-05 04:10:49 +02:00
AoElite 5bf7dba140 Merge pull request #743 from booky10/feat/itemstack-components-api
Add support for components in existing ItemStack nbt utilities
2024-05-04 22:01:03 -04:00
booky10 7d74474fde Limit damage to 0 in ItemStack#setDamageValue 2024-05-05 03:08:32 +02:00
booky10 14195de83e Fix relative compression path 2024-05-05 02:56:58 +02:00
booky10 8e16c5564d Implement nbt-serialized component types
Previously left unimplemented because I thought they weren't needed

Related to #741
2024-05-05 02:15:47 +02:00
booky10 803a50542c Add support for components in existing ItemStack nbt utilities
Includes damage, max damage and nbt

Also fixes ItemStack match/equals methods
2024-05-05 01:11:17 +02:00
AoElite 150acb64c3 Merge pull request #742 from booky10/fix/particles-packet
Fix particle packet for 1.20.5+
2024-05-04 18:55:09 -04:00
booky10 009f0a7c13 Fix particle packet for 1.20.5+
Fixes #740
2024-05-05 00:14:28 +02:00
retrooper db99d1f187 Update gradle publish 2024-05-04 00:56:25 +02:00
retrooper 6514b84adf Fix to netty injection on fabric 2024-05-04 00:54:04 +02:00
retrooper e40dfe35b8 Merge pull request #737 from booky10/fix/fabric-adventure-include
Include adventure dependency in fabric recursively
2024-05-04 00:31:30 +02:00
booky10 fee0ff6e26 Include adventure dependency in fabric recursively 2024-05-04 00:30:22 +02:00
retrooper 9ed447164a SpigotConversionUtil for MainHand 2024-05-04 00:27:08 +02:00
retrooper 6102208f45 SpigotConversionUtil#toBukkitPose and fromBukkitPose added 2024-05-04 00:14:06 +02:00
retrooper ec31fb0cbb Merge branch '2.0' of https://github.com/retrooper/packetevents into 2.0 2024-05-03 23:59:45 +02:00
retrooper c4660b4821 Remove random test code in fabric 2024-05-03 23:59:38 +02:00
retrooper 978be6bbcc Merge pull request #736 from booky10/fix/armadillo-state-metadata
Fix armadillo state metadata enum
2024-05-03 23:58:24 +02:00
booky10 ee8b1e9458 Fix armadillo state metadata enum
Fixes #735
2024-05-03 23:54:51 +02:00
retrooper 4fdd047026 Add Fabric to PacketEvents repo 2024-05-03 23:53:53 +02:00
retrooper 5c22920393 Fixing build task order 2024-05-03 19:44:59 +02:00
retrooper 8a18947fd2 Merge pull request #733 from booky10/fix/block-state-properties
Fix block state properties being left unparsed
2024-05-03 19:29:33 +02:00
AoElite e903aa52e3 Merge pull request #734 from Bram1903/FoliaCompatUtilPatch
Fixed: Paper Schedulers 0 delay handling
2024-05-03 13:27:36 -04:00
Bram 9ff8cf30b4 Fixed: Some paper schedulers that do not allow a delay of 0 in either the initial or regular delay 2024-05-03 18:53:49 +02:00
retrooper 8092bbdb3b Revert "Fix shadowJar build issues"
This reverts commit bff9ef2f6b.
2024-05-03 18:51:42 +02:00
retrooper bff9ef2f6b Fix shadowJar build issues 2024-05-03 18:42:29 +02:00
AoElite cc1bd65841 fix runAtFixedRate tick conversion in AsyncScheduler 2024-05-03 11:54:06 -04:00
booky10 8a84b1fc15 Fix block state properties being left unparsed
Fixes #728
2024-05-03 17:50:45 +02:00
Abhigya 3015f40531 Merge pull request #731 from AbhigyaKrishna/2.0
Mapping generation fix and task upToDate check
2024-05-03 12:53:24 +05:30
AbhigyaKrishna f4e5dab1d8 feat: mapping task upToDate check 2024-05-03 12:51:20 +05:30
AbhigyaKrishna 2792dd4c78 fix: mappings generation issue 2024-05-03 12:50:54 +05:30
AbhigyaKrishna b4d45f0fba Merge remote-tracking branch 'origin/2.0' into 2.0 2024-05-03 03:50:25 +05:30
AoElite 3443a482b3 async runAtFixedRate fix 2024-05-02 18:12:57 -04:00
AbhigyaKrishna d89af56959 feat: mapping task upToDate check 2024-05-03 03:19:54 +05:30
AoElite 80d7c4a5a9 add runAtFixedRate specifically for ticks in AsyncScheduler 2024-05-02 17:36:36 -04:00
retrooper 810b205cfa Merge pull request #709 from Bram1903/FoliaCompatUtilPatch
Folia Compatibility Utility Rewrite
2024-05-02 23:00:48 +02:00
Bram 0c452ab842 Merge branch 'refs/heads/2.0' into FoliaCompatUtilPatch 2024-05-02 18:16:45 +02:00
Abhigya be414fceb6 Merge pull request #727 from AbhigyaKrishna/2.0
Added missing StateValue for 1.20.5
2024-05-02 21:10:27 +05:30
AbhigyaKrishna 95099e9763 feat: added missing StateValue 2024-05-02 21:09:27 +05:30
Bram f806773cbe Merge branch 'refs/heads/2.0' into FoliaCompatUtilPatch 2024-05-02 17:30:04 +02:00
retrooper 9af8bab57f Merge pull request #724 from LeeGodSRC/fix/cb-relocation
fix: Fixed CB Relocation on Paper 1.20.5+
2024-05-02 17:05:27 +02:00
Bram 20c5d9f28a Merge branch 'refs/heads/2.0' into FoliaCompatUtilPatch 2024-05-02 16:42:54 +02:00
Abhigya cbe474dafa Merge pull request #648 from AbhigyaKrishna/mapping-compression
Mapping compression
2024-05-02 19:21:18 +05:30
AbhigyaKrishna af90c6534b feat: updated license 2024-05-02 19:01:46 +05:30
AbhigyaKrishna 4130fcf172 fix: diff patching 2024-05-02 18:58:29 +05:30
AbhigyaKrishna e321a169c2 test: created mapping test 2024-05-02 18:58:01 +05:30
AbhigyaKrishna 54d4614600 feat: diff interface 2024-05-02 16:52:07 +05:30
AbhigyaKrishna 8fc10e8f62 feat: implement new diff system 2024-05-02 16:45:35 +05:30
AbhigyaKrishna e770a1c9ee feat: robust diff system 2024-05-02 16:45:13 +05:30
AbhigyaKrishna c999f3a810 feat: compression task update 2024-05-02 12:54:05 +05:30
leegod 8e070aac9a fix: Fixed CB Relocation on Paper 1.20.5+ 2024-05-02 13:50:30 +08:00
AbhigyaKrishna faecd9dd9c Updated all mapping to 1.20.5 2024-05-02 04:00:15 +05:30
AbhigyaKrishna e40d8c875f Updated code for new type builder system 2024-05-02 02:39:12 +05:30
Bram 10765058f8 Fixed: Another Return statement missing after scheduling a task on Bukkit rather than Folia 2024-05-01 22:42:44 +02:00
Bram c71d6da310 Fixed: GlobalRegionScheduler#Execute being marked as private
Fixed: Return statement missing after scheduling a task on Bukkit rather than Folia
2024-05-01 22:39:54 +02:00
AbhigyaKrishna 4ec106e36f Merge 2.0 into mapping-compression 2024-05-02 01:44:09 +05:30
Abhigya 66a7ef3ffa Merge pull request #658 from booky10/dev/1.20.5
1.20.5 update
2024-05-02 01:23:56 +05:30
booky10 3d858013e6 Merge branch '2.0' into dev/1.20.5 2024-05-01 17:47:06 +02:00
booky10 3c15e5409f Move general components to another package
Components could potentially be used for something other than items in the future
2024-04-29 18:27:44 +02:00
retrooper 206d484f27 Rename the new FoliaCompatUtil to FoliaScheduler 2024-04-28 23:36:56 +02:00
retrooper e2949ade16 Update copyright years 2024-04-28 23:35:00 +02:00
retrooper 896ed7ff07 Optimizations in event system. 2024-04-28 18:10:22 +02:00
retrooper 4ca682704a Fix finding minecraft server instance on 1.20.5 (atleast on paper) 2024-04-28 18:06:22 +02:00
booky10 2275091e76 Add 1.20.6 versions 2024-04-26 16:53:28 +02:00
booky10 dd71d9ae69 Fix SCUTE/GRASS item types being invalid 2024-04-25 18:21:30 +02:00
booky10 b2d3aee10e Add constants for commonly used tool attribute uuids 2024-04-25 18:18:53 +02:00
booky10 1891307753 Fix GENERIC_GRAVITY attribute key 2024-04-24 20:48:21 +02:00
booky10 399d831d04 Fix reading entity effect for 1.20.5 2024-04-24 19:08:43 +02:00
booky10 29ad41f42f Fix reading mapped entities being two ids offset 2024-04-24 18:55:26 +02:00
booky10 bab19e14bd Merge branch '2.0' into dev/1.20.5 2024-04-24 18:48:09 +02:00
booky10 286ea801d8 Fix explosion sound in WrapperPlayServerExplosion 2024-04-24 18:43:06 +02:00
booky10 6320cc314e Prevent NPE on missing world data
Caused by server not sending data the client already knows about
2024-04-24 18:33:42 +02:00
booky10 cb094f1af3 Fix WrapperConfigServerSelectKnownPacks constructor 2024-04-24 18:22:25 +02:00
booky10 d00d138a21 Fix User#getWorldNBT(Dimension) 2024-04-24 18:22:05 +02:00
booky10 8b86b3e48b Read world nbt from restructured registry data packet 2024-04-24 18:05:46 +02:00
booky10 3232c69a5a Implement dummy component type for components without content 2024-04-24 17:53:15 +02:00
retrooper 4ee24812f4 Merge remote-tracking branch 'origin/2.0' into 2.0 2024-04-24 17:38:07 +02:00
retrooper a2139718a5 Properly cleanup user on proxy 2024-04-24 17:37:42 +02:00
booky10 57e536b8b2 Fix itemstack conversion between bukkit and nms 2024-04-24 17:33:38 +02:00
booky10 ab0e4030c3 Add sound mappings for <1.20.5 2024-04-23 21:32:07 +02:00
booky10 89fe7f43a7 Fix component value writing 2024-04-23 19:15:04 +02:00
booky10 fffb4e08b8 Add tostring handling for components 2024-04-23 19:14:56 +02:00
booky10 1b071e6564 Adjust for new handler names on channel init 2024-04-23 18:58:33 +02:00
booky10 efb1b1e1eb Fix statetype registration 2024-04-19 22:11:31 +02:00
booky10 60421a6727 Fix serverbound configuration phase packets 2024-04-19 22:11:13 +02:00
booky10 7f7107a79a Fix NPE in StateTypes#getByName 2024-04-19 21:12:03 +02:00
booky10 94827892cc Fix attributes for <1.20.5 2024-04-19 16:03:08 +02:00
booky10 78d0d674b5 Implement 1.20.5-rc1 changes for WrapperLoginServerLoginSuccess 2024-04-18 23:25:41 +02:00
booky10 ed681fadd1 Fix sound packet wrappers for >= 1.19.3 when using unregistered sounds 2024-04-18 22:49:27 +02:00
booky10 35de72c331 Implement TrimMaterial and TrimPattern registries
Technically wrong as datapacks can add more stuff, but this works until packetevents actually tracks registry data sent on login
2024-04-18 22:35:19 +02:00
booky10 018d611b2b Small cleanup to component types definition logic 2024-04-18 14:12:49 +02:00
booky10 852d34cdcf Fix equality checks for all component values 2024-04-17 22:33:22 +02:00
booky10 d4fead85b8 Add all generated default components to items 2024-04-17 22:16:12 +02:00
Bram a8bbc97d00 Fixed: Wrong message applied upon detecting an invalid packet 2024-04-17 21:55:34 +02:00
Bram 94d77e94da Merge branch 'refs/heads/2.0' into FoliaCompatUtilPatch 2024-04-17 21:52:37 +02:00
booky10 b1e2a746e3 Implement directly encoded instruments
Also implements sound event registry which is required for this (currently only for 1.20.5)
2024-04-17 19:00:45 +02:00
booky10 1b8e23dcf5 Fix showintooltip empty state for ItemEnchantments component value 2024-04-16 23:35:25 +02:00
booky10 ecd87f2fc6 Finish support for setting components on item type definition 2024-04-16 22:33:35 +02:00
booky10 22453a2fac Implement static component map builder and add shared item type components 2024-04-16 22:22:16 +02:00
booky10 80c1413811 Wrap lore component 2024-04-16 22:21:59 +02:00
booky10 0fcd8d57c0 Implement registry for state types 2024-04-16 22:06:35 +02:00
booky10 750d8813f3 Finish making all components mutable 2024-04-16 21:01:51 +02:00
booky10 ca546a9e59 Start making all components mutable 2024-04-16 19:15:41 +02:00
booky10 29fd80865c Fix compile issues 2024-04-16 18:59:26 +02:00
booky10 ab253a0976 Add potion registry 2024-04-16 18:56:57 +02:00
booky10 5545de8886 Fix equality checks for newly added registries 2024-04-16 18:56:44 +02:00
booky10 637aecbf4b Add armor material registry 2024-04-16 18:39:04 +02:00
booky10 aaf6d41766 Add instrument registry 2024-04-16 18:38:52 +02:00
booky10 f814d0ecf8 Finish implement component type serializers 2024-04-16 18:28:17 +02:00
booky10 f20e8432b1 Finish banner patterns registry 2024-04-16 18:07:56 +02:00
booky10 0e558e4baf Implement even more component types 2024-04-16 17:44:15 +02:00
booky10 5eb7d5b3fc Implement more component types 2024-04-16 13:28:28 +02:00
booky10 4a5382b14c Start implementing serializers for some component types
Mojang literally serializes half their entire codebase with these component types, this will take a while
2024-04-15 23:23:59 +02:00
booky10 c2b006ddab Add default component definition support to ItemTypes 2024-04-15 22:42:08 +02:00
booky10 e4b60d55f3 Re-generate all ItemTypes 2024-04-15 22:15:41 +02:00
booky10 4521ce8037 Make all ItemTypes final
187/1344 weren't before, idk why
2024-04-15 21:49:36 +02:00
booky10 73490b8ff6 Implement serialization for new itemstack component patches 2024-04-15 21:36:05 +02:00
AoElite 0549c8e486 Merge pull request #713 from booky10/fix/tab-complete-packet
Fix WrapperPlayClientTabComplete discarding certain fields
2024-04-15 14:51:55 -04:00
booky10 af7c0d346f Unload file mappings after PotionTypes creation 2024-04-15 20:26:25 +02:00
booky10 9a5da1bc9a Implement mappings for potion types 2024-04-15 20:18:51 +02:00
booky10 96a601da74 Fix WrapperPlayClientTabComplete discarding certain fields
Transaction id and assume command flag are lost as these fields get set after the constructor reads from the event
2024-04-15 19:57:44 +02:00
booky10 f29626311c Fix time argument parser for <1.19.4 2024-04-14 23:08:28 +02:00
booky10 ea0b9a497e Implement mappings for command argument parsers
Should also resolve #700, but needs testing
2024-04-14 22:51:31 +02:00
booky10 b11e76494e Implement mappings for block entity types 2024-04-14 22:22:15 +02:00
booky10 cb3a62cf71 Add block entity type mappings data 2024-04-14 22:13:49 +02:00
booky10 992d4855e7 Read unsigned short in creative inventory action packet 2024-04-14 21:55:28 +02:00
booky10 a684b56dc3 Use varints for amplifiers in entity effect wrapper 2024-04-14 21:50:09 +02:00
booky10 e6c86a7e4f Update dimension encoding/decoding 2024-04-14 21:49:58 +02:00
booky10 73e34d8f0b Update WrapperConfigServerRegistryData to 1.20.5-pre1 2024-04-14 21:37:21 +02:00
booky10 d006974e7b Add packet wrappers for all new packets 2024-04-14 21:22:27 +02:00
booky10 0742f24973 Add new potion types 2024-04-14 20:52:16 +02:00
booky10 76bde2568b Add new command argument parsers 2024-04-14 20:52:12 +02:00
booky10 40bd7d60d4 Update packet type ids 2024-04-14 20:51:20 +02:00
booky10 6d7718428a Fix BlockTags/ItemTags 2024-04-14 20:26:40 +02:00
booky10 92229a90e9 Fix WrapperCommonCookieResponse 2024-04-14 20:11:53 +02:00
booky10 7dd6fbd9af Update entity types to 1.20.5-pre1 2024-04-14 20:09:43 +02:00
booky10 2fa285ddde Update particle types to 1.20.5-pre1 2024-04-14 20:05:37 +02:00
booky10 8962c80495 Update some mappings and registries to 1.20.5-pre1 2024-04-14 19:17:46 +02:00
booky10 2dccce47bf Merge branch '2.0' into dev/1.20.5 2024-04-14 03:34:39 +02:00
Bram 6231e8c7d4 Fixed: AsyncScheduler now converts back the delay to ticks using the convertTimeToTicks method when using the Bukkit scheduler 2024-04-09 19:38:57 +02:00
Bram 5ba3080d00 Improved: InternalBukkitListener no longer unnecessarily uses the entity scheduler, but the region scheduler instead
Added: Chunk coordinates to region scheduler world methods
2024-04-09 19:17:54 +02:00
Bram a110c549be Fixed: EntityScheduler being wrongly invoked 2024-04-09 18:57:24 +02:00
Bram 021460ba08 Removed: Unnecessary comments 2024-04-09 09:17:54 +02:00
Bram 74d14166d5 Added: Proper deprecation annotations and documentation
Added: Copyright Notice
2024-04-08 21:42:17 +02:00
Bram f24add4246 Fixed: RegionScheduler being a protected class, instead of public (I only meant to make the constructor protected) 2024-04-08 19:09:03 +02:00
Bram acf631a54f Improved: Java docs 2024-04-06 19:30:48 +02:00
Bram a6b4087454 Fixed: Reflection method name mismatch in the AsyncScheduler and the GlobalRegionScheduler 2024-04-06 18:44:30 +02:00
Bram f392495474 Schedulers are now only able to be initialized from within the FoliaCompatUtil 2024-04-06 18:31:49 +02:00
Bram b8fdd74f96 Added: Paper Schedulers 2024-04-06 16:40:03 +02:00
Bram 9dba5d40ca Added: TaskWrapper
Improved: FoliaCompatUtil reflection caching
2024-04-05 21:30:08 +02:00
retrooper 78c7709add Recognition of SpigotConversionUtil#getEntityById 2024-03-31 01:21:58 +01:00
retrooper 7a0908faaf Fix SpigotConversionUtil#getEntityById for paper 2024-03-31 01:14:49 +01:00
retrooper 0624b1766f On legacy minecraft versions (older than 1.16), the colors are already "down-sampled" so the setting is redundant. On 1.16+, the downsampled setting is set to false by default, and will allows costumization of hex colors. 2024-03-30 23:49:12 +01:00
retrooper 651de583b6 Fix SpigotReflectionUtil#getEntityById for 1.17+ 2024-03-30 23:38:07 +01:00
retrooper c29847af02 Final change in exception handling of readUTF 2024-03-29 21:47:18 +01:00
retrooper 87c8147514 Merge remote-tracking branch 'origin/2.0' into 2.0 2024-03-29 19:48:33 +01:00
retrooper 57778b5eb3 Minor change in exception handling of readUTF 2024-03-29 19:48:11 +01:00
retrooper f2d136af0a Removed unused variable in Location 2024-03-26 18:46:45 +01:00
retrooper 22d568f30e Added direction functionality to location 2024-03-26 18:31:28 +01:00
retrooper 49a81fa4f7 Merge pull request #705 from Leymooo/2.0
Fix UUID serialization on < 1.20.3 servers with Adventure 4.15+
2024-03-24 16:45:27 +01:00
Leymooo 57f9a8fe3a Fix UUID serialization on < 1.20.3 servers with Adventure 4.15+ 2024-03-23 23:33:19 +02:00
retrooper 94c731afbf Merge pull request #704 from z7087/patch-3
Fix BlockFace.getBlockFaceByValue may return OTHER
2024-03-23 01:06:49 +01:00
z7087 98304cb41e Update BlockFace.java 2024-03-17 02:42:53 +08:00
AoElite 70d68d7860 Merge pull request #698 from Wekylend/fix/item-types-map
Fix ItemTypes ITEM_TYPE_MAP key loading
2024-03-16 01:55:30 -04:00
AoElite 5502c4a434 Merge pull request #692 from ytnoos/viaver-dev
Support for ViaVersion dev builds, Fixes #689
2024-03-16 01:45:59 -04:00
Wekylend f424b9bd66 Fix ITEM_TYPE_MAP key loading
This subsequently should fix the getByName method always returning null.
2024-03-09 01:24:29 +01:00
Abhigya c8d0733935 Merge pull request #697 from booky10/fix/missing-block-properties-api
Add missing blockstate property methods for dusted and flower_amount
2024-03-08 10:55:31 +05:30
Abhigya c2ba3304f7 Merge pull request #694 from hypemc-pl/2.0
Correct NBT component style serialization
2024-03-08 10:51:23 +05:30
booky10 510bf9301c Add missing blockstate property getters for dusted and flower_amount 2024-03-07 15:01:54 +01:00
Abhigya 8a64746b18 Merge pull request #695 from AbhigyaKrishna/2.0
Removed invalid function from NBTCodec
2024-03-04 13:45:27 +05:30
AbhigyaKrishna feab6ba0bd Removed invalid function from NBTCodec 2024-03-04 13:42:31 +05:30
Kamilkime f11a5dd31c Correct NBT component style serialization 2024-03-04 02:08:40 +01:00
ytnoos 5a3a4f6507 Support for ViaVersion dev builds 2024-03-02 11:11:11 +01:00
retrooper 40fa932d33 Merge pull request #683 from AbhigyaKrishna/2.0
AdventureNBTSerializer reworked
2024-03-01 21:33:57 +01:00
AbhigyaKrishna 1355ca6bdd Optimised imports 2024-02-29 12:46:56 +05:30
AoElite 5639c2b85e Merge pull request #687 from Syntellix/2.0
Implement settings for printing packet exception stacktraces and kicking the player for packet exceptions
2024-02-27 14:48:05 -05:00
AoElite baa8837987 Merge pull request #686 from SamB440/feat/read-only-block-data
Add methods for getting WrappedBlockStates without cloning
2024-02-27 13:48:03 -05:00
MachineBreaker 38f2783149 Apply requested changes 2024-02-27 14:17:17 -04:00
MachineBreaker 43a5e2c590 Add settings for full stacktrace and player kicking
Idea from AoElite
2024-02-27 13:59:41 -04:00
MachineBreaker 9a124b8e68 Don't print full stacktrace if debug is not enabled 2024-02-27 13:27:32 -04:00
SamB440 02b9e9260f Add methods for getting WrappedBlockStates without cloning 2024-02-27 16:29:57 +00:00
AbhigyaKrishna d109e9dd54 Reading text field from number and boolean 2024-02-25 13:24:13 +05:30
AbhigyaKrishna 2ea24250a0 Component serialization for boolean and number 2024-02-25 13:06:45 +05:30
AbhigyaKrishna 39d555f3ec Update license 2024-02-24 20:31:32 +05:30
AbhigyaKrishna 6e09ec2e2b Simplified decoration reading 2024-02-24 17:37:18 +05:30
AbhigyaKrishna f91de06044 AdventureNBTSerializer rework (minor patch) 2024-02-24 13:36:59 +05:30
AbhigyaKrishna 63e3563a1a Merge remote-tracking branch 'origin/2.0' into 2.0
# Conflicts:
#	api/src/main/java/com/github/retrooper/packetevents/util/adventure/AdventureNBTSerializer.java
2024-02-24 13:34:22 +05:30
AbhigyaKrishna 655d97c73a AdventureNBTSerializer rework 2024-02-24 13:33:58 +05:30
AbhigyaKrishna a7c8f21d31 AdventureNBTSerializer rework 2024-02-24 13:18:28 +05:30
AbhigyaKrishna f23ff3d421 pattern matching for excluding gson 2024-02-24 13:17:44 +05:30
AbhigyaKrishna 766f0c0a32 NBT toString implementation 2024-02-24 13:15:45 +05:30
retrooper e13d52a518 Attempted fixes at WrapperPlayServerDeclareCommands 2024-02-23 19:55:27 +01:00
AbhigyaKrishna 329b8adefa Removed debug statements 2024-02-12 02:51:22 +05:30
AbhigyaKrishna a7949eb096 Merge remote-tracking branch 'origin/mapping-compression' into mapping-compression 2024-02-12 02:50:11 +05:30
AbhigyaKrishna a4288ca29c Fixed loading of Block states 2024-02-12 02:49:51 +05:30
retrooper e5b5845ebf Update copyright year on newly created files. 2024-02-11 19:56:36 +01:00
booky10 3726f6629a Add common packet implementation for cookie responses 2024-01-19 20:12:38 +01:00
booky10 33aae65e35 Update particle type mappings for 24w03b 2024-01-19 18:05:07 +01:00
booky10 2d495b7570 Add backwards compatibility for sweeping edge renaming 2024-01-17 23:09:27 +01:00
booky10 5a8acfdffd Add packet wrapper for all new packets 2024-01-17 22:49:48 +01:00
booky10 1938f9f3bf Fix missing play PacketType 2024-01-17 22:39:35 +01:00
booky10 672b8e47fd Update login encryption request packet 2024-01-17 22:33:25 +01:00
booky10 846d0a893e Update secure chat enforcement fields 2024-01-17 22:33:14 +01:00
booky10 fb45b5b35a Update handshake packet for 24w03a 2024-01-17 22:27:31 +01:00
booky10 1205020451 Update block and item tags 2024-01-17 22:19:12 +01:00
booky10 3ed2735d0e Rename enchantment "sweeping" to "sweeping_edge" 2024-01-17 22:11:53 +01:00
booky10 5b3d6ae7a2 Update attribute mappings for 24w03a 2024-01-17 22:09:11 +01:00
booky10 e3d9638b47 Update packet types and ids for 24w03a 2024-01-17 21:58:02 +01:00
booky10 9ec6118159 Merge branch '2.0' into dev/1.20.5 2024-01-17 21:43:47 +01:00
AbhigyaKrishna af251d03b8 Use new mappings scheme 2024-01-07 15:48:35 +05:30
AbhigyaKrishna 1445057145 Mapping Compression Task 2024-01-07 15:47:45 +05:30
booky10 721532ee44 Merge branch '2.0' into dev/1.20.5 2023-12-30 05:10:54 +01:00
booky10 c936c9da31 Merge branch '2.0' into dev/1.20.5 2023-12-26 03:56:11 +01:00
booky10 28cb480ac3 Merge branch '2.0' into dev/1.20.5 2023-12-22 02:49:37 +01:00
booky10 26eee81455 Also add validity check to ItemTags 2023-12-19 21:42:56 +01:00
booky10 8c63a7c7b6 Update item tags to 23w51b 2023-12-19 21:38:44 +01:00
booky10 d221869491 Re-generate block-/item-tags
But this time with correct ordering
2023-12-19 21:36:46 +01:00
booky10 539b814a5a Update attributes update packet structure
Attributes are now encoded as id instead of writing their keys
2023-12-19 21:05:05 +01:00
booky10 d0da1d710b Add attribute mappings
Attributes are now encoded with their id in packets
2023-12-19 20:56:17 +01:00
booky10 2771959dd8 Update effect packet structure
Removes factor data
2023-12-19 20:43:34 +01:00
booky10 aa17d098c4 Update entity data type mappings 2023-12-19 20:40:15 +01:00
booky10 7a1f432652 Update item type mappings 2023-12-19 20:35:22 +01:00
booky10 bca60bfa19 Update entity type mappings 2023-12-19 20:35:17 +01:00
booky10 94e2dc0378 Add 1.20.5 version constants 2023-12-19 20:35:09 +01:00
266 changed files with 1827802 additions and 260129 deletions

No files matched your search

+7 -1
View File
@@ -52,4 +52,10 @@ jobs:
uses: actions/upload-artifact@v3
with:
name: velocity-build
path: velocity/build/libs
path: velocity/build/libs
- name: Upload build artifacts fabric
uses: actions/upload-artifact@v3
with:
name: fabric-build
path: fabric/build/libs
+38 -1
View File
@@ -1,3 +1,5 @@
import com.github.retrooper.MappingCompressionTask
// papermc repo + disableAutoTargetJvm needed for mockbukkit
repositories {
maven { url 'https://repo.papermc.io/repository/maven-public/' }
@@ -5,6 +7,19 @@ repositories {
java {
disableAutoTargetJvm()
sourceSets {
main {
resources {
srcDirs += ["$buildDir.canonicalPath/mappings/generated"]
}
}
test {
resources {
srcDirs += ["$buildDir.canonicalPath/mappings/generated"]
}
}
}
}
dependencies {
@@ -20,4 +35,26 @@ dependencies {
test {
useJUnitPlatform()
}
}
task generateMapping(type: MappingCompressionTask) {
mappingsDir = rootDir.toPath().resolve("mappings")
outDir = project.buildDir.toPath().resolve("mappings/generated/assets/mappings")
outputs.upToDateWhen {
def gen_modified = project.buildDir.toPath().resolve("mappings/generated/assets/mappings").toFile().lastModified()
def list = []
project.rootProject.projectDir.toPath().resolve("mappings").toFile().eachFileRecurse(groovy.io.FileType.FILES) { file ->
list << file
}
for (File file : list) {
if (file.lastModified() > gen_modified) {
return false
}
}
return true
}
}
tasks.processResources.dependsOn(generateMapping)
@@ -38,7 +38,7 @@ public abstract class PacketEventsAPI<T> {
private final Logger LOGGER = Logger.getLogger(PacketEventsAPI.class.getName());
private static final LogManager LOG_MANAGER = new LogManager();
//TODO UPDATE
private static final PEVersion VERSION = new PEVersion(2, 2, 1);
private static final PEVersion VERSION = new PEVersion(2, 3, 0);
public EventManager getEventManager() {
return EVENT_MANAGER;
@@ -22,13 +22,13 @@ import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.exception.InvalidHandshakeException;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
import java.util.Set;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
public class EventManager {
private final Map<Byte, Set<PacketListenerCommon>> listenersMap = new ConcurrentHashMap<>();
private final Map<PacketListenerPriority, Set<PacketListenerCommon>> listenersMap =
Collections.synchronizedMap(new EnumMap<>(PacketListenerPriority.class));
/**
* Call the PacketEvent.
@@ -44,7 +44,7 @@ public class EventManager {
}
public void callEvent(PacketEvent event, @Nullable Runnable postCallListenerAction) {
for (byte priority = PacketListenerPriority.LOWEST.getId(); priority <= PacketListenerPriority.MONITOR.getId(); priority++) {
for (PacketListenerPriority priority : PacketListenerPriority.values()) {
Set<PacketListenerCommon> listeners = listenersMap.get(priority);
if (listeners != null) {
for (PacketListenerCommon listener : listeners) {
@@ -80,13 +80,12 @@ public class EventManager {
* @param listener {@link PacketListenerCommon}
*/
public PacketListenerCommon registerListener(PacketListenerCommon listener) {
byte priority = listener.getPriority().getId();
Set<PacketListenerCommon> listenerSet = listenersMap.get(priority);
Set<PacketListenerCommon> listenerSet = listenersMap.get(listener.getPriority());
if (listenerSet == null) {
listenerSet = ConcurrentHashMap.newKeySet();
}
listenerSet.add(listener);
listenersMap.put(priority, listenerSet);
listenersMap.put(listener.getPriority(), listenerSet);
return listener;
}
@@ -103,7 +102,7 @@ public class EventManager {
}
public void unregisterListener(PacketListenerCommon listener) {
Set<PacketListenerCommon> listenerSet = listenersMap.get(listener.getPriority().getId());
Set<PacketListenerCommon> listenerSet = listenersMap.get(listener.getPriority());
if (listenerSet == null) return;
listenerSet.remove(listener);
}
@@ -27,21 +27,30 @@ import com.github.retrooper.packetevents.manager.protocol.ProtocolManager;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.ConnectionState;
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
import com.github.retrooper.packetevents.protocol.nbt.NBTInt;
import com.github.retrooper.packetevents.protocol.nbt.NBTList;
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
import com.github.retrooper.packetevents.protocol.nbt.NBTType;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.protocol.player.User;
import com.github.retrooper.packetevents.protocol.player.UserProfile;
import com.github.retrooper.packetevents.resources.ResourceLocation;
import com.github.retrooper.packetevents.wrapper.configuration.server.WrapperConfigServerRegistryData;
import com.github.retrooper.packetevents.wrapper.configuration.server.WrapperConfigServerRegistryData.RegistryElement;
import com.github.retrooper.packetevents.wrapper.handshaking.client.WrapperHandshakingClientHandshake;
import com.github.retrooper.packetevents.wrapper.login.server.WrapperLoginServerLoginSuccess;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerJoinGame;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerRespawn;
import java.net.InetSocketAddress;
import java.util.List;
public class InternalPacketListener extends PacketListenerAbstract {
private static final ResourceLocation DIMENSION_TYPE_REGISTRY_KEY =
ResourceLocation.minecraft("dimension_type");
public InternalPacketListener() {
this(PacketListenerPriority.LOWEST);
}
@@ -89,10 +98,29 @@ public class InternalPacketListener extends PacketListenerAbstract {
// Store world data
NBTCompound registryDataTag = registryData.getRegistryData();
if (registryDataTag != null) {
NBTList<NBTCompound> list = registryDataTag
.getCompoundTagOrNull("minecraft:dimension_type")
NBTList<NBTCompound> list = null;
if (registryDataTag != null) { // <1.20.5
list = registryDataTag
.getCompoundTagOrNull(DIMENSION_TYPE_REGISTRY_KEY.toString())
.getCompoundListTagOrNull("value");
} else if (DIMENSION_TYPE_REGISTRY_KEY.equals(registryData.getRegistryKey())) { // >=1.20.5
// remap to legacy format
list = new NBTList<>(NBTType.COMPOUND);
List<RegistryElement> elements = registryData.getElements();
if (elements != null) {
int i = 0;
for (RegistryElement element : elements) {
NBTCompound tag = new NBTCompound();
tag.setTag("name", new NBTString(element.getId().toString()));
tag.setTag("id", new NBTInt(i++));
if (element.getData() != null) { // may be null because of known packs not being sent
tag.setTag("element", element.getData());
}
list.addTag(tag);
}
}
}
if (list != null) {
user.setWorldNBT(list);
}
}
@@ -110,18 +138,13 @@ public class InternalPacketListener extends PacketListenerAbstract {
NBTCompound dimensionCodec = joinGame.getDimensionCodec();
if (dimensionCodec != null) {
NBTList<NBTCompound> list = dimensionCodec
.getCompoundTagOrNull("minecraft:dimension_type")
.getCompoundTagOrNull(DIMENSION_TYPE_REGISTRY_KEY.toString())
.getCompoundListTagOrNull("value");
user.setWorldNBT(list);
}
// Update world height
NBTCompound dimension = user.getWorldNBT(joinGame.getDimension().getDimensionName());
if (dimension != null) {
NBTCompound worldNBT = dimension.getCompoundTagOrNull("element");
user.setMinWorldHeight(worldNBT.getNumberTagOrNull("min_y").getAsInt());
user.setTotalWorldHeight(worldNBT.getNumberTagOrNull("height").getAsInt());
}
user.switchDimensionType(joinGame.getServerVersion(), joinGame.getDimension());
}
// Respawn is used to switch dimensions
@@ -132,12 +155,7 @@ public class InternalPacketListener extends PacketListenerAbstract {
return; // Fixed world height, no tags are sent to the client
}
NBTCompound dimension = user.getWorldNBT(respawn.getDimension().getDimensionName());
if (dimension != null) {
NBTCompound worldNBT = dimension.getCompoundTagOrNull("element"); // This is 1.17+, it always sends the world name
user.setMinWorldHeight(worldNBT.getNumberTagOrNull("min_y").getAsInt());
user.setTotalWorldHeight(worldNBT.getNumberTagOrNull("height").getAsInt());
}
user.switchDimensionType(respawn.getServerVersion(), respawn.getDimension());
} else if (event.getPacketType() == PacketType.Play.Server.CONFIGURATION_START) {
user.setEncoderState(ConnectionState.CONFIGURATION);
} else if (event.getPacketType() == PacketType.Configuration.Server.CONFIGURATION_END) {
@@ -47,8 +47,8 @@ public enum ServerVersion {
V_1_18(757), V_1_18_1(757), V_1_18_2(758),
//1.19.1 and 1.19.2 have the same protocol version
V_1_19(759), V_1_19_1(760), V_1_19_2(760), V_1_19_3(761), V_1_19_4(762),
//1.20 and 1.20.1 have the same protocol version. 1.20.3 and 1.20.4 have the same protocol version.
V_1_20(763), V_1_20_1(763), V_1_20_2(764), V_1_20_3(765), V_1_20_4(765),
//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),
//TODO UPDATE Add server version constant
ERROR(-1, true);
@@ -18,6 +18,8 @@
package com.github.retrooper.packetevents.netty.buffer;
import com.github.retrooper.packetevents.exception.PacketProcessException;
import java.io.*;
//TODO give netty credit
public class ByteBufInputStream extends InputStream implements DataInput {
@@ -204,7 +206,8 @@ public class ByteBufInputStream extends InputStream implements DataInput {
}
public String readUTF() throws IOException {
return DataInputStream.readUTF(this);
String text = DataInputStream.readUTF(this);
return text;
}
public int readUnsignedByte() throws IOException {
@@ -225,7 +228,14 @@ public class ByteBufInputStream extends InputStream implements DataInput {
if (fieldSize < 0) {
throw new IndexOutOfBoundsException("fieldSize cannot be a negative number");
} else if (fieldSize > this.available()) {
throw new EOFException("fieldSize is too long! Length is " + fieldSize + ", but maximum is " + this.available());
int value = this.available();
String msg = "fieldSize is too long! Length is " + fieldSize + ", but maximum is " + value;
if (value == 0) {
throw new PacketProcessException(msg);
}
else {
throw new EOFException(msg);
}
}
}
}
@@ -0,0 +1,24 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2023 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;
public interface Attribute extends MappedEntity {
}
@@ -0,0 +1,25 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.attribute;
public enum AttributeOperation {
ADDITION,
MULTIPLY_BASE,
MULTIPLY_TOTAL,
}
@@ -0,0 +1,106 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2023 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.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 org.jetbrains.annotations.ApiStatus;
import java.util.HashMap;
import java.util.Map;
public class Attributes {
private static final Map<String, Attribute> ATTRIBUTE_MAP = new HashMap<>();
private static final Map<Byte, Map<Integer, Attribute>> ATTRIBUTE_ID_MAP = new HashMap<>();
private static final TypesBuilder TYPES_BUILDER = new TypesBuilder("attribute/attribute_mappings");
public static Attribute define(String key) {
TypesBuilderData data = TYPES_BUILDER.define(key);
Attribute attribute = new Attribute() {
@Override
public ResourceLocation getName() {
return data.getName();
}
@Override
public int getId(ClientVersion version) {
return MappingHelper.getId(version, TYPES_BUILDER, data);
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Attribute) {
return this.getName().equals(((Attribute) obj).getName());
}
return false;
}
};
MappingHelper.registerMapping(TYPES_BUILDER, ATTRIBUTE_MAP, ATTRIBUTE_ID_MAP, attribute);
return attribute;
}
// with minecraft:key
public static Attribute getByName(String name) {
return ATTRIBUTE_MAP.get(name);
}
public static Attribute getById(ClientVersion version, int id) {
int index = TYPES_BUILDER.getDataIndex(version);
Map<Integer, Attribute> idMap = ATTRIBUTE_ID_MAP.get((byte) index);
return idMap.get(id);
}
public static final Attribute GENERIC_ARMOR = define("generic.armor");
public static final Attribute GENERIC_ARMOR_TOUGHNESS = define("generic.armor_toughness");
public static final Attribute GENERIC_ATTACK_DAMAGE = define("generic.attack_damage");
public static final Attribute GENERIC_ATTACK_KNOCKBACK = define("generic.attack_knockback");
public static final Attribute GENERIC_ATTACK_SPEED = define("generic.attack_speed");
public static final Attribute GENERIC_FLYING_SPEED = define("generic.flying_speed");
public static final Attribute GENERIC_FOLLOW_RANGE = define("generic.follow_range");
@ApiStatus.Obsolete // renamed in 1.20.5
public static final Attribute HORSE_JUMP_STRENGTH = define("horse.jump_strength");
public static final Attribute GENERIC_KNOCKBACK_RESISTANCE = define("generic.knockback_resistance");
public static final Attribute GENERIC_LUCK = define("generic.luck");
public static final Attribute GENERIC_MAX_HEALTH = define("generic.max_health");
public static final Attribute GENERIC_MOVEMENT_SPEED = define("generic.movement_speed");
public static final Attribute ZOMBIE_SPAWN_REINFORCEMENTS = define("zombie.spawn_reinforcements");
// Added in 1.20.2
public static final Attribute GENERIC_MAX_ABSORPTION = define("generic.max_absorption");
// added in 1.20.5
public static final Attribute PLAYER_BLOCK_BREAK_SPEED = define("player.block_break_speed");
public static final Attribute PLAYER_BLOCK_INTERACTION_RANGE = define("player.block_interaction_range");
public static final Attribute PLAYER_ENTITY_INTERACTION_RANGE = define("player.entity_interaction_range");
public static final Attribute GENERIC_FALL_DAMAGE_MULTIPLIER = define("generic.fall_damage_multiplier");
public static final Attribute GENERIC_GRAVITY = define("generic.gravity");
public static final Attribute GENERIC_JUMP_STRENGTH = define("generic.jump_strength");
public static final Attribute GENERIC_SAFE_FALL_DISTANCE = define("generic.safe_fall_distance");
public static final Attribute GENERIC_SCALE = define("generic.scale");
public static final Attribute GENERIC_STEP_HEIGHT = define("generic.step_height");
static {
TYPES_BUILDER.unloadFileMappings();
}
}
@@ -20,8 +20,9 @@ package com.github.retrooper.packetevents.protocol.chat;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.resources.ResourceLocation;
import com.github.retrooper.packetevents.util.TypesBuilder;
import com.github.retrooper.packetevents.util.TypesBuilderData;
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 java.util.HashMap;
import java.util.Map;
@@ -30,20 +31,11 @@ public class ChatTypes {
private static final Map<String, ChatType> CHAT_TYPE_MAP = new HashMap<>();
//Key - mappings version, value - map with chat type ids and chat types
private static final Map<Byte, Map<Integer, ChatType>> CHAT_TYPE_ID_MAP = new HashMap<>();
private static final TypesBuilder TYPES_BUILDER = new TypesBuilder("chat/chat_type_mappings",
ClientVersion.V_1_18_2,
ClientVersion.V_1_19,
ClientVersion.V_1_19_1);
static {
TYPES_BUILDER.unloadFileMappings();
}
private static final TypesBuilder TYPES_BUILDER = new TypesBuilder("chat/chat_type_mappings");
public static ChatType define(String key) {
TypesBuilderData data = TYPES_BUILDER.define(key);
ChatType chatType = new ChatType() {
private final int[] ids = data.getData();
@Override
public ResourceLocation getName() {
return data.getName();
@@ -51,16 +43,10 @@ public class ChatTypes {
@Override
public int getId(ClientVersion version) {
int index = TYPES_BUILDER.getDataIndex(version);
return ids[index];
return MappingHelper.getId(version, TYPES_BUILDER, data);
}
};
CHAT_TYPE_MAP.put(chatType.getName().toString(), chatType);
for (ClientVersion version : TYPES_BUILDER.getVersions()) {
int index = TYPES_BUILDER.getDataIndex(version);
Map<Integer, ChatType> typeIdMap = CHAT_TYPE_ID_MAP.computeIfAbsent((byte) index, k -> new HashMap<>());
typeIdMap.put(chatType.getId(version), chatType);
}
MappingHelper.registerMapping(TYPES_BUILDER, CHAT_TYPE_MAP, CHAT_TYPE_ID_MAP, chatType);
return chatType;
}
@@ -91,4 +77,8 @@ public class ChatTypes {
public static final ChatType MSG_COMMAND = define("msg_command");
@Deprecated
public static final ChatType TEAM_MSG_COMMAND = define("team_msg_command");
static {
TYPES_BUILDER.unloadFileMappings();
}
}
@@ -28,16 +28,16 @@ import java.util.Optional;
public class Node {
private byte flags;
private List<Integer> children;
private Optional<Integer> redirectNodeIndex;
private int redirectNodeIndex;
private Optional<String> name;
private Optional<Integer> parserID;
private Optional<List<Object>> properties;
private Optional<ResourceLocation> suggestionsType;
public Node(byte flags, List<Integer> children, @Nullable Integer redirectNodeIndex, @Nullable String name, @Nullable Integer parserID, @Nullable List<Object> properties, @Nullable ResourceLocation suggestionsType) {
public Node(byte flags, List<Integer> children, int redirectNodeIndex, @Nullable String name, @Nullable Integer parserID, @Nullable List<Object> properties, @Nullable ResourceLocation suggestionsType) {
this.flags = flags;
this.children = children;
this.redirectNodeIndex = Optional.ofNullable(redirectNodeIndex);
this.redirectNodeIndex = redirectNodeIndex;
this.name = Optional.ofNullable(name);
this.parserID = Optional.ofNullable(parserID);
this.properties = Optional.ofNullable(properties);
@@ -60,11 +60,11 @@ public class Node {
this.children = children;
}
public Optional<Integer> getRedirectNodeIndex() {
public int getRedirectNodeIndex() {
return redirectNodeIndex;
}
public void setRedirectNodeIndex(Optional<Integer> redirectNodeIndex) {
public void setRedirectNodeIndex(int redirectNodeIndex) {
this.redirectNodeIndex = redirectNodeIndex;
}
@@ -1,6 +1,6 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 retrooper and contributors
* 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
@@ -16,171 +16,260 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
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.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.wrapper.PacketWrapper;
import org.jetbrains.annotations.Nullable;
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 {
private static final List<Parser> parsers = Arrays.asList(
new Parser("brigadier:bool", null, null),
new Parser("brigadier:float",
packetWrapper -> {
byte flags = packetWrapper.readByte();
float min = (flags & 0x01) != 0 ? packetWrapper.readFloat() : -Float.MAX_VALUE;
float max = (flags & 0x02) != 0 ? packetWrapper.readFloat() : Float.MAX_VALUE;
return Arrays.asList(flags, min, max);
},
(packetWrapper, properties) -> {
byte flags = (byte) properties.get(0);
packetWrapper.writeByte(flags);
if ((flags & 0x01) != 0) packetWrapper.writeFloat((float) properties.get(1));
if ((flags & 0x02) != 0) packetWrapper.writeFloat((float) properties.get(2));
}
),
new Parser("brigadier:double",
packetWrapper -> {
byte flags = packetWrapper.readByte();
double min = (flags & 0x01) != 0 ? packetWrapper.readDouble() : -Double.MAX_VALUE;
double max = (flags & 0x02) != 0 ? packetWrapper.readDouble() : Double.MAX_VALUE;
return Arrays.asList(flags, min, max);
},
(packetWrapper, properties) -> {
byte flags = (byte) properties.get(0);
packetWrapper.writeByte(flags);
if ((flags & 0x01) != 0) packetWrapper.writeDouble((double) properties.get(1));
if ((flags & 0x02) != 0) packetWrapper.writeDouble((double) properties.get(2));
}
),
new Parser("brigadier:integer",
packetWrapper -> {
byte flags = packetWrapper.readByte();
int min = (flags & 0x01) != 0 ? packetWrapper.readInt() : Integer.MIN_VALUE;
int max = (flags & 0x02) != 0 ? packetWrapper.readInt() : Integer.MAX_VALUE;
return Arrays.asList(flags, min, max);
},
(packetWrapper, properties) -> {
byte flags = (byte) properties.get(0);
packetWrapper.writeByte(flags);
if ((flags & 0x01) != 0) packetWrapper.writeInt((int) properties.get(1));
if ((flags & 0x02) != 0) packetWrapper.writeInt((int) properties.get(2));
}
),
new Parser("brigadier:long",
packetWrapper -> {
byte flags = packetWrapper.readByte();
long min = (flags & 0x01) != 0 ? packetWrapper.readLong() : Long.MIN_VALUE;
long max = (flags & 0x02) != 0 ? packetWrapper.readLong() : Long.MAX_VALUE;
return Arrays.asList(flags, min, max);
},
(packetWrapper, properties) -> {
byte flags = (byte) properties.get(0);
packetWrapper.writeByte(flags);
if ((flags & 0x01) != 0) packetWrapper.writeLong((long) properties.get(1));
if ((flags & 0x02) != 0) packetWrapper.writeLong((long) properties.get(2));
}
),
new Parser("brigadier:string",
packetWrapper -> Collections.singletonList(packetWrapper.readVarInt()),
(packetWrapper, properties) -> packetWrapper.writeVarInt((Integer) properties.get(0))
),
new Parser("minecraft:entity",
packetWrapper -> Collections.singletonList(packetWrapper.readByte()),
(packetWrapper, properties) -> packetWrapper.writeByte(((Byte) properties.get(0)).intValue())
),
new Parser("minecraft:game_profile", null, null),
new Parser("minecraft:block_pos", null, null),
new Parser("minecraft:column_pos", null, null),
new Parser("minecraft:vec3", null, null),
new Parser("minecraft:vec2", null, null),
new Parser("minecraft:block_state", null, null),
new Parser("minecraft:block_predicate", null, null),
new Parser("minecraft:item_stack", null, null),
new Parser("minecraft:item_predicate", null, null),
new Parser("minecraft:color", null, null),
new Parser("minecraft:component", null, null),
new Parser("minecraft:style", null, null),
new Parser("minecraft:message", null, null),
new Parser("minecraft:nbt", null, null),
new Parser("minecraft:nbt_tag", null, null),
new Parser("minecraft:nbt_path", null, null),
new Parser("minecraft:objective", null, null),
new Parser("minecraft:objective_criteria", null, null),
new Parser("minecraft:operation", null, null),
new Parser("minecraft:particle", null, null),
new Parser("minecraft:angle", null, null),
new Parser("minecraft:rotation", null, null),
new Parser("minecraft:scoreboard_slot", null, null),
new Parser("minecraft:score_holder",
packetWrapper -> Collections.singletonList(packetWrapper.readByte()),
(packetWrapper, properties) -> packetWrapper.writeByte(((Byte) properties.get(0)).intValue())
),
new Parser("minecraft:swizzle", null, null),
new Parser("minecraft:team", null, null),
new Parser("minecraft:item_slot", null, null),
new Parser("minecraft:resource_location", null, null),
new Parser("minecraft:function", null, null),
new Parser("minecraft:entity_anchor", null, null),
new Parser("minecraft:int_range", null, null),
new Parser("minecraft:float_range", null, null),
new Parser("minecraft:dimension", null, null),
new Parser("minecraft:gamemode", null, null),
new Parser("minecraft:time",
packetWrapper -> Collections.singletonList(packetWrapper.readInt()),
(packetWrapper, properties) -> packetWrapper.writeInt((int) properties.get(0))
),
new Parser("minecraft:resource_or_tag",
packetWrapper -> Collections.singletonList(packetWrapper.readIdentifier()),
(packetWrapper, properties) -> packetWrapper.writeIdentifier((ResourceLocation) properties.get(0))
),
new Parser("minecraft:resource_or_tag_key",
packetWrapper -> Collections.singletonList(packetWrapper.readIdentifier()),
(packetWrapper, properties) -> packetWrapper.writeIdentifier((ResourceLocation) properties.get(0))
),
new Parser("minecraft:resource",
packetWrapper -> Collections.singletonList(packetWrapper.readIdentifier()),
(packetWrapper, properties) -> packetWrapper.writeIdentifier((ResourceLocation) properties.get(0))
),
new Parser("minecraft:resource_key",
packetWrapper -> Collections.singletonList(packetWrapper.readIdentifier()),
(packetWrapper, properties) -> packetWrapper.writeIdentifier((ResourceLocation) properties.get(0))
),
new Parser("minecraft:template_mirror", null, null),
new Parser("minecraft:template_rotation", null, null),
new Parser("minecraft:heightmap", null, null),
new Parser("minecraft:uuid", null, null)
);
public static List<Parser> getParsers() {
return 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");
public static Parser define(String key) {
return define(key, null, null);
}
public static final class Parser {
private final String name; //not really needed, just for toString or something
private final Optional<Function<PacketWrapper<?>, List<Object>>> read;
private final Optional<BiConsumer<PacketWrapper<?>, List<Object>>> write;
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;
}
// with key
public static Parser getByName(String name) {
return PARSER_MAP.get(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);
}
public static List<Parser> getParsers() {
return Collections.unmodifiableList(ALL_PARSERS);
}
public static final Parser BRIGADIER_BOOL = define("brigadier:bool", null, null);
public static final Parser BRIGADIER_FLOAT = define("brigadier:float",
packetWrapper -> {
byte flags = packetWrapper.readByte();
float min = (flags & 0x01) != 0 ? packetWrapper.readFloat() : -Float.MAX_VALUE;
float max = (flags & 0x02) != 0 ? packetWrapper.readFloat() : Float.MAX_VALUE;
return Arrays.asList(flags, min, max);
},
(packetWrapper, properties) -> {
byte flags = (byte) properties.get(0);
packetWrapper.writeByte(flags);
if ((flags & 0x01) != 0) packetWrapper.writeFloat((float) properties.get(1));
if ((flags & 0x02) != 0) packetWrapper.writeFloat((float) properties.get(2));
}
);
public static final Parser BRIGADIER_DOUBLE = define("brigadier:double",
packetWrapper -> {
byte flags = packetWrapper.readByte();
double min = (flags & 0x01) != 0 ? packetWrapper.readDouble() : -Double.MAX_VALUE;
double max = (flags & 0x02) != 0 ? packetWrapper.readDouble() : Double.MAX_VALUE;
return Arrays.asList(flags, min, max);
},
(packetWrapper, properties) -> {
byte flags = (byte) properties.get(0);
packetWrapper.writeByte(flags);
if ((flags & 0x01) != 0) packetWrapper.writeDouble((double) properties.get(1));
if ((flags & 0x02) != 0) packetWrapper.writeDouble((double) properties.get(2));
}
);
public static final Parser BRIGADIER_INTEGER = define("brigadier:integer",
packetWrapper -> {
byte flags = packetWrapper.readByte();
int min = (flags & 0x01) != 0 ? packetWrapper.readInt() : Integer.MIN_VALUE;
int max = (flags & 0x02) != 0 ? packetWrapper.readInt() : Integer.MAX_VALUE;
return Arrays.asList(flags, min, max);
},
(packetWrapper, properties) -> {
byte flags = (byte) properties.get(0);
packetWrapper.writeByte(flags);
if ((flags & 0x01) != 0) packetWrapper.writeInt((int) properties.get(1));
if ((flags & 0x02) != 0) packetWrapper.writeInt((int) properties.get(2));
}
);
public static final Parser BRIGADIER_LONG = define("brigadier:long",
packetWrapper -> {
byte flags = packetWrapper.readByte();
long min = (flags & 0x01) != 0 ? packetWrapper.readLong() : Long.MIN_VALUE;
long max = (flags & 0x02) != 0 ? packetWrapper.readLong() : Long.MAX_VALUE;
return Arrays.asList(flags, min, max);
},
(packetWrapper, properties) -> {
byte flags = (byte) properties.get(0);
packetWrapper.writeByte(flags);
if ((flags & 0x01) != 0) packetWrapper.writeLong((long) properties.get(1));
if ((flags & 0x02) != 0) packetWrapper.writeLong((long) properties.get(2));
}
);
public static final Parser BRIGADIER_STRING = define("brigadier:string",
packetWrapper -> Collections.singletonList(packetWrapper.readVarInt()),
(packetWrapper, properties) -> packetWrapper.writeVarInt((Integer) properties.get(0))
);
public static final Parser ENTITY = define("entity",
packetWrapper -> Collections.singletonList(packetWrapper.readByte()),
(packetWrapper, properties) -> packetWrapper.writeByte(((Byte) properties.get(0)).intValue())
);
public static final Parser GAME_PROFILE = define("game_profile", null, null);
public static final Parser BLOCK_POS = define("block_pos", null, null);
public static final Parser COLUMN_POS = define("column_pos", null, null);
public static final Parser VEC3 = define("vec3", null, null);
public static final Parser VEC2 = define("vec2", null, null);
public static final Parser BLOCK_STATE = define("block_state", null, null);
public static final Parser BLOCK_PREDICATE = define("block_predicate", null, null);
public static final Parser ITEM_STACK = define("item_stack", null, null);
public static final Parser ITEM_PREDICATE = define("item_predicate", null, null);
public static final Parser COLOR = define("color", null, null);
public static final Parser COMPONENT = define("component", null, null);
public static final Parser STYLE = define("style", null, null);
public static final Parser MESSAGE = define("message", null, null);
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);
public static final Parser OBJECTIVE_CRITERIA = define("objective_criteria", null, null);
public static final Parser OPERATION = define("operation", null, null);
public static final Parser PARTICLE = define("particle", null, null);
public static final Parser ANGLE = define("angle", null, null);
public static final Parser ROTATION = define("rotation", null, null);
public static final Parser SCOREBOARD_SLOT = define("scoreboard_slot", null, null);
public static final Parser SCORE_HOLDER = define("score_holder",
packetWrapper -> Collections.singletonList(packetWrapper.readByte()),
(packetWrapper, properties) -> packetWrapper.writeByte(((Byte) properties.get(0)).intValue())
);
public static final Parser SWIZZLE = define("swizzle", null, null);
public static final Parser TEAM = define("team", null, null);
public static final Parser ITEM_SLOT = define("item_slot", null, null);
public static final Parser ITEM_SLOTS = define("item_slots", null, null);
public static final Parser RESOURCE_LOCATION = define("resource_location", null, null);
public static final Parser FUNCTION = define("function", null, null);
public static final Parser ENTITY_ANCHOR = define("entity_anchor", null, null);
public static final Parser INT_RANGE = define("int_range", null, null);
public static final Parser FLOAT_RANGE = define("float_range", null, null);
public static final Parser DIMENSION = define("dimension", null, null);
public static final Parser GAMEMODE = define("gamemode", null, null);
public static final Parser TIME = define("time",
wrapper -> Collections.singletonList(wrapper.getServerVersion()
.isNewerThanOrEquals(ServerVersion.V_1_19_4) ? wrapper.readInt() : 0),
(wrapper, properties) -> {
if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_19_4)) {
wrapper.writeInt((int) properties.get(0));
}
}
);
public static final Parser RESOURCE_OR_TAG = define("resource_or_tag",
packetWrapper -> Collections.singletonList(packetWrapper.readIdentifier()),
(packetWrapper, properties) -> packetWrapper.writeIdentifier((ResourceLocation) properties.get(0))
);
public static final Parser RESOURCE_OR_TAG_KEY = define("resource_or_tag_key",
packetWrapper -> Collections.singletonList(packetWrapper.readIdentifier()),
(packetWrapper, properties) -> packetWrapper.writeIdentifier((ResourceLocation) properties.get(0))
);
public static final Parser RESOURCE = define("resource",
packetWrapper -> Collections.singletonList(packetWrapper.readIdentifier()),
(packetWrapper, properties) -> packetWrapper.writeIdentifier((ResourceLocation) properties.get(0))
);
public static final Parser RESOURCE_KEY = define("resource_key",
packetWrapper -> Collections.singletonList(packetWrapper.readIdentifier()),
(packetWrapper, properties) -> packetWrapper.writeIdentifier((ResourceLocation) properties.get(0))
);
public static final Parser TEMPLATE_MIRROR = define("template_mirror", null, null);
public static final Parser TEMPLATE_ROTATION = define("template_rotation", null, null);
public static final Parser HEIGHTMAP = define("heightmap", null, null);
public static final Parser LOOT_TABLE = define("loot_table", null, null);
public static final Parser LOOT_PREDICATE = define("loot_predicate", null, null);
public static final Parser LOOT_MODIFIER = define("loot_modifier", null, null);
public static final Parser UUID = define("uuid", null, null);
static {
TYPES_BUILDER.unloadFileMappings();
}
@FunctionalInterface
public interface Reader extends Function<PacketWrapper<?>, List<Object>> {}
@FunctionalInterface
public interface Writer extends BiConsumer<PacketWrapper<?>, List<Object>> {}
public static final class Parser implements MappedEntity {
private final TypesBuilderData data;
private final Reader reader;
private final Writer writer;
@Deprecated
public Parser(String name, @Nullable Function<PacketWrapper<?>, List<Object>> read, @Nullable BiConsumer<PacketWrapper<?>, List<Object>> write) {
this.name = name;
this.read = Optional.ofNullable(read);
this.write = Optional.ofNullable(write);
this(
new TypesBuilderData(new ResourceLocation(name), new int[0]),
read == null ? null : read::apply,
write == null ? null : write::accept
);
}
public Optional<List<Object>> readProperties(PacketWrapper<?> packetWrapper) {
return read.map(fn -> fn.apply(packetWrapper));
private Parser(TypesBuilderData data, @Nullable Reader reader, Writer writer) {
this.data = data;
this.reader = reader;
this.writer = writer;
}
public void writeProperties(PacketWrapper<?> packetWrapper, List<Object> properties) {
write.ifPresent(fn -> fn.accept(packetWrapper, properties));
public Optional<List<Object>> readProperties(PacketWrapper<?> wrapper) {
if (this.reader != null) {
return Optional.of(this.reader.apply(wrapper));
}
return Optional.empty();
}
public void writeProperties(PacketWrapper<?> wrapper, List<Object> properties) {
if (this.writer != null) {
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;
}
}
}
@@ -0,0 +1,91 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.component;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Predicate;
public class ComponentPredicate implements Predicate<IComponentMap> {
private List<ComponentValue<?>> requiredComponents;
public ComponentPredicate(List<ComponentValue<?>> requiredComponents) {
this.requiredComponents = requiredComponents;
}
public static ComponentPredicate read(PacketWrapper<?> wrapper) {
List<ComponentValue<?>> components = wrapper.readList(ComponentValue::read);
return new ComponentPredicate(components);
}
public static void write(PacketWrapper<?> wrapper, ComponentPredicate predicate) {
wrapper.writeList(predicate.requiredComponents, ComponentValue::write);
}
public static ComponentPredicate emptyPredicate() {
return new ComponentPredicate(new ArrayList<>());
}
@SuppressWarnings("unchecked")
public static ComponentPredicate fromPatches(PatchableComponentMap components) {
Map<ComponentType<?>, Optional<?>> patches = components.getPatches();
List<ComponentValue<?>> values = new ArrayList<>(patches.size());
for (Map.Entry<ComponentType<?>, Optional<?>> patch : patches.entrySet()) {
if (patch.getValue().isPresent()) {
values.add(new ComponentValue<>(
(ComponentType<Object>) patch.getKey(),
patch.getValue().get()
));
}
}
return new ComponentPredicate(values);
}
public PatchableComponentMap asPatches(StaticComponentMap base) {
PatchableComponentMap patched = new PatchableComponentMap(base);
for (ComponentValue<?> component : this.requiredComponents) {
patched.set(component);
}
return patched;
}
@Override
public boolean test(IComponentMap components) {
for (ComponentValue<?> component : this.requiredComponents) {
Optional<?> value = components.getOptional(component.getType());
if (!value.isPresent() || !component.getValue().equals(value.get())) {
return false;
}
}
return true;
}
public List<ComponentValue<?>> getRequiredComponents() {
return this.requiredComponents;
}
public void setRequiredComponents(List<ComponentValue<?>> requiredComponents) {
this.requiredComponents = requiredComponents;
}
}
@@ -0,0 +1,29 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.component;
import com.github.retrooper.packetevents.protocol.mapper.MappedEntity;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
public interface ComponentType<T> extends MappedEntity {
T read(PacketWrapper<?> wrapper);
void write(PacketWrapper<?> wrapper, T content);
}
@@ -0,0 +1,256 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.component;
import com.github.retrooper.packetevents.protocol.color.DyeColor;
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;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ChargedProjectiles;
import com.github.retrooper.packetevents.protocol.component.builtin.item.DebugStickState;
import com.github.retrooper.packetevents.protocol.component.builtin.item.FireworkExplosion;
import com.github.retrooper.packetevents.protocol.component.builtin.item.FoodProperties;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemAdventurePredicate;
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.ItemContainerContents;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemContainerLoot;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemDyeColor;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemEnchantments;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemFireworks;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemLock;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemLore;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemMapDecorations;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemMapPostProcessingState;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemPotionContents;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemProfile;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemRarity;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemRecipes;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemTool;
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.nbt.NBTCompound;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.resources.ResourceLocation;
import com.github.retrooper.packetevents.util.Dummy;
import com.github.retrooper.packetevents.util.mappings.MappingHelper;
import com.github.retrooper.packetevents.util.mappings.TypesBuilder;
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Function;
public class ComponentTypes {
private static final Map<String, ComponentType<?>> COMPONENT_TYPE_MAP = new HashMap<>();
private static final Map<Byte, Map<Integer, ComponentType<?>>> COMPONENT_TYPE_ID_MAP = new HashMap<>();
private static final TypesBuilder TYPES_BUILDER = new TypesBuilder("item/item_component_mappings");
public static <T> ComponentType<T> define(String key) {
return define(key, null, null);
}
public static <T> ComponentType<T> define(String key, @Nullable Reader<T> reader, @Nullable Writer<T> writer) {
TypesBuilderData data = TYPES_BUILDER.define(key);
ComponentType<T> type = new ComponentType<T>() {
@Override
public T read(PacketWrapper<?> wrapper) {
return reader == null ? null : reader.apply(wrapper);
}
@Override
public void write(PacketWrapper<?> wrapper, T content) {
if (writer != null) {
writer.accept(wrapper, content);
}
}
@Override
public ResourceLocation getName() {
return data.getName();
}
@Override
public int getId(ClientVersion version) {
return MappingHelper.getId(version, TYPES_BUILDER, data);
}
@Override
public boolean equals(Object obj) {
if (obj instanceof ComponentType<?>) {
return this.getName().equals(((ComponentType<?>) obj).getName());
}
return false;
}
@Override
public String toString() {
return "Component[" + this.getName() + "]";
}
};
MappingHelper.registerMapping(TYPES_BUILDER, COMPONENT_TYPE_MAP, COMPONENT_TYPE_ID_MAP, type);
return type;
}
// with key
public static ComponentType<?> getByName(String name) {
return COMPONENT_TYPE_MAP.get(name);
}
public static ComponentType<?> getById(ClientVersion version, int id) {
int index = TYPES_BUILDER.getDataIndex(version);
Map<Integer, ComponentType<?>> idMap = COMPONENT_TYPE_ID_MAP.get((byte) index);
return idMap.get(id);
}
// item component types
public static final ComponentType<NBTCompound> CUSTOM_DATA = define("custom_data",
PacketWrapper::readNBT, PacketWrapper::writeNBT);
public static final ComponentType<Integer> MAX_STACK_SIZE = define("max_stack_size",
PacketWrapper::readVarInt, PacketWrapper::writeVarInt);
public static final ComponentType<Integer> MAX_DAMAGE = define("max_damage",
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<Component> CUSTOM_NAME = define("custom_name",
PacketWrapper::readComponent, PacketWrapper::writeComponent);
public static final ComponentType<Component> ITEM_NAME = define("item_name",
PacketWrapper::readComponent, PacketWrapper::writeComponent);
public static final ComponentType<ItemLore> LORE = define("lore",
ItemLore::read, ItemLore::write);
public static final ComponentType<ItemRarity> RARITY = define("rarity",
wrapper -> wrapper.readEnum(ItemRarity.values()), PacketWrapper::writeEnum);
public static final ComponentType<ItemEnchantments> ENCHANTMENTS = define("enchantments",
ItemEnchantments::read, ItemEnchantments::write);
public static final ComponentType<ItemAdventurePredicate> CAN_PLACE_ON = define("can_place_on",
ItemAdventurePredicate::read, ItemAdventurePredicate::write);
public static final ComponentType<ItemAdventurePredicate> CAN_BREAK = define("can_break",
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<Dummy> HIDE_ADDITIONAL_TOOLTIP = define("hide_additional_tooltip",
Dummy::dummyRead, Dummy::dummyWrite);
public static final ComponentType<Dummy> HIDE_TOOLTIP = define("hide_tooltip",
Dummy::dummyRead, Dummy::dummyWrite);
public static final ComponentType<Integer> REPAIR_COST = define("repair_cost",
PacketWrapper::readVarInt, PacketWrapper::writeVarInt);
public static final ComponentType<Dummy> CREATIVE_SLOT_LOCK = define("creative_slot_lock",
Dummy::dummyRead, Dummy::dummyWrite);
public static final ComponentType<Boolean> ENCHANTMENT_GLINT_OVERRIDE = define("enchantment_glint_override",
PacketWrapper::readBoolean, PacketWrapper::writeBoolean);
public static final ComponentType<Dummy> INTANGIBLE_PROJECTILE = define("intangible_projectile",
Dummy::dummyReadNbt, Dummy::dummyWriteNbt);
public static final ComponentType<FoodProperties> FOOD = define("food",
FoodProperties::read, FoodProperties::write);
public static final ComponentType<Dummy> FIRE_RESISTANT = define("fire_resistant",
Dummy::dummyRead, Dummy::dummyWrite);
public static final ComponentType<ItemTool> TOOL = define("tool",
ItemTool::read, ItemTool::write);
public static final ComponentType<ItemEnchantments> STORED_ENCHANTMENTS = define("stored_enchantments",
ItemEnchantments::read, ItemEnchantments::write);
public static final ComponentType<ItemDyeColor> DYED_COLOR = define("dyed_color",
ItemDyeColor::read, ItemDyeColor::write);
public static final ComponentType<Integer> MAP_COLOR = define("map_color",
PacketWrapper::readInt, PacketWrapper::writeInt);
public static final ComponentType<Integer> MAP_ID = define("map_id",
PacketWrapper::readVarInt, PacketWrapper::writeVarInt);
public static final ComponentType<ItemMapDecorations> MAP_DECORATIONS = define("map_decorations",
ItemMapDecorations::read, ItemMapDecorations::write);
public static final ComponentType<ItemMapPostProcessingState> MAP_POST_PROCESSING = define("map_post_processing",
wrapper -> wrapper.readEnum(ItemMapPostProcessingState.values()), PacketWrapper::writeEnum);
public static final ComponentType<ChargedProjectiles> CHARGED_PROJECTILES = define("charged_projectiles",
ChargedProjectiles::read, ChargedProjectiles::write);
public static final ComponentType<BundleContents> BUNDLE_CONTENTS = define("bundle_contents",
BundleContents::read, BundleContents::write);
public static final ComponentType<ItemPotionContents> POTION_CONTENTS = define("potion_contents",
ItemPotionContents::read, ItemPotionContents::write);
public static final ComponentType<SuspiciousStewEffects> SUSPICIOUS_STEW_EFFECTS = define("suspicious_stew_effects",
SuspiciousStewEffects::read, SuspiciousStewEffects::write);
public static final ComponentType<WritableBookContent> WRITABLE_BOOK_CONTENT = define("writable_book_content",
WritableBookContent::read, WritableBookContent::write);
public static final ComponentType<WrittenBookContent> WRITTEN_BOOK_CONTENT = define("written_book_content",
WrittenBookContent::read, WrittenBookContent::write);
public static final ComponentType<ArmorTrim> TRIM = define("trim",
ArmorTrim::read, ArmorTrim::write);
public static final ComponentType<DebugStickState> DEBUG_STICK_STATE = define("debug_stick_state",
DebugStickState::read, DebugStickState::write);
public static final ComponentType<NBTCompound> ENTITY_DATA = define("entity_data",
PacketWrapper::readNBT, PacketWrapper::writeNBT);
public static final ComponentType<NBTCompound> BUCKET_ENTITY_DATA = define("bucket_entity_data",
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<Integer> OMINOUS_BOTTLE_AMPLIFIER = define("ominous_bottle_amplifier",
PacketWrapper::readVarInt, PacketWrapper::writeVarInt);
public static final ComponentType<ItemRecipes> RECIPES = define("recipes",
ItemRecipes::read, ItemRecipes::write);
public static final ComponentType<LodestoneTracker> LODESTONE_TRACKER = define("lodestone_tracker",
LodestoneTracker::read, LodestoneTracker::write);
public static final ComponentType<FireworkExplosion> FIREWORK_EXPLOSION = define("firework_explosion",
FireworkExplosion::read, FireworkExplosion::write);
public static final ComponentType<ItemFireworks> FIREWORKS = define("fireworks",
ItemFireworks::read, ItemFireworks::write);
public static final ComponentType<ItemProfile> PROFILE = define("profile",
ItemProfile::read, ItemProfile::write);
public static final ComponentType<ResourceLocation> NOTE_BLOCK_SOUND = define("note_block_sound",
PacketWrapper::readIdentifier, PacketWrapper::writeIdentifier);
public static final ComponentType<BannerLayers> BANNER_PATTERNS = define("banner_patterns",
BannerLayers::read, BannerLayers::write);
public static final ComponentType<DyeColor> BASE_COLOR = define("base_color",
wrapper -> wrapper.readEnum(DyeColor.values()), PacketWrapper::writeEnum);
public static final ComponentType<PotDecorations> POT_DECORATIONS = define("pot_decorations",
PotDecorations::read, PotDecorations::write);
public static final ComponentType<ItemContainerContents> CONTAINER = define("container",
ItemContainerContents::read, ItemContainerContents::write);
public static final ComponentType<ItemBlockStateProperties> BLOCK_STATE = define("block_state",
ItemBlockStateProperties::read, ItemBlockStateProperties::write);
public static final ComponentType<ItemBees> BEES = define("bees",
ItemBees::read, ItemBees::write);
public static final ComponentType<ItemLock> LOCK = define("lock",
ItemLock::read, ItemLock::write);
public static final ComponentType<ItemContainerLoot> CONTAINER_LOOT = define("container_loot",
ItemContainerLoot::read, ItemContainerLoot::write);
static {
TYPES_BUILDER.unloadFileMappings();
}
@FunctionalInterface
public interface Reader<T> extends Function<PacketWrapper<?>, T> {}
@FunctionalInterface
public interface Writer<T> extends BiConsumer<PacketWrapper<?>, T> {}
}
@@ -0,0 +1,76 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.component;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.Objects;
public final class ComponentValue<T> {
private final ComponentType<T> type;
private final T value;
public ComponentValue(ComponentType<T> type, T value) {
this.type = type;
this.value = value;
}
public static ComponentValue<?> read(PacketWrapper<?> wrapper) {
ComponentType<?> type = wrapper.readMappedEntity(ComponentTypes::getById);
return read0(wrapper, type);
}
private static <T> ComponentValue<T> read0(PacketWrapper<?> wrapper, ComponentType<T> type) {
// additional method required here for proper handling because of how generics work
return new ComponentValue<>(type, type.read(wrapper));
}
public static <T> void write(PacketWrapper<?> wrapper, ComponentValue<T> value) {
wrapper.writeMappedEntity(value.type);
value.type.write(wrapper, value.value);
}
public ComponentType<T> getType() {
return this.type;
}
public T getValue() {
return this.value;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof ComponentValue)) return false;
ComponentValue<?> that = (ComponentValue<?>) obj;
if (!this.type.equals(that.type)) return false;
return this.value.equals(that.value);
}
@Override
public int hashCode() {
return Objects.hash(this.type, this.value);
}
@Override
public String toString() {
return "ComponentValue{type=" + this.type + ", value=" + this.value + '}';
}
}
@@ -0,0 +1,58 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.component;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
public interface IComponentMap {
default <T> Optional<T> getOptional(ComponentType<T> type) {
return Optional.ofNullable(this.get(type));
}
boolean has(ComponentType<?> type);
@Contract("_, !null -> !null")
default <T> @Nullable T getOr(ComponentType<T> type, @Nullable T otherValue) {
T value = this.get(type);
if (value != null) {
return value;
}
return otherValue;
}
<T> @Nullable T get(ComponentType<T> type);
default <T> void set(ComponentValue<T> component) {
this.set(component.getType(), component.getValue());
}
default <T> void set(ComponentType<T> type, @Nullable T value) {
this.set(type, Optional.ofNullable(value));
}
default <T> void unset(ComponentType<T> type) {
this.set(type, Optional.empty());
}
<T> void set(ComponentType<T> type, Optional<T> value);
}
@@ -0,0 +1,103 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.component;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
public class PatchableComponentMap implements IComponentMap {
public static final PatchableComponentMap EMPTY = new PatchableComponentMap(
Collections.emptyMap(), Collections.emptyMap());
private final Map<ComponentType<?>, ?> base;
private final Map<ComponentType<?>, Optional<?>> patches;
public PatchableComponentMap(StaticComponentMap base) {
this(base.getDelegate(), new HashMap<>());
}
public PatchableComponentMap(Map<ComponentType<?>, ?> base) {
this(base, new HashMap<>());
}
public PatchableComponentMap(
StaticComponentMap base,
Map<ComponentType<?>, Optional<?>> patches
) {
this(base.getDelegate(), patches);
}
public PatchableComponentMap(
Map<ComponentType<?>, ?> base,
Map<ComponentType<?>, Optional<?>> patches
) {
this.base = Collections.unmodifiableMap(new HashMap<>(base));
this.patches = patches;
}
@SuppressWarnings("unchecked") // no
@Override
public <T> @Nullable T get(ComponentType<T> type) {
Optional<?> patched = this.patches.get(type);
if (patched != null) {
return (T) patched.orElse(null);
}
return (T) this.base.get(type);
}
@Override
public <T> void set(ComponentType<T> type, Optional<T> value) {
Object baseVal = this.base.get(type);
T newVal = value.orElse(null);
if (Objects.equals(baseVal, newVal)) {
this.patches.remove(type); // fallback to base
} else {
this.patches.put(type, value);
}
}
@Override
public boolean has(ComponentType<?> type) {
Optional<?> patched = this.patches.get(type);
return patched != null ? patched.isPresent() : this.base.containsKey(type);
}
public PatchableComponentMap copy() {
return new PatchableComponentMap(this.base, new HashMap<>(this.patches));
}
public Map<ComponentType<?>, ?> getBase() {
return this.base;
}
public Map<ComponentType<?>, Optional<?>> getPatches() {
return this.patches;
}
@Override
public String toString() {
return "PatchableComponentMap{base=" + this.base + ", patches=" + this.patches + '}';
}
}
@@ -0,0 +1,121 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.component;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemAttributeModifiers;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemEnchantments;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemLore;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemRarity;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
public class StaticComponentMap implements IComponentMap {
public static final StaticComponentMap EMPTY = new StaticComponentMap(Collections.emptyMap());
public static final StaticComponentMap SHARED_ITEM_COMPONENTS = builder()
.set(ComponentTypes.MAX_STACK_SIZE, 64)
.set(ComponentTypes.LORE, ItemLore.EMPTY)
.set(ComponentTypes.ENCHANTMENTS, ItemEnchantments.EMPTY)
.set(ComponentTypes.REPAIR_COST, 0)
.set(ComponentTypes.ATTRIBUTE_MODIFIERS, ItemAttributeModifiers.EMPTY)
.set(ComponentTypes.RARITY, ItemRarity.COMMON)
.build();
private final boolean empty;
private final Map<ComponentType<?>, ?> delegate;
public StaticComponentMap(Map<ComponentType<?>, ?> delegate) {
this.empty = delegate.isEmpty();
this.delegate = this.empty ? Collections.emptyMap()
: Collections.unmodifiableMap(new HashMap<>(delegate));
}
public static Builder builder() {
return new Builder();
}
@Override
public boolean has(ComponentType<?> type) {
return !this.empty && this.delegate.containsKey(type);
}
@SuppressWarnings("unchecked") // no
@Override
public <T> @Nullable T get(ComponentType<T> type) {
return this.empty ? null : (T) this.delegate.get(type);
}
@Override
public <T> void set(ComponentType<T> type, Optional<T> value) {
throw new UnsupportedOperationException();
}
public StaticComponentMap merge(StaticComponentMap prioritizedMap) {
return builder().setAll(this).setAll(prioritizedMap).build();
}
public Map<ComponentType<?>, ?> getDelegate() {
return this.delegate;
}
public boolean isEmpty() {
return this.empty;
}
public static class Builder {
private final Map<ComponentType<?>, Object> map = new HashMap<>();
public Builder() {
}
public StaticComponentMap build() {
return new StaticComponentMap(this.map);
}
public Builder setAll(StaticComponentMap map) {
return this.setAll(map.getDelegate());
}
@SuppressWarnings("unchecked")
public Builder setAll(Map<ComponentType<?>, ?> map) {
for (Map.Entry<ComponentType<?>, ?> entry : map.entrySet()) {
this.set((ComponentType<Object>) entry.getKey(), entry.getValue());
}
return this;
}
public <T> Builder set(ComponentType<T> type, Optional<T> value) {
return this.set(type, value.orElse(null));
}
public <T> Builder set(ComponentType<T> type, @Nullable T value) {
if (value == null) {
this.map.remove(type);
} else {
this.map.put(type, value);
}
return this;
}
}
}
@@ -0,0 +1,90 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.component.builtin.item;
import com.github.retrooper.packetevents.protocol.item.trimmaterial.TrimMaterial;
import com.github.retrooper.packetevents.protocol.item.trimpattern.TrimPattern;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.Objects;
public class ArmorTrim {
private TrimMaterial material;
private TrimPattern pattern;
private boolean showInTooltip;
public ArmorTrim(TrimMaterial material, TrimPattern pattern, boolean showInTooltip) {
this.material = material;
this.pattern = pattern;
this.showInTooltip = showInTooltip;
}
public static ArmorTrim read(PacketWrapper<?> wrapper) {
TrimMaterial material = TrimMaterial.read(wrapper);
TrimPattern pattern = TrimPattern.read(wrapper);
boolean showInTooltip = 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);
}
public TrimMaterial getMaterial() {
return this.material;
}
public void setMaterial(TrimMaterial material) {
this.material = material;
}
public TrimPattern getPattern() {
return this.pattern;
}
public void setPattern(TrimPattern pattern) {
this.pattern = pattern;
}
public boolean isShowInTooltip() {
return this.showInTooltip;
}
public void setShowInTooltip(boolean showInTooltip) {
this.showInTooltip = showInTooltip;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof ArmorTrim)) return false;
ArmorTrim armorTrim = (ArmorTrim) obj;
if (this.showInTooltip != armorTrim.showInTooltip) return false;
if (!this.material.equals(armorTrim.material)) return false;
return this.pattern.equals(armorTrim.pattern);
}
@Override
public int hashCode() {
return Objects.hash(this.material, this.pattern, this.showInTooltip);
}
}
@@ -0,0 +1,123 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.component.builtin.item;
import com.github.retrooper.packetevents.protocol.color.DyeColor;
import com.github.retrooper.packetevents.protocol.item.banner.BannerPattern;
import com.github.retrooper.packetevents.protocol.item.banner.BannerPatterns;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.List;
import java.util.Objects;
public class BannerLayers {
private List<Layer> layers;
public BannerLayers(List<Layer> layers) {
this.layers = layers;
}
public static BannerLayers read(PacketWrapper<?> wrapper) {
List<Layer> layers = wrapper.readList(Layer::read);
return new BannerLayers(layers);
}
public static void write(PacketWrapper<?> wrapper, BannerLayers patterns) {
wrapper.writeList(patterns.layers, Layer::write);
}
public void addLayer(Layer layer) {
this.layers.add(layer);
}
public List<Layer> getLayers() {
return this.layers;
}
public void setLayers(List<Layer> layers) {
this.layers = layers;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof BannerLayers)) return false;
BannerLayers that = (BannerLayers) obj;
return this.layers.equals(that.layers);
}
@Override
public int hashCode() {
return Objects.hashCode(this.layers);
}
public static class Layer {
private BannerPattern pattern;
private DyeColor color;
public Layer(BannerPattern pattern, DyeColor color) {
this.pattern = pattern;
this.color = color;
}
public static Layer read(PacketWrapper<?> wrapper) {
BannerPattern pattern = wrapper.readMappedEntityOrDirect(
BannerPatterns::getById, BannerPattern::readDirect);
DyeColor color = wrapper.readEnum(DyeColor.values());
return new Layer(pattern, color);
}
public static void write(PacketWrapper<?> wrapper, Layer layer) {
wrapper.writeMappedEntityOrDirect(layer.pattern, BannerPattern::writeDirect);
wrapper.writeEnum(layer.color);
}
public BannerPattern getPattern() {
return this.pattern;
}
public void setPattern(BannerPattern pattern) {
this.pattern = pattern;
}
public DyeColor getColor() {
return this.color;
}
public void setColor(DyeColor color) {
this.color = color;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof Layer)) return false;
Layer layer = (Layer) obj;
if (!this.pattern.equals(layer.pattern)) return false;
return this.color == layer.color;
}
@Override
public int hashCode() {
return Objects.hash(this.pattern, this.color);
}
}
}
@@ -0,0 +1,68 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.component.builtin.item;
import com.github.retrooper.packetevents.protocol.item.ItemStack;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.List;
import java.util.Objects;
public class BundleContents {
private List<ItemStack> items;
public BundleContents(List<ItemStack> items) {
this.items = items;
}
public static BundleContents read(PacketWrapper<?> wrapper) {
List<ItemStack> items = wrapper.readList(PacketWrapper::readPresentItemStack);
return new BundleContents(items);
}
public static void write(PacketWrapper<?> wrapper, BundleContents projectiles) {
wrapper.writeList(projectiles.items, PacketWrapper::writePresentItemStack);
}
public void addItem(ItemStack itemStack) {
this.items.add(itemStack);
}
public List<ItemStack> getItems() {
return this.items;
}
public void setItems(List<ItemStack> items) {
this.items = items;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof BundleContents)) return false;
BundleContents that = (BundleContents) obj;
return this.items.equals(that.items);
}
@Override
public int hashCode() {
return Objects.hashCode(this.items);
}
}
@@ -0,0 +1,68 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.component.builtin.item;
import com.github.retrooper.packetevents.protocol.item.ItemStack;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.List;
import java.util.Objects;
public class ChargedProjectiles {
private List<ItemStack> items;
public ChargedProjectiles(List<ItemStack> items) {
this.items = items;
}
public static ChargedProjectiles read(PacketWrapper<?> wrapper) {
List<ItemStack> items = wrapper.readList(PacketWrapper::readPresentItemStack);
return new ChargedProjectiles(items);
}
public static void write(PacketWrapper<?> wrapper, ChargedProjectiles projectiles) {
wrapper.writeList(projectiles.items, PacketWrapper::writePresentItemStack);
}
public void addItem(ItemStack itemStack) {
this.items.add(itemStack);
}
public List<ItemStack> getItems() {
return this.items;
}
public void setItems(List<ItemStack> items) {
this.items = items;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof ChargedProjectiles)) return false;
ChargedProjectiles that = (ChargedProjectiles) obj;
return this.items.equals(that.items);
}
@Override
public int hashCode() {
return Objects.hashCode(this.items);
}
}
@@ -0,0 +1,93 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.component.builtin.item;
import com.github.retrooper.packetevents.protocol.nbt.NBT;
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
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.Nullable;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
public class DebugStickState {
private Map<StateType, String> properties;
public DebugStickState(Map<StateType, String> properties) {
this.properties = properties;
}
public static DebugStickState read(PacketWrapper<?> wrapper) {
NBTCompound compound = wrapper.readNBT();
Map<StateType, String> properties = new HashMap<>(compound.size());
for (Map.Entry<String, NBT> tag : compound.getTags().entrySet()) {
StateType stateType = StateTypes.getByName(tag.getKey());
String property = ((NBTString) tag.getValue()).getValue();
properties.put(stateType, property);
}
return new DebugStickState(properties);
}
public static void write(PacketWrapper<?> wrapper, DebugStickState state) {
NBTCompound compound = new NBTCompound();
for (Map.Entry<StateType, String> property : state.properties.entrySet()) {
compound.setTag(property.getKey().getName(),
new NBTString(property.getValue()));
}
wrapper.writeNBT(compound);
}
public @Nullable String getProperty(StateType stateType) {
return this.properties.get(stateType);
}
public void setProperty(StateType stateType, @Nullable String property) {
if (property != null) {
this.properties.put(stateType, property);
} else {
this.properties.remove(stateType);
}
}
public Map<StateType, String> getProperties() {
return this.properties;
}
public void setProperties(Map<StateType, String> properties) {
this.properties = properties;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof DebugStickState)) return false;
DebugStickState that = (DebugStickState) o;
return this.properties.equals(that.properties);
}
@Override
public int hashCode() {
return Objects.hashCode(this.properties);
}
}
@@ -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.wrapper.PacketWrapper;
import java.util.List;
import java.util.Objects;
public class FireworkExplosion {
private Shape shape;
private List<Integer> colors;
private List<Integer> fadeColors;
private boolean hasTrail;
private boolean hasTwinkle;
public FireworkExplosion(
Shape shape, List<Integer> colors, List<Integer> fadeColors,
boolean hasTrail, boolean hasTwinkle
) {
this.shape = shape;
this.colors = colors;
this.fadeColors = fadeColors;
this.hasTrail = hasTrail;
this.hasTwinkle = hasTwinkle;
}
public static FireworkExplosion read(PacketWrapper<?> wrapper) {
Shape shape = wrapper.readEnum(Shape.values());
List<Integer> colors = wrapper.readList(PacketWrapper::readInt);
List<Integer> fadeColors = wrapper.readList(PacketWrapper::readInt);
boolean hasTrail = wrapper.readBoolean();
boolean hasTwinkle = wrapper.readBoolean();
return new FireworkExplosion(shape, colors, fadeColors, hasTrail, hasTwinkle);
}
public static void write(PacketWrapper<?> wrapper, FireworkExplosion explosion) {
wrapper.writeEnum(explosion.shape);
wrapper.writeList(explosion.colors, PacketWrapper::writeInt);
wrapper.writeList(explosion.fadeColors, PacketWrapper::writeInt);
wrapper.writeBoolean(explosion.hasTrail);
wrapper.writeBoolean(explosion.hasTwinkle);
}
public Shape getShape() {
return this.shape;
}
public void setShape(Shape shape) {
this.shape = shape;
}
public void addColor(int color) {
this.colors.add(color);
}
public List<Integer> getColors() {
return this.colors;
}
public void setColors(List<Integer> colors) {
this.colors = colors;
}
public void addFadeColor(int color) {
this.fadeColors.add(color);
}
public List<Integer> getFadeColors() {
return this.fadeColors;
}
public void setFadeColors(List<Integer> fadeColors) {
this.fadeColors = fadeColors;
}
public boolean isHasTrail() {
return this.hasTrail;
}
public void setHasTrail(boolean hasTrail) {
this.hasTrail = hasTrail;
}
public boolean isHasTwinkle() {
return this.hasTwinkle;
}
public void setHasTwinkle(boolean hasTwinkle) {
this.hasTwinkle = hasTwinkle;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof FireworkExplosion)) return false;
FireworkExplosion that = (FireworkExplosion) obj;
if (this.hasTrail != that.hasTrail) return false;
if (this.hasTwinkle != that.hasTwinkle) return false;
if (this.shape != that.shape) return false;
if (!this.colors.equals(that.colors)) return false;
return this.fadeColors.equals(that.fadeColors);
}
@Override
public int hashCode() {
return Objects.hash(this.shape, this.colors, this.fadeColors, this.hasTrail, this.hasTwinkle);
}
public enum Shape {
SMALL_BALL,
LARGE_BALL,
STAR,
CREEPER,
BURST,
}
}
@@ -0,0 +1,174 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.component.builtin.item;
import com.github.retrooper.packetevents.protocol.potion.PotionEffect;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.List;
import java.util.Objects;
public class FoodProperties {
private int nutrition;
private float saturation;
private boolean canAlwaysEat;
private float eatSeconds;
private List<PossibleEffect> effects;
public FoodProperties(int nutrition, float saturation, boolean canAlwaysEat, float eatSeconds, List<PossibleEffect> effects) {
this.nutrition = nutrition;
this.saturation = saturation;
this.canAlwaysEat = canAlwaysEat;
this.eatSeconds = eatSeconds;
this.effects = effects;
}
public static FoodProperties read(PacketWrapper<?> wrapper) {
int nutrition = wrapper.readVarInt();
float saturation = wrapper.readFloat();
boolean canAlwaysEat = wrapper.readBoolean();
float eatSeconds = wrapper.readFloat();
List<PossibleEffect> effects = wrapper.readList(PossibleEffect::read);
return new FoodProperties(nutrition, saturation, canAlwaysEat, eatSeconds, effects);
}
public static void write(PacketWrapper<?> wrapper, FoodProperties props) {
wrapper.writeVarInt(props.nutrition);
wrapper.writeFloat(props.saturation);
wrapper.writeBoolean(props.canAlwaysEat);
wrapper.writeFloat(props.eatSeconds);
wrapper.writeList(props.effects, PossibleEffect::write);
}
public int getNutrition() {
return this.nutrition;
}
public void setNutrition(int nutrition) {
this.nutrition = nutrition;
}
public float getSaturation() {
return this.saturation;
}
public void setSaturation(float saturation) {
this.saturation = saturation;
}
public boolean isCanAlwaysEat() {
return this.canAlwaysEat;
}
public void setCanAlwaysEat(boolean canAlwaysEat) {
this.canAlwaysEat = canAlwaysEat;
}
public float getEatSeconds() {
return this.eatSeconds;
}
public void setEatSeconds(float eatSeconds) {
this.eatSeconds = eatSeconds;
}
public void addEffect(PossibleEffect effect) {
this.effects.add(effect);
}
public List<PossibleEffect> getEffects() {
return this.effects;
}
public void setEffects(List<PossibleEffect> effects) {
this.effects = effects;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof FoodProperties)) return false;
FoodProperties that = (FoodProperties) obj;
if (this.nutrition != that.nutrition) return false;
if (Float.compare(that.saturation, this.saturation) != 0) return false;
if (this.canAlwaysEat != that.canAlwaysEat) return false;
if (Float.compare(that.eatSeconds, this.eatSeconds) != 0) return false;
return this.effects.equals(that.effects);
}
@Override
public int hashCode() {
return Objects.hash(this.nutrition, this.saturation, this.canAlwaysEat, this.eatSeconds, this.effects);
}
public static class PossibleEffect {
private PotionEffect effect;
private float probability;
public PossibleEffect(PotionEffect effect, float probability) {
this.effect = effect;
this.probability = probability;
}
public static PossibleEffect read(PacketWrapper<?> wrapper) {
PotionEffect effect = PotionEffect.read(wrapper);
float probability = wrapper.readFloat();
return new PossibleEffect(effect, probability);
}
public static void write(PacketWrapper<?> wrapper, PossibleEffect effect) {
PotionEffect.write(wrapper, effect.effect);
wrapper.writeFloat(effect.probability);
}
public PotionEffect getEffect() {
return this.effect;
}
public void setEffect(PotionEffect effect) {
this.effect = effect;
}
public float getProbability() {
return this.probability;
}
public void setProbability(float probability) {
this.probability = probability;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof PossibleEffect)) return false;
PossibleEffect that = (PossibleEffect) obj;
if (Float.compare(that.probability, this.probability) != 0) return false;
return this.effect.equals(that.effect);
}
@Override
public int hashCode() {
return Objects.hash(this.effect, this.probability);
}
}
}
@@ -0,0 +1,329 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.component.builtin.item;
import com.github.retrooper.packetevents.protocol.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.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;
private boolean showInTooltip;
public ItemAdventurePredicate(List<BlockPredicate> predicates, boolean showInTooltip) {
this.predicates = predicates;
this.showInTooltip = showInTooltip;
}
public static ItemAdventurePredicate read(PacketWrapper<?> wrapper) {
List<BlockPredicate> predicates = wrapper.readList(BlockPredicate::read);
boolean showInTooltip = 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);
}
public void addPredicate(BlockPredicate predicate) {
this.predicates.add(predicate);
}
public List<BlockPredicate> getPredicates() {
return this.predicates;
}
public void setPredicates(List<BlockPredicate> predicates) {
this.predicates = predicates;
}
public boolean isShowInTooltip() {
return this.showInTooltip;
}
public void setShowInTooltip(boolean showInTooltip) {
this.showInTooltip = showInTooltip;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof ItemAdventurePredicate)) return false;
ItemAdventurePredicate that = (ItemAdventurePredicate) obj;
if (this.showInTooltip != that.showInTooltip) return false;
return this.predicates.equals(that.predicates);
}
@Override
public int hashCode() {
return Objects.hash(this.predicates, this.showInTooltip);
}
public static class BlockPredicate {
private @Nullable MappedEntitySet<StateType.Mapped> blocks;
private @Nullable List<PropertyMatcher> properties;
private @Nullable NBTCompound nbt;
public BlockPredicate(
@Nullable MappedEntitySet<StateType.Mapped> blocks,
@Nullable List<PropertyMatcher> properties,
@Nullable NBTCompound nbt
) {
this.blocks = blocks;
this.properties = properties;
this.nbt = nbt;
}
public static BlockPredicate read(PacketWrapper<?> wrapper) {
MappedEntitySet<StateType.Mapped> blocks = wrapper.readOptional(
ew -> MappedEntitySet.read(ew, StateTypes::getMappedById));
List<PropertyMatcher> properties = wrapper.readList(PropertyMatcher::read);
NBTCompound nbt = wrapper.readNBT();
return new BlockPredicate(blocks, properties, nbt);
}
public static void write(PacketWrapper<?> wrapper, BlockPredicate predicate) {
wrapper.writeOptional(predicate.blocks, MappedEntitySet::write);
wrapper.writeOptional(predicate.properties,
(ew, val) -> ew.writeList(val, PropertyMatcher::write));
wrapper.writeOptional(predicate.nbt, PacketWrapper::writeNBT);
}
public @Nullable MappedEntitySet<StateType.Mapped> getBlocks() {
return this.blocks;
}
public void setBlocks(@Nullable MappedEntitySet<StateType.Mapped> blocks) {
this.blocks = blocks;
}
public void addProperty(PropertyMatcher propertyMatcher) {
if (this.properties == null) {
this.properties = new ArrayList<>(4);
}
this.properties.add(propertyMatcher);
}
public @Nullable List<PropertyMatcher> getProperties() {
return this.properties;
}
public void setProperties(@Nullable List<PropertyMatcher> properties) {
this.properties = properties;
}
public @Nullable NBTCompound getNbt() {
return this.nbt;
}
public void setNbt(@Nullable NBTCompound nbt) {
this.nbt = nbt;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof BlockPredicate)) return false;
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);
}
@Override
public int hashCode() {
return Objects.hash(this.blocks, this.properties, this.nbt);
}
}
public static class PropertyMatcher {
private String name;
private ValueMatcher matcher;
public PropertyMatcher(String name, ValueMatcher matcher) {
this.name = name;
this.matcher = matcher;
}
public static PropertyMatcher read(PacketWrapper<?> wrapper) {
String name = wrapper.readString();
ValueMatcher matcher = ValueMatcher.read(wrapper);
return new PropertyMatcher(name, matcher);
}
public static void write(PacketWrapper<?> wrapper, PropertyMatcher matcher) {
wrapper.writeString(matcher.name);
ValueMatcher.write(wrapper, matcher.matcher);
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public ValueMatcher getMatcher() {
return this.matcher;
}
public void setMatcher(ValueMatcher matcher) {
this.matcher = matcher;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof PropertyMatcher)) return false;
PropertyMatcher that = (PropertyMatcher) obj;
if (!this.name.equals(that.name)) return false;
return this.matcher.equals(that.matcher);
}
@Override
public int hashCode() {
return Objects.hash(this.name, this.matcher);
}
}
public interface ValueMatcher {
static ValueMatcher read(PacketWrapper<?> wrapper) {
if (wrapper.readBoolean()) {
return ExactValueMatcher.read(wrapper);
}
return RangedValueMatcher.read(wrapper);
}
static void write(PacketWrapper<?> wrapper, ValueMatcher matcher) {
if (matcher instanceof ExactValueMatcher) {
wrapper.writeBoolean(true);
ExactValueMatcher.write(wrapper, (ExactValueMatcher) matcher);
} else if (matcher instanceof RangedValueMatcher) {
wrapper.writeBoolean(false);
RangedValueMatcher.write(wrapper, (RangedValueMatcher) matcher);
} else {
throw new IllegalArgumentException("Illegal matcher implementation: " + matcher);
}
}
}
public static class ExactValueMatcher implements ValueMatcher {
private String value;
public ExactValueMatcher(String value) {
this.value = value;
}
public static ExactValueMatcher read(PacketWrapper<?> wrapper) {
return new ExactValueMatcher(wrapper.readString());
}
public static void write(PacketWrapper<?> wrapper, ExactValueMatcher matcher) {
wrapper.writeString(matcher.value);
}
public String getValue() {
return this.value;
}
public void setValue(String value) {
this.value = value;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof ExactValueMatcher)) return false;
ExactValueMatcher that = (ExactValueMatcher) obj;
return this.value.equals(that.value);
}
@Override
public int hashCode() {
return Objects.hashCode(this.value);
}
}
public static class RangedValueMatcher implements ValueMatcher {
private @Nullable String minValue;
private @Nullable String maxValue;
public RangedValueMatcher(@Nullable String minValue, @Nullable String maxValue) {
this.minValue = minValue;
this.maxValue = maxValue;
}
public static RangedValueMatcher read(PacketWrapper<?> wrapper) {
String minValue = wrapper.readOptional(PacketWrapper::readString);
String maxValue = wrapper.readOptional(PacketWrapper::readString);
return new RangedValueMatcher(minValue, maxValue);
}
public static void write(PacketWrapper<?> wrapper, RangedValueMatcher matcher) {
wrapper.writeOptional(matcher.minValue, PacketWrapper::writeString);
wrapper.writeOptional(matcher.maxValue, PacketWrapper::writeString);
}
public @Nullable String getMinValue() {
return this.minValue;
}
public void setMinValue(@Nullable String minValue) {
this.minValue = minValue;
}
public @Nullable String getMaxValue() {
return this.maxValue;
}
public void setMaxValue(@Nullable String maxValue) {
this.maxValue = maxValue;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof RangedValueMatcher)) return false;
RangedValueMatcher that = (RangedValueMatcher) obj;
if (!Objects.equals(this.minValue, that.minValue)) return false;
return Objects.equals(this.maxValue, that.maxValue);
}
@Override
public int hashCode() {
return Objects.hash(this.minValue, this.maxValue);
}
}
}
@@ -0,0 +1,264 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.component.builtin.item;
import com.github.retrooper.packetevents.protocol.attribute.Attribute;
import com.github.retrooper.packetevents.protocol.attribute.AttributeOperation;
import com.github.retrooper.packetevents.protocol.attribute.Attributes;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
public class ItemAttributeModifiers {
public static final ItemAttributeModifiers EMPTY = new ItemAttributeModifiers(
Collections.emptyList(), true) {
@Override
public void setShowInTooltip(boolean showInTooltip) {
throw new UnsupportedOperationException();
}
};
private List<ModifierEntry> modifiers;
private boolean showInTooltip;
public ItemAttributeModifiers(List<ModifierEntry> modifiers, boolean showInTooltip) {
this.modifiers = modifiers;
this.showInTooltip = showInTooltip;
}
public static ItemAttributeModifiers read(PacketWrapper<?> wrapper) {
List<ModifierEntry> modifiers = wrapper.readList(ModifierEntry::read);
boolean showInTooltip = 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);
}
public void addModifier(ModifierEntry modifier) {
this.modifiers.add(modifier);
}
public List<ModifierEntry> getModifiers() {
return this.modifiers;
}
public void setModifiers(List<ModifierEntry> modifiers) {
this.modifiers = modifiers;
}
public boolean isShowInTooltip() {
return this.showInTooltip;
}
public void setShowInTooltip(boolean showInTooltip) {
this.showInTooltip = showInTooltip;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof ItemAttributeModifiers)) return false;
ItemAttributeModifiers that = (ItemAttributeModifiers) obj;
if (this.showInTooltip != that.showInTooltip) return false;
return this.modifiers.equals(that.modifiers);
}
@Override
public int hashCode() {
return Objects.hash(this.modifiers, this.showInTooltip);
}
@Override
public String toString() {
return "ItemAttributeModifiers{modifiers=" + this.modifiers + ", showInTooltip=" + this.showInTooltip + '}';
}
public static class ModifierEntry {
private Attribute attribute;
private Modifier modifier;
private EquipmentSlotGroup slotGroup;
public ModifierEntry(Attribute attribute, Modifier modifier, EquipmentSlotGroup slotGroup) {
this.attribute = attribute;
this.modifier = modifier;
this.slotGroup = slotGroup;
}
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);
}
public static void write(PacketWrapper<?> wrapper, ModifierEntry entry) {
wrapper.writeMappedEntity(entry.attribute);
Modifier.write(wrapper, entry.modifier);
wrapper.writeEnum(entry.slotGroup);
}
public Attribute getAttribute() {
return this.attribute;
}
public void setAttribute(Attribute attribute) {
this.attribute = attribute;
}
public Modifier getModifier() {
return this.modifier;
}
public void setModifier(Modifier modifier) {
this.modifier = modifier;
}
public EquipmentSlotGroup getSlotGroup() {
return this.slotGroup;
}
public void setSlotGroup(EquipmentSlotGroup slotGroup) {
this.slotGroup = slotGroup;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof ModifierEntry)) return false;
ModifierEntry that = (ModifierEntry) obj;
if (!this.attribute.equals(that.attribute)) return false;
if (!this.modifier.equals(that.modifier)) return false;
return this.slotGroup == that.slotGroup;
}
@Override
public int hashCode() {
return Objects.hash(this.attribute, this.modifier, this.slotGroup);
}
@Override
public String toString() {
return "ModifierEntry{attribute=" + this.attribute + ", modifier=" + this.modifier + ", slotGroup=" + this.slotGroup + '}';
}
}
public static class Modifier {
private UUID id;
private String name;
private double value;
private AttributeOperation operation;
public Modifier(UUID id, String name, double value, AttributeOperation operation) {
this.id = id;
this.name = name;
this.value = value;
this.operation = operation;
}
public static Modifier read(PacketWrapper<?> wrapper) {
UUID id = wrapper.readUUID();
String name = wrapper.readString();
double value = wrapper.readDouble();
AttributeOperation operation = wrapper.readEnum(AttributeOperation.values());
return new Modifier(id, name, value, operation);
}
public static void write(PacketWrapper<?> wrapper, Modifier modifier) {
wrapper.writeUUID(modifier.id);
wrapper.writeString(modifier.name);
wrapper.writeDouble(modifier.value);
wrapper.writeEnum(modifier.operation);
}
public UUID getId() {
return this.id;
}
public void setId(UUID id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public double getValue() {
return this.value;
}
public void setValue(double value) {
this.value = value;
}
public AttributeOperation getOperation() {
return this.operation;
}
public void setOperation(AttributeOperation operation) {
this.operation = operation;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof Modifier)) return false;
Modifier modifier = (Modifier) obj;
if (Double.compare(modifier.value, this.value) != 0) return false;
if (!this.id.equals(modifier.id)) return false;
if (!this.name.equals(modifier.name)) return false;
return this.operation == modifier.operation;
}
@Override
public int hashCode() {
return Objects.hash(this.id, this.name, this.value, this.operation);
}
@Override
public String toString() {
return "Modifier{id=" + this.id + ", name='" + this.name + '\'' + ", value=" + this.value + ", operation=" + this.operation + '}';
}
}
public enum EquipmentSlotGroup {
ANY,
MAINHAND,
OFFHAND,
HAND,
FEET,
LEGS,
CHEST,
HEAD,
ARMOR,
BODY,
}
}
@@ -0,0 +1,133 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.component.builtin.item;
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.List;
import java.util.Objects;
public class ItemBees {
private List<BeeEntry> bees;
public ItemBees(List<BeeEntry> bees) {
this.bees = bees;
}
public static ItemBees read(PacketWrapper<?> wrapper) {
List<BeeEntry> bees = wrapper.readList(BeeEntry::read);
return new ItemBees(bees);
}
public static void write(PacketWrapper<?> wrapper, ItemBees bees) {
wrapper.writeList(bees.bees, BeeEntry::write);
}
public void addBee(BeeEntry bee) {
this.bees.add(bee);
}
public List<BeeEntry> getBees() {
return this.bees;
}
public void setBees(List<BeeEntry> bees) {
this.bees = bees;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof ItemBees)) return false;
ItemBees itemBees = (ItemBees) obj;
return this.bees.equals(itemBees.bees);
}
@Override
public int hashCode() {
return Objects.hashCode(this.bees);
}
public static class BeeEntry {
private NBTCompound entityData;
private int ticksInHive;
private int minTicksInHive;
public BeeEntry(NBTCompound entityData, int ticksInHive, int minTicksInHive) {
this.entityData = entityData;
this.ticksInHive = ticksInHive;
this.minTicksInHive = minTicksInHive;
}
public static BeeEntry read(PacketWrapper<?> wrapper) {
NBTCompound entityData = wrapper.readNBT();
int ticksInHive = wrapper.readVarInt();
int minTicksInHive = wrapper.readVarInt();
return new BeeEntry(entityData, ticksInHive, minTicksInHive);
}
public static void write(PacketWrapper<?> wrapper, BeeEntry bee) {
wrapper.writeNBT(bee.entityData);
wrapper.writeVarInt(bee.ticksInHive);
wrapper.writeVarInt(bee.minTicksInHive);
}
public NBTCompound getEntityData() {
return this.entityData;
}
public void setEntityData(NBTCompound entityData) {
this.entityData = entityData;
}
public int getTicksInHive() {
return this.ticksInHive;
}
public void setTicksInHive(int ticksInHive) {
this.ticksInHive = ticksInHive;
}
public int getMinTicksInHive() {
return this.minTicksInHive;
}
public void setMinTicksInHive(int minTicksInHive) {
this.minTicksInHive = minTicksInHive;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof BeeEntry)) return false;
BeeEntry beeEntry = (BeeEntry) obj;
if (this.ticksInHive != beeEntry.ticksInHive) return false;
if (this.minTicksInHive != beeEntry.minTicksInHive) return false;
return this.entityData.equals(beeEntry.entityData);
}
@Override
public int hashCode() {
return Objects.hash(this.entityData, this.ticksInHive, this.minTicksInHive);
}
}
}
@@ -0,0 +1,100 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.component.builtin.item;
import com.github.retrooper.packetevents.protocol.world.states.type.StateValue;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
import java.util.Objects;
public class ItemBlockStateProperties {
private Map<String, String> properties;
public ItemBlockStateProperties(Map<String, String> properties) {
this.properties = properties;
}
public static ItemBlockStateProperties read(PacketWrapper<?> wrapper) {
Map<String, String> properties = wrapper.readMap(
PacketWrapper::readString, PacketWrapper::readString);
return new ItemBlockStateProperties(properties);
}
public static void write(PacketWrapper<?> wrapper, ItemBlockStateProperties props) {
wrapper.writeMap(props.properties,
PacketWrapper::writeString,
PacketWrapper::writeString);
}
public @Nullable Object getProperty(StateValue stateValue) {
String value = this.getProperty(stateValue.getName());
if (value != null) {
return stateValue.getParser().apply(value);
}
return null;
}
public @Nullable String getProperty(String key) {
return this.properties.get(key);
}
public void setProperty(StateValue stateValue, @Nullable Object value) {
this.setProperty(stateValue.getName(), value == null ? null : value.toString());
}
public void setProperty(String key, @Nullable String value) {
if (value == null) {
this.properties.remove(key);
} else {
this.properties.put(key, value);
}
}
public void unsetProperty(StateValue stateValue) {
this.unsetProperty(stateValue.getName());
}
public void unsetProperty(String key) {
this.setProperty(key, null);
}
public Map<String, String> getProperties() {
return this.properties;
}
public void setProperties(Map<String, String> properties) {
this.properties = properties;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof ItemBlockStateProperties)) return false;
ItemBlockStateProperties that = (ItemBlockStateProperties) obj;
return this.properties.equals(that.properties);
}
@Override
public int hashCode() {
return Objects.hashCode(this.properties);
}
}
@@ -0,0 +1,68 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.component.builtin.item;
import com.github.retrooper.packetevents.protocol.item.ItemStack;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.List;
import java.util.Objects;
public class ItemContainerContents {
private List<ItemStack> items;
public ItemContainerContents(List<ItemStack> items) {
this.items = items;
}
public static ItemContainerContents read(PacketWrapper<?> wrapper) {
List<ItemStack> items = wrapper.readList(PacketWrapper::readItemStack);
return new ItemContainerContents(items);
}
public static void write(PacketWrapper<?> wrapper, ItemContainerContents contents) {
wrapper.writeList(contents.items, PacketWrapper::writeItemStack);
}
public void addItem(ItemStack itemStack) {
this.items.add(itemStack);
}
public List<ItemStack> getItems() {
return this.items;
}
public void setItems(List<ItemStack> items) {
this.items = items;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof ItemContainerContents)) return false;
ItemContainerContents that = (ItemContainerContents) obj;
return this.items.equals(that.items);
}
@Override
public int hashCode() {
return Objects.hashCode(this.items);
}
}
@@ -0,0 +1,86 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.component.builtin.item;
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
import com.github.retrooper.packetevents.protocol.nbt.NBTLong;
import com.github.retrooper.packetevents.protocol.nbt.NBTNumber;
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
import com.github.retrooper.packetevents.resources.ResourceLocation;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.Objects;
public class ItemContainerLoot {
private ResourceLocation lootTable;
private long seed;
public ItemContainerLoot(ResourceLocation lootTable, long seed) {
this.lootTable = lootTable;
this.seed = seed;
}
public static ItemContainerLoot read(PacketWrapper<?> wrapper) {
NBTCompound compound = wrapper.readNBT();
ResourceLocation lootTable = new ResourceLocation(compound.getStringTagValueOrThrow("loot_table"));
NBTNumber seedTag = compound.getNumberTagOrNull("seed");
long seed = seedTag == null ? 0L : seedTag.getAsLong();
return new ItemContainerLoot(lootTable, seed);
}
public static void write(PacketWrapper<?> wrapper, ItemContainerLoot loot) {
NBTCompound compound = new NBTCompound();
compound.setTag("loot_table", new NBTString(loot.lootTable.toString()));
if (loot.seed != 0L) {
compound.setTag("seed", new NBTLong(loot.seed));
}
wrapper.writeNBT(compound);
}
public ResourceLocation getLootTable() {
return this.lootTable;
}
public void setLootTable(ResourceLocation lootTable) {
this.lootTable = lootTable;
}
public long getSeed() {
return this.seed;
}
public void setSeed(long seed) {
this.seed = seed;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof ItemContainerLoot)) return false;
ItemContainerLoot that = (ItemContainerLoot) obj;
if (this.seed != that.seed) return false;
return this.lootTable.equals(that.lootTable);
}
@Override
public int hashCode() {
return Objects.hash(this.lootTable, this.seed);
}
}
@@ -0,0 +1,75 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.component.builtin.item;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.Objects;
public class ItemDyeColor {
private int rgb;
private boolean showInTooltip;
public ItemDyeColor(int rgb, boolean showInTooltip) {
this.rgb = rgb;
this.showInTooltip = showInTooltip;
}
public static ItemDyeColor read(PacketWrapper<?> wrapper) {
int rgb = wrapper.readInt();
boolean showInTooltip = wrapper.readBoolean();
return new ItemDyeColor(rgb, showInTooltip);
}
public static void write(PacketWrapper<?> wrapper, ItemDyeColor color) {
wrapper.writeInt(color.rgb);
wrapper.writeBoolean(color.showInTooltip);
}
public int getRgb() {
return this.rgb;
}
public void setRgb(int rgb) {
this.rgb = rgb;
}
public boolean isShowInTooltip() {
return this.showInTooltip;
}
public void setShowInTooltip(boolean showInTooltip) {
this.showInTooltip = showInTooltip;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof ItemDyeColor)) return false;
ItemDyeColor that = (ItemDyeColor) obj;
if (this.rgb != that.rgb) return false;
return this.showInTooltip == that.showInTooltip;
}
@Override
public int hashCode() {
return Objects.hash(this.rgb, this.showInTooltip);
}
}
@@ -0,0 +1,127 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.component.builtin.item;
import com.github.retrooper.packetevents.protocol.item.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 java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
public class ItemEnchantments implements Iterable<Map.Entry<EnchantmentType, Integer>> {
public static final ItemEnchantments EMPTY = new ItemEnchantments(
Collections.emptyMap(), true) {
@Override
public void setShowInTooltip(boolean showInTooltip) {
throw new UnsupportedOperationException();
}
};
private Map<EnchantmentType, Integer> enchantments;
private boolean showInTooltip;
public ItemEnchantments(Map<EnchantmentType, Integer> enchantments, boolean showInTooltip) {
this.enchantments = Collections.unmodifiableMap(enchantments);
this.showInTooltip = showInTooltip;
}
public static ItemEnchantments read(PacketWrapper<?> wrapper) {
ClientVersion version = wrapper.getServerVersion().toClientVersion();
Map<EnchantmentType, Integer> enchantments = wrapper.readMap(
ew -> EnchantmentTypes.getById(version, ew.readVarInt()),
PacketWrapper::readVarInt
);
boolean showInTooltip = wrapper.readBoolean();
return new ItemEnchantments(enchantments, showInTooltip);
}
public static void write(PacketWrapper<?> wrapper, ItemEnchantments enchantments) {
ClientVersion version = wrapper.getServerVersion().toClientVersion();
wrapper.writeMap(enchantments.getEnchantments(),
(ew, enchantment) -> ew.writeVarInt(enchantment.getId(version)),
PacketWrapper::writeVarInt
);
wrapper.writeBoolean(enchantments.isShowInTooltip());
}
public int getEnchantmentLevel(EnchantmentType enchantment) {
return this.enchantments.getOrDefault(enchantment, 0);
}
public void setEnchantmentLevel(EnchantmentType enchantment, int level) {
if (level == 0) {
this.enchantments.remove(enchantment);
} else {
this.enchantments.put(enchantment, level);
}
}
public boolean isEmpty() {
return this.getEnchantmentCount() < 1;
}
public int getEnchantmentCount() {
return this.enchantments.size();
}
public Map<EnchantmentType, Integer> getEnchantments() {
return this.enchantments;
}
public void setEnchantments(Map<EnchantmentType, Integer> enchantments) {
this.enchantments = enchantments;
}
public boolean isShowInTooltip() {
return this.showInTooltip;
}
public void setShowInTooltip(boolean showInTooltip) {
this.showInTooltip = showInTooltip;
}
@Override
public Iterator<Map.Entry<EnchantmentType, Integer>> iterator() {
return this.enchantments.entrySet().iterator();
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof ItemEnchantments)) return false;
ItemEnchantments that = (ItemEnchantments) obj;
if (this.showInTooltip != that.showInTooltip) return false;
return this.enchantments.equals(that.enchantments);
}
@Override
public int hashCode() {
return Objects.hash(this.enchantments, this.showInTooltip);
}
@Override
public String toString() {
return "ItemEnchantments{enchantments=" + this.enchantments + ", showInTooltip=" + this.showInTooltip + '}';
}
}
@@ -0,0 +1,80 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.component.builtin.item;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.List;
import java.util.Objects;
public class ItemFireworks {
private int flightDuration;
private List<FireworkExplosion> explosions;
public ItemFireworks(int flightDuration, List<FireworkExplosion> explosions) {
this.flightDuration = flightDuration;
this.explosions = explosions;
}
public static ItemFireworks read(PacketWrapper<?> wrapper) {
int flightDuration = wrapper.readVarInt();
List<FireworkExplosion> explosions = wrapper.readList(FireworkExplosion::read);
return new ItemFireworks(flightDuration, explosions);
}
public static void write(PacketWrapper<?> wrapper, ItemFireworks fireworks) {
wrapper.writeVarInt(fireworks.flightDuration);
wrapper.writeList(fireworks.explosions, FireworkExplosion::write);
}
public int getFlightDuration() {
return this.flightDuration;
}
public void setFlightDuration(int flightDuration) {
this.flightDuration = flightDuration;
}
public void addExplosion(FireworkExplosion explosion) {
this.explosions.add(explosion);
}
public List<FireworkExplosion> getExplosions() {
return this.explosions;
}
public void setExplosions(List<FireworkExplosion> explosions) {
this.explosions = explosions;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof ItemFireworks)) return false;
ItemFireworks that = (ItemFireworks) obj;
if (this.flightDuration != that.flightDuration) return false;
return this.explosions.equals(that.explosions);
}
@Override
public int hashCode() {
return Objects.hash(this.flightDuration, this.explosions);
}
}
@@ -0,0 +1,63 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.component.builtin.item;
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.Objects;
public class ItemLock {
private String code;
public ItemLock(String code) {
this.code = code;
}
public static ItemLock read(PacketWrapper<?> wrapper) {
NBTString codeTag = (NBTString) wrapper.readNBTRaw();
return new ItemLock(codeTag.getValue());
}
public static void write(PacketWrapper<?> wrapper, ItemLock lock) {
wrapper.writeNBTRaw(new NBTString(lock.code));
}
public String getCode() {
return this.code;
}
public void setCode(String code) {
this.code = code;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof ItemLock)) return false;
ItemLock itemLock = (ItemLock) obj;
return this.code.equals(itemLock.code);
}
@Override
public int hashCode() {
return Objects.hashCode(this.code);
}
}
@@ -0,0 +1,76 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.component.builtin.item;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import net.kyori.adventure.text.Component;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
public class ItemLore {
public static final ItemLore EMPTY = new ItemLore(Collections.emptyList());
private List<Component> lines;
public ItemLore(List<Component> lines) {
this.lines = lines;
}
public static ItemLore read(PacketWrapper<?> wrapper) {
List<Component> lines = wrapper.readList(PacketWrapper::readComponent);
return new ItemLore(lines);
}
public static void write(PacketWrapper<?> wrapper, ItemLore lore) {
wrapper.writeList(lore.lines, PacketWrapper::writeComponent);
}
public void addLine(Component line) {
this.lines.add(line);
}
public List<Component> getLines() {
return this.lines;
}
public void setLines(List<Component> lines) {
this.lines = lines;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof ItemLore)) return false;
ItemLore itemLore = (ItemLore) obj;
return this.lines.equals(itemLore.lines);
}
@Override
public int hashCode() {
return Objects.hash(this.lines);
}
@Override
public String toString() {
return "ItemLore{lines=" + this.lines + '}';
}
}
@@ -0,0 +1,176 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.component.builtin.item;
import com.github.retrooper.packetevents.protocol.item.mapdecoration.MapDecorationType;
import com.github.retrooper.packetevents.protocol.item.mapdecoration.MapDecorationTypes;
import com.github.retrooper.packetevents.protocol.nbt.NBT;
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
import com.github.retrooper.packetevents.protocol.nbt.NBTDouble;
import com.github.retrooper.packetevents.protocol.nbt.NBTFloat;
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
public class ItemMapDecorations {
private Map<String, Decoration> decorations;
public ItemMapDecorations(Map<String, Decoration> decorations) {
this.decorations = decorations;
}
public static ItemMapDecorations read(PacketWrapper<?> wrapper) {
NBTCompound compound = wrapper.readNBT();
Map<String, Decoration> decorations = new HashMap<>(compound.size());
for (Map.Entry<String, NBT> tag : compound.getTags().entrySet()) {
Decoration decoration = Decoration.readCompound((NBTCompound) tag.getValue());
decorations.put(tag.getKey(), decoration);
}
return new ItemMapDecorations(decorations);
}
public static void write(PacketWrapper<?> wrapper, ItemMapDecorations decorations) {
NBTCompound compound = new NBTCompound();
for (Map.Entry<String, Decoration> decoration : decorations.decorations.entrySet()) {
NBTCompound entry = new NBTCompound();
Decoration.writeCompound(entry, decoration.getValue());
compound.setTag(decoration.getKey(), entry);
}
wrapper.writeNBT(compound);
}
public @Nullable Decoration getDecoration(String key) {
return this.decorations.get(key);
}
public void setDecoration(String key, @Nullable Decoration decoration) {
if (decoration != null) {
this.decorations.put(key, decoration);
} else {
this.decorations.remove(key);
}
}
public Map<String, Decoration> getDecorations() {
return this.decorations;
}
public void setDecorations(Map<String, Decoration> decorations) {
this.decorations = decorations;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof ItemMapDecorations)) return false;
ItemMapDecorations that = (ItemMapDecorations) obj;
return this.decorations.equals(that.decorations);
}
@Override
public int hashCode() {
return Objects.hashCode(this.decorations);
}
public static final class Decoration {
private MapDecorationType type;
private double x;
private double z;
private float rotation;
public Decoration(MapDecorationType type, double x, double z, float rotation) {
this.type = type;
this.x = x;
this.z = z;
this.rotation = rotation;
}
@ApiStatus.Internal
public static Decoration readCompound(NBTCompound compound) {
MapDecorationType type = MapDecorationTypes.getByName(compound.getStringTagValueOrThrow("type"));
double x = compound.getNumberTagOrThrow("x").getAsDouble();
double z = compound.getNumberTagOrThrow("z").getAsDouble();
float rotation = compound.getNumberTagOrThrow("rotation").getAsFloat();
return new Decoration(type, x, z, rotation);
}
@ApiStatus.Internal
public static void writeCompound(NBTCompound compound, Decoration decoration) {
compound.setTag("type", new NBTString(decoration.type.getName().toString()));
compound.setTag("x", new NBTDouble(decoration.x));
compound.setTag("z", new NBTDouble(decoration.z));
compound.setTag("float", new NBTFloat(decoration.rotation));
}
public MapDecorationType getType() {
return this.type;
}
public void setType(MapDecorationType type) {
this.type = type;
}
public double getX() {
return this.x;
}
public void setX(double x) {
this.x = x;
}
public double getZ() {
return this.z;
}
public void setZ(double z) {
this.z = z;
}
public float getRotation() {
return this.rotation;
}
public void setRotation(float rotation) {
this.rotation = rotation;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof Decoration)) return false;
Decoration that = (Decoration) obj;
if (Double.compare(that.x, this.x) != 0) return false;
if (Double.compare(that.z, this.z) != 0) return false;
if (Float.compare(that.rotation, this.rotation) != 0) return false;
return this.type.equals(that.type);
}
@Override
public int hashCode() {
return Objects.hash(this.type, this.x, this.z, this.rotation);
}
}
}
@@ -0,0 +1,24 @@
/*
* 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;
public enum ItemMapPostProcessingState {
LOCKED,
SCALED,
}
@@ -0,0 +1,101 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.component.builtin.item;
import com.github.retrooper.packetevents.protocol.potion.Potion;
import com.github.retrooper.packetevents.protocol.potion.PotionEffect;
import com.github.retrooper.packetevents.protocol.potion.Potions;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Objects;
public class ItemPotionContents {
private @Nullable Potion potion;
private @Nullable Integer customColor;
private List<PotionEffect> customEffects;
public ItemPotionContents(
@Nullable Potion potion,
@Nullable Integer customColor,
List<PotionEffect> customEffects
) {
this.potion = potion;
this.customColor = customColor;
this.customEffects = customEffects;
}
public static ItemPotionContents read(PacketWrapper<?> wrapper) {
Potion potionId = wrapper.readOptional(ew -> ew.readMappedEntity(Potions::getById));
Integer customColor = wrapper.readOptional(PacketWrapper::readInt);
List<PotionEffect> customEffects = wrapper.readList(PotionEffect::read);
return new ItemPotionContents(potionId, customColor, customEffects);
}
public static void write(PacketWrapper<?> wrapper, ItemPotionContents contents) {
wrapper.writeOptional(contents.potion, PacketWrapper::writeMappedEntity);
wrapper.writeOptional(contents.customColor, PacketWrapper::writeInt);
wrapper.writeList(contents.customEffects, PotionEffect::write);
}
public @Nullable Potion getPotion() {
return this.potion;
}
public void setPotion(@Nullable Potion potion) {
this.potion = potion;
}
public @Nullable Integer getCustomColor() {
return this.customColor;
}
public void setCustomColor(@Nullable Integer customColor) {
this.customColor = customColor;
}
private void addCustomEffect(PotionEffect effect) {
this.customEffects.add(effect);
}
public List<PotionEffect> getCustomEffects() {
return this.customEffects;
}
public void setCustomEffects(List<PotionEffect> customEffects) {
this.customEffects = customEffects;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof ItemPotionContents)) return false;
ItemPotionContents that = (ItemPotionContents) obj;
if (!Objects.equals(this.potion, that.potion)) return false;
if (!Objects.equals(this.customColor, that.customColor)) return false;
return this.customEffects.equals(that.customEffects);
}
@Override
public int hashCode() {
return Objects.hash(this.potion, this.customColor, this.customEffects);
}
}
@@ -0,0 +1,165 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.component.builtin.item;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
public class ItemProfile {
private @Nullable String name;
private @Nullable UUID id;
private List<Property> properties;
public ItemProfile(
@Nullable String name,
@Nullable UUID id,
List<Property> properties
) {
this.name = name;
this.id = id;
this.properties = properties;
}
public static ItemProfile read(PacketWrapper<?> wrapper) {
String name = wrapper.readOptional(ew -> ew.readString(16));
UUID id = wrapper.readOptional(PacketWrapper::readUUID);
List<Property> properties = wrapper.readList(Property::read);
return new ItemProfile(name, id, properties);
}
public static void write(PacketWrapper<?> wrapper, ItemProfile profile) {
wrapper.writeOptional(profile.name, (ew, name) -> ew.writeString(name, 16));
wrapper.writeOptional(profile.id, PacketWrapper::writeUUID);
wrapper.writeList(profile.properties, Property::write);
}
public @Nullable String getName() {
return this.name;
}
public void setName(@Nullable String name) {
this.name = name;
}
public @Nullable UUID getId() {
return this.id;
}
public void setId(@Nullable UUID id) {
this.id = id;
}
public void addProperty(Property property) {
this.properties.add(property);
}
public List<Property> getProperties() {
return this.properties;
}
public void setProperties(List<Property> properties) {
this.properties = properties;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof ItemProfile)) return false;
ItemProfile that = (ItemProfile) obj;
if (!Objects.equals(this.name, that.name)) return false;
if (!Objects.equals(this.id, that.id)) return false;
return this.properties.equals(that.properties);
}
@Override
public int hashCode() {
return Objects.hash(this.name, this.id, this.properties);
}
public static class Property {
private String name;
private String value;
private @Nullable String signature;
public Property(String name, String value, @Nullable String signature) {
this.name = name;
this.value = value;
this.signature = signature;
}
public static Property read(PacketWrapper<?> wrapper) {
String name = wrapper.readString(64);
String value = wrapper.readString(32767);
String signature = wrapper.readOptional(ew -> ew.readString(1024));
return new Property(name, value, signature);
}
public static void write(PacketWrapper<?> wrapper, Property property) {
wrapper.writeString(property.name, 64);
wrapper.writeString(property.value, 32767);
wrapper.writeOptional(property.signature,
(ew, signature) -> ew.writeString(signature, 1024));
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return this.value;
}
public void setValue(String value) {
this.value = value;
}
public @Nullable String getSignature() {
return this.signature;
}
public void setSignature(@Nullable String signature) {
this.signature = signature;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof Property)) return false;
Property property = (Property) obj;
if (!this.name.equals(property.name)) return false;
if (!this.value.equals(property.value)) return false;
return Objects.equals(this.signature, property.signature);
}
@Override
public int hashCode() {
return Objects.hash(this.name, this.value, this.signature);
}
}
}
@@ -0,0 +1,26 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.component.builtin.item;
public enum ItemRarity {
COMMON,
UNCOMMON,
RARE,
EPIC,
}
@@ -0,0 +1,72 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.component.builtin.item;
import com.github.retrooper.packetevents.resources.ResourceLocation;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.List;
import java.util.Objects;
public class ItemRecipes {
private List<ResourceLocation> recipes;
public ItemRecipes(List<ResourceLocation> recipes) {
this.recipes = recipes;
}
public static ItemRecipes read(PacketWrapper<?> wrapper) {
List<ResourceLocation> recipes = wrapper.readList(PacketWrapper::readIdentifier);
return new ItemRecipes(recipes);
}
public static void write(PacketWrapper<?> wrapper, ItemRecipes recipes) {
wrapper.writeList(recipes.recipes, PacketWrapper::writeIdentifier);
}
public void addRecipe(ResourceLocation recipeKey) {
this.recipes.add(recipeKey);
}
public void removeRecipe(ResourceLocation recipeKey) {
this.recipes.remove(recipeKey);
}
public List<ResourceLocation> getRecipes() {
return this.recipes;
}
public void setRecipes(List<ResourceLocation> recipes) {
this.recipes = recipes;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof ItemRecipes)) return false;
ItemRecipes that = (ItemRecipes) obj;
return this.recipes.equals(that.recipes);
}
@Override
public int hashCode() {
return Objects.hashCode(this.recipes);
}
}
@@ -0,0 +1,166 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.component.builtin.item;
import com.github.retrooper.packetevents.protocol.mapper.MappedEntitySet;
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.Nullable;
import java.util.List;
import java.util.Objects;
public class ItemTool {
private List<Rule> rules;
private float defaultMiningSpeed;
private int damagePerBlock;
public ItemTool(List<Rule> rules, float defaultMiningSpeed, int damagePerBlock) {
this.rules = rules;
this.defaultMiningSpeed = defaultMiningSpeed;
this.damagePerBlock = damagePerBlock;
}
public static ItemTool read(PacketWrapper<?> wrapper) {
List<Rule> rules = wrapper.readList(Rule::read);
float defaultMiningSpeed = wrapper.readFloat();
int damagePerBlock = wrapper.readVarInt();
return new ItemTool(rules, defaultMiningSpeed, damagePerBlock);
}
public static void write(PacketWrapper<?> wrapper, ItemTool tool) {
wrapper.writeList(tool.rules, Rule::write);
wrapper.writeFloat(tool.defaultMiningSpeed);
wrapper.writeVarInt(tool.damagePerBlock);
}
public void addRule(Rule rule) {
this.rules.add(rule);
}
public List<Rule> getRules() {
return this.rules;
}
public void setRules(List<Rule> rules) {
this.rules = rules;
}
public float getDefaultMiningSpeed() {
return this.defaultMiningSpeed;
}
public void setDefaultMiningSpeed(float defaultMiningSpeed) {
this.defaultMiningSpeed = defaultMiningSpeed;
}
public int getDamagePerBlock() {
return this.damagePerBlock;
}
public void setDamagePerBlock(int damagePerBlock) {
this.damagePerBlock = damagePerBlock;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof ItemTool)) return false;
ItemTool itemTool = (ItemTool) obj;
if (Float.compare(itemTool.defaultMiningSpeed, this.defaultMiningSpeed) != 0) return false;
if (this.damagePerBlock != itemTool.damagePerBlock) return false;
return this.rules.equals(itemTool.rules);
}
@Override
public int hashCode() {
return Objects.hash(this.rules, this.defaultMiningSpeed, this.damagePerBlock);
}
public static class Rule {
private MappedEntitySet<StateType.Mapped> blocks;
private @Nullable Float speed;
private @Nullable Boolean correctForDrops;
public Rule(
MappedEntitySet<StateType.Mapped> blocks,
@Nullable Float speed,
@Nullable Boolean correctForDrops
) {
this.blocks = blocks;
this.speed = speed;
this.correctForDrops = correctForDrops;
}
public static Rule read(PacketWrapper<?> wrapper) {
MappedEntitySet<StateType.Mapped> blocks = MappedEntitySet.read(wrapper, StateTypes::getMappedById);
Float speed = wrapper.readOptional(PacketWrapper::readFloat);
Boolean correctForDrops = wrapper.readOptional(PacketWrapper::readBoolean);
return new Rule(blocks, speed, correctForDrops);
}
public static void write(PacketWrapper<?> wrapper, Rule rule) {
MappedEntitySet.write(wrapper, rule.blocks);
wrapper.writeOptional(rule.speed, PacketWrapper::writeFloat);
wrapper.writeOptional(rule.correctForDrops, PacketWrapper::writeBoolean);
}
public MappedEntitySet<StateType.Mapped> getBlocks() {
return this.blocks;
}
public void setBlocks(MappedEntitySet<StateType.Mapped> blocks) {
this.blocks = blocks;
}
public @Nullable Float getSpeed() {
return this.speed;
}
public void setSpeed(@Nullable Float speed) {
this.speed = speed;
}
public @Nullable Boolean getCorrectForDrops() {
return this.correctForDrops;
}
public void setCorrectForDrops(@Nullable Boolean correctForDrops) {
this.correctForDrops = correctForDrops;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof Rule)) return false;
Rule rule = (Rule) obj;
if (!this.blocks.equals(rule.blocks)) return false;
if (!Objects.equals(this.speed, rule.speed)) return false;
return Objects.equals(this.correctForDrops, rule.correctForDrops);
}
@Override
public int hashCode() {
return Objects.hash(this.blocks, this.speed, this.correctForDrops);
}
}
}
@@ -0,0 +1,77 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.component.builtin.item;
import com.github.retrooper.packetevents.protocol.world.WorldBlockPosition;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
public class LodestoneTracker {
private @Nullable WorldBlockPosition target;
private boolean tracked;
public LodestoneTracker(@Nullable WorldBlockPosition target, boolean tracked) {
this.target = target;
this.tracked = tracked;
}
public static LodestoneTracker read(PacketWrapper<?> wrapper) {
WorldBlockPosition target = wrapper.readOptional(PacketWrapper::readWorldBlockPosition);
boolean tracked = wrapper.readBoolean();
return new LodestoneTracker(target, tracked);
}
public static void write(PacketWrapper<?> wrapper, LodestoneTracker tracker) {
wrapper.writeOptional(tracker.target, PacketWrapper::writeWorldBlockPosition);
wrapper.writeBoolean(tracker.tracked);
}
public @Nullable WorldBlockPosition getTarget() {
return this.target;
}
public void setTarget(@Nullable WorldBlockPosition target) {
this.target = target;
}
public boolean isTracked() {
return this.tracked;
}
public void setTracked(boolean tracked) {
this.tracked = tracked;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof LodestoneTracker)) return false;
LodestoneTracker that = (LodestoneTracker) obj;
if (this.tracked != that.tracked) return false;
return Objects.equals(this.target, that.target);
}
@Override
public int hashCode() {
return Objects.hash(this.target, this.tracked);
}
}
@@ -0,0 +1,125 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.component.builtin.item;
import com.github.retrooper.packetevents.protocol.item.type.ItemType;
import com.github.retrooper.packetevents.protocol.item.type.ItemTypes;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Queue;
public class PotDecorations {
private @Nullable ItemType back;
private @Nullable ItemType left;
private @Nullable ItemType right;
private @Nullable ItemType front;
private PotDecorations(Queue<ItemType> items) {
this(items.poll(), items.poll(), items.poll(), items.poll());
}
public PotDecorations(
@Nullable ItemType back,
@Nullable ItemType left,
@Nullable ItemType right,
@Nullable ItemType front
) {
this.back = back;
this.left = left;
this.right = right;
this.front = front;
}
private List<ItemType> asList() {
return Arrays.asList(this.back, this.left, this.right, this.front);
}
private static @Nullable ItemType readItem(PacketWrapper<?> wrapper) {
ItemType type = wrapper.readMappedEntity(ItemTypes::getById);
return type == ItemTypes.BRICK ? null : type;
}
public static PotDecorations read(PacketWrapper<?> wrapper) {
Queue<ItemType> items = wrapper.<ItemType, Queue<ItemType>>readCollection(
ArrayDeque::new, PotDecorations::readItem);
return new PotDecorations(items);
}
private static void writeItem(PacketWrapper<?> wrapper, @Nullable ItemType type) {
wrapper.writeMappedEntity(type == null ? ItemTypes.BRICK : type);
}
public static void write(PacketWrapper<?> wrapper, PotDecorations decorations) {
wrapper.writeList(decorations.asList(), PotDecorations::writeItem);
}
public @Nullable ItemType getBack() {
return this.back;
}
public void setBack(@Nullable ItemType back) {
this.back = back;
}
public @Nullable ItemType getLeft() {
return this.left;
}
public void setLeft(@Nullable ItemType left) {
this.left = left;
}
public @Nullable ItemType getRight() {
return this.right;
}
public void setRight(@Nullable ItemType right) {
this.right = right;
}
public @Nullable ItemType getFront() {
return this.front;
}
public void setFront(@Nullable ItemType front) {
this.front = front;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof PotDecorations)) return false;
PotDecorations that = (PotDecorations) obj;
if (!Objects.equals(this.back, that.back)) return false;
if (!Objects.equals(this.left, that.left)) return false;
if (!Objects.equals(this.right, that.right)) return false;
return Objects.equals(this.front, that.front);
}
@Override
public int hashCode() {
return Objects.hash(this.back, this.left, this.right, this.front);
}
}
@@ -0,0 +1,121 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.component.builtin.item;
import com.github.retrooper.packetevents.protocol.potion.PotionType;
import com.github.retrooper.packetevents.protocol.potion.PotionTypes;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import java.util.List;
import java.util.Objects;
public class SuspiciousStewEffects {
private List<EffectEntry> effects;
public SuspiciousStewEffects(List<EffectEntry> effects) {
this.effects = effects;
}
public static SuspiciousStewEffects read(PacketWrapper<?> wrapper) {
List<EffectEntry> effects = wrapper.readList(EffectEntry::read);
return new SuspiciousStewEffects(effects);
}
public static void write(PacketWrapper<?> wrapper, SuspiciousStewEffects effects) {
wrapper.writeList(effects.effects, EffectEntry::write);
}
public void addEffect(EffectEntry effect) {
this.effects.add(effect);
}
public List<EffectEntry> getEffects() {
return this.effects;
}
public void setEffects(List<EffectEntry> effects) {
this.effects = effects;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof SuspiciousStewEffects)) return false;
SuspiciousStewEffects that = (SuspiciousStewEffects) obj;
return this.effects.equals(that.effects);
}
@Override
public int hashCode() {
return Objects.hashCode(this.effects);
}
public static class EffectEntry {
private PotionType type;
private int duration;
public EffectEntry(PotionType type, int duration) {
this.type = type;
this.duration = duration;
}
public static EffectEntry read(PacketWrapper<?> wrapper) {
PotionType type = wrapper.readMappedEntity(PotionTypes::getById);
int duration = wrapper.readVarInt();
return new EffectEntry(type, duration);
}
public static void write(PacketWrapper<?> wrapper, EffectEntry effect) {
wrapper.writeMappedEntity(effect.type);
wrapper.writeVarInt(effect.duration);
}
public PotionType getType() {
return this.type;
}
public void setType(PotionType type) {
this.type = type;
}
public int getDuration() {
return this.duration;
}
public void setDuration(int duration) {
this.duration = duration;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof EffectEntry)) return false;
EffectEntry that = (EffectEntry) obj;
if (this.duration != that.duration) return false;
return this.type.equals(that.type);
}
@Override
public int hashCode() {
return Objects.hash(this.type, this.duration);
}
}
}
@@ -0,0 +1,75 @@
/*
* 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.util.Filterable;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Objects;
public class WritableBookContent {
private List<Filterable<String>> pages;
public WritableBookContent(List<Filterable<String>> pages) {
this.pages = pages;
}
public static WritableBookContent read(PacketWrapper<?> wrapper) {
List<Filterable<String>> pages = wrapper.readList(ew -> Filterable.read(
ew, eew -> eew.readString(1024)));
return new WritableBookContent(pages);
}
public static void write(PacketWrapper<?> wrapper, WritableBookContent content) {
wrapper.writeList(content.pages, (ew, page) -> Filterable.write(
ew, page, (eew, text) -> eew.writeString(text, 1024)));
}
public @Nullable Filterable<String> getPage(int index) {
return index >= 0 && index < this.pages.size() ? this.pages.get(index) : null;
}
public void addPage(Filterable<String> page) {
this.pages.add(page);
}
public List<Filterable<String>> getPages() {
return this.pages;
}
public void setPages(List<Filterable<String>> pages) {
this.pages = pages;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof WritableBookContent)) return false;
WritableBookContent that = (WritableBookContent) obj;
return this.pages.equals(that.pages);
}
@Override
public int hashCode() {
return Objects.hashCode(this.pages);
}
}
@@ -0,0 +1,131 @@
/*
* 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.util.Filterable;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Objects;
public class WrittenBookContent {
private Filterable<String> title;
private String author;
private int generation;
private List<Filterable<Component>> pages;
private boolean resolved;
public WrittenBookContent(
Filterable<String> title, String author, int generation,
List<Filterable<Component>> pages, boolean resolved
) {
this.title = title;
this.author = author;
this.generation = generation;
this.pages = pages;
this.resolved = resolved;
}
public static WrittenBookContent read(PacketWrapper<?> wrapper) {
Filterable<String> title = Filterable.read(wrapper, ew -> ew.readString(32));
String author = wrapper.readString();
int generation = wrapper.readVarInt();
List<Filterable<Component>> pages = wrapper.readList(ew -> Filterable.read(
ew, PacketWrapper::readComponent));
boolean resolved = wrapper.readBoolean();
return new WrittenBookContent(title, author, generation, pages, resolved);
}
public static void write(PacketWrapper<?> wrapper, WrittenBookContent content) {
Filterable.write(wrapper, content.title, (ew, text) -> ew.writeString(text, 32));
wrapper.writeString(content.author);
wrapper.writeVarInt(content.generation);
wrapper.writeList(content.pages, (ew, page) -> Filterable.write(
ew, page, PacketWrapper::writeComponent));
wrapper.writeBoolean(content.resolved);
}
public Filterable<String> getTitle() {
return this.title;
}
public void setTitle(Filterable<String> title) {
this.title = title;
}
public String getAuthor() {
return this.author;
}
public void setAuthor(String author) {
this.author = author;
}
public int getGeneration() {
return this.generation;
}
public void setGeneration(int generation) {
this.generation = generation;
}
public @Nullable Filterable<Component> getPage(int index) {
return index >= 0 && index < this.pages.size() ? this.pages.get(index) : null;
}
public void addPage(Filterable<Component> page) {
this.pages.add(page);
}
public List<Filterable<Component>> getPages() {
return this.pages;
}
public void setPages(List<Filterable<Component>> pages) {
this.pages = pages;
}
public boolean isResolved() {
return this.resolved;
}
public void setResolved(boolean resolved) {
this.resolved = resolved;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof WrittenBookContent)) return false;
WrittenBookContent that = (WrittenBookContent) obj;
if (this.generation != that.generation) return false;
if (this.resolved != that.resolved) return false;
if (!this.title.equals(that.title)) return false;
if (!this.author.equals(that.author)) return false;
return this.pages.equals(that.pages);
}
@Override
public int hashCode() {
return Objects.hash(this.title, this.author, this.generation, this.pages, this.resolved);
}
}
@@ -0,0 +1,27 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2023 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.entity.armadillo;
public enum ArmadilloState {
IDLE,
ROLLING,
SCARED,
UNROLLING,
}
@@ -20,27 +20,27 @@ package com.github.retrooper.packetevents.protocol.entity.data;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.entity.armadillo.ArmadilloState;
import com.github.retrooper.packetevents.protocol.entity.pose.EntityPose;
import com.github.retrooper.packetevents.protocol.entity.sniffer.SnifferState;
import com.github.retrooper.packetevents.protocol.entity.villager.VillagerData;
import com.github.retrooper.packetevents.protocol.item.ItemStack;
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
import com.github.retrooper.packetevents.protocol.particle.Particle;
import com.github.retrooper.packetevents.protocol.particle.type.ParticleType;
import com.github.retrooper.packetevents.protocol.particle.type.ParticleTypes;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.protocol.world.BlockFace;
import com.github.retrooper.packetevents.protocol.world.WorldBlockPosition;
import com.github.retrooper.packetevents.resources.ResourceLocation;
import com.github.retrooper.packetevents.util.Quaternion4f;
import com.github.retrooper.packetevents.util.TypesBuilder;
import com.github.retrooper.packetevents.util.TypesBuilderData;
import com.github.retrooper.packetevents.util.Vector3f;
import com.github.retrooper.packetevents.util.Vector3i;
import com.github.retrooper.packetevents.util.mappings.TypesBuilder;
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import net.kyori.adventure.text.Component;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
@@ -55,15 +55,7 @@ public class EntityDataTypes {
private static final Map<String, EntityDataType<?>> ENTITY_DATA_TYPE_MAP = new HashMap<>();
private static final Map<Byte, Map<Integer, EntityDataType<?>>> ENTITY_DATA_TYPE_ID_MAP = new HashMap<>();
protected static final TypesBuilder TYPES_BUILDER = new TypesBuilder("entity/entity_data_type_mappings",
ClientVersion.V_1_8,
ClientVersion.V_1_9,
ClientVersion.V_1_11,
ClientVersion.V_1_13,
ClientVersion.V_1_14,
ClientVersion.V_1_19,
ClientVersion.V_1_19_3,
ClientVersion.V_1_19_4);
protected static final TypesBuilder TYPES_BUILDER = new TypesBuilder("entity/entity_data_type_mappings");
public static final EntityDataType<Byte> BYTE = define("byte", PacketWrapper::readByte, PacketWrapper::writeByte);
@@ -153,14 +145,7 @@ public class EntityDataTypes {
public static final EntityDataType<NBTCompound> NBT = define("nbt", PacketWrapper::readNBT, PacketWrapper::writeNBT);
public static final EntityDataType<Particle> PARTICLE = define("particle", wrapper -> {
int id = wrapper.readVarInt();
ParticleType type = ParticleTypes.getById(PacketEvents.getAPI().getServerManager().getVersion().toClientVersion(), id);
return new Particle(type, type.readDataFunction().apply(wrapper));
}, (wrapper, particle) -> {
wrapper.writeVarInt(particle.getType().getId(PacketEvents.getAPI().getServerManager().getVersion().toClientVersion()));
particle.getType().writeDataFunction().accept(wrapper, particle.getData());
});
public static final EntityDataType<Particle<?>> PARTICLE = define("particle", Particle::read, Particle::write);
public static final EntityDataType<VillagerData> VILLAGER_DATA = define("villager_data", PacketWrapper::readVillagerData, PacketWrapper::writeVillagerData);
@@ -194,7 +179,6 @@ public class EntityDataTypes {
return SnifferState.values()[id];
}, (PacketWrapper<?> wrapper, SnifferState value) -> wrapper.writeVarInt(value.ordinal()));
public static final EntityDataType<Vector3f> VECTOR3F = define("vector3f",
(PacketWrapper<?> wrapper) -> new Vector3f(wrapper.readFloat(), wrapper.readFloat(), wrapper.readFloat()),
(PacketWrapper<?> wrapper, Vector3f value) -> {
@@ -212,6 +196,20 @@ public class EntityDataTypes {
wrapper.writeFloat(value.getW());
});
// Added in 1.20.5
public static final EntityDataType<ArmadilloState> ARMADILLO_STATE = define("armadillo_state",
(PacketWrapper<?> wrapper) -> ArmadilloState.values()[wrapper.readVarInt()],
(PacketWrapper<?> wrapper, ArmadilloState value) -> wrapper.writeVarInt(value.ordinal())
);
public static final EntityDataType<List<Particle<?>>> PARTICLES = define("particles",
wrapper -> wrapper.readList(Particle::read),
(wrapper, particles) -> wrapper.writeList(particles, Particle::write)
);
public static final EntityDataType<Integer> WOLF_VARIANT =
define("wolf_variant_type", readIntDeserializer(), writeIntSerializer());
public static EntityDataType<?> getById(ClientVersion version, int id) {
int index = TYPES_BUILDER.getDataIndex(version);
Map<Integer, EntityDataType<?>> typeIdMap = ENTITY_DATA_TYPE_ID_MAP.get((byte) index);
@@ -367,4 +365,8 @@ public class EntityDataTypes {
}
}
static {
TYPES_BUILDER.unloadFileMappings();
}
}
@@ -20,8 +20,8 @@ package com.github.retrooper.packetevents.protocol.entity.type;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.resources.ResourceLocation;
import com.github.retrooper.packetevents.util.TypesBuilder;
import com.github.retrooper.packetevents.util.TypesBuilderData;
import com.github.retrooper.packetevents.util.mappings.TypesBuilder;
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
@@ -33,33 +33,8 @@ public class EntityTypes {
//Key - mappings version, value - map with entity type ids and entity types
private static final Map<Byte, Map<Integer, EntityType>> ENTITY_TYPE_ID_MAP = new HashMap<>();
private static final Map<Byte, Map<Integer, EntityType>> LEGACY_ENTITY_TYPE_ID_MAP = new HashMap<>();
private static final TypesBuilder TYPES_BUILDER = new TypesBuilder("entity/entity_type_mappings",
ClientVersion.V_1_10,
ClientVersion.V_1_11,
ClientVersion.V_1_12,
ClientVersion.V_1_13,
ClientVersion.V_1_14,
ClientVersion.V_1_15,
ClientVersion.V_1_16,
ClientVersion.V_1_16_2,
ClientVersion.V_1_17,
ClientVersion.V_1_19,
ClientVersion.V_1_19_3,
ClientVersion.V_1_19_4,
ClientVersion.V_1_20_3);
private static final TypesBuilder LEGACY_TYPES_BUILDER = new TypesBuilder("entity/legacy_entity_type_mappings",
ClientVersion.V_1_8,
ClientVersion.V_1_9,
ClientVersion.V_1_10,
ClientVersion.V_1_11,
ClientVersion.V_1_12,
ClientVersion.V_1_13);
static {
TYPES_BUILDER.unloadFileMappings();
LEGACY_TYPES_BUILDER.unloadFileMappings();
}
private static final TypesBuilder TYPES_BUILDER = new TypesBuilder("entity/entity_type_mappings");
private static final TypesBuilder LEGACY_TYPES_BUILDER = new TypesBuilder("entity/legacy_entity_type_mappings");
public static EntityType define(String key, @Nullable EntityType parent) {
TypesBuilderData data = TYPES_BUILDER.define(key);
@@ -313,5 +288,17 @@ public class EntityTypes {
// Added in 1.20.3
public static final EntityType BREEZE = define("breeze", ABSTRACT_MONSTER);
public static final EntityType WIND_CHARGE = define("wind_charge", PROJECTILE_ABSTRACT);
public static final EntityType ABSTRACT_WIND_CHARGE = define("abstract_wind_charge", PROJECTILE_ABSTRACT);
public static final EntityType WIND_CHARGE = define("wind_charge", ABSTRACT_WIND_CHARGE);
// Added in 1.20.5
public static final EntityType ARMADILLO = define("armadillo", ABSTRACT_ANIMAL);
public static final EntityType BOGGED = define("bogged", ABSTRACT_SKELETON);
public static final EntityType BREEZE_WIND_CHARGE = define("breeze_wind_charge", ABSTRACT_WIND_CHARGE);
public static final EntityType OMINOUS_ITEM_SPAWNER = define("ominous_item_spawner", ENTITY);
static {
TYPES_BUILDER.unloadFileMappings();
LEGACY_TYPES_BUILDER.unloadFileMappings();
}
}
@@ -19,7 +19,6 @@
package com.github.retrooper.packetevents.protocol.entity.villager.profession;
import com.github.retrooper.packetevents.resources.ResourceLocation;
import com.github.retrooper.packetevents.util.TypesBuilder;
import java.util.HashMap;
import java.util.Map;
@@ -18,18 +18,36 @@
package com.github.retrooper.packetevents.protocol.item;
import com.github.retrooper.packetevents.protocol.component.ComponentType;
import com.github.retrooper.packetevents.protocol.component.ComponentTypes;
import com.github.retrooper.packetevents.protocol.component.PatchableComponentMap;
import com.github.retrooper.packetevents.protocol.component.builtin.item.ItemEnchantments;
import com.github.retrooper.packetevents.protocol.item.enchantment.Enchantment;
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.item.type.ItemType;
import com.github.retrooper.packetevents.protocol.item.type.ItemTypes;
import com.github.retrooper.packetevents.protocol.nbt.*;
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
import com.github.retrooper.packetevents.protocol.nbt.NBTInt;
import com.github.retrooper.packetevents.protocol.nbt.NBTList;
import com.github.retrooper.packetevents.protocol.nbt.NBTShort;
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
import com.github.retrooper.packetevents.protocol.nbt.NBTType;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import static com.github.retrooper.packetevents.protocol.component.ComponentTypes.DAMAGE;
import static com.github.retrooper.packetevents.protocol.component.ComponentTypes.ENCHANTMENTS;
import static com.github.retrooper.packetevents.protocol.component.ComponentTypes.MAX_DAMAGE;
import static com.github.retrooper.packetevents.protocol.component.ComponentTypes.MAX_STACK_SIZE;
import static com.github.retrooper.packetevents.protocol.component.ComponentTypes.STORED_ENCHANTMENTS;
public class ItemStack {
public static final ItemStack EMPTY = new ItemStack(ItemTypes.AIR, 0, new NBTCompound(), 0);
@@ -37,20 +55,35 @@ public class ItemStack {
private int amount;
@Nullable
private NBTCompound nbt;
@Nullable // lazy loaded
private PatchableComponentMap components; // Added in 1.20.5
private int legacyData = -1;
private boolean cachedIsEmpty = false;
private ItemStack(ItemType type, int amount, @Nullable NBTCompound nbt, int legacyData) {
this(type, amount, nbt, null, legacyData);
}
private ItemStack(
ItemType type,
int amount,
@Nullable NBTCompound nbt,
@Nullable PatchableComponentMap components,
int legacyData
) {
this.type = type;
this.amount = amount;
this.nbt = nbt;
this.components = components;
this.legacyData = legacyData;
updateCachedEmptyStatus();
}
public int getMaxStackSize() {
return getType().getMaxAmount();
return this.getComponentOr(MAX_STACK_SIZE,
// fallback to legacy specified max stack size
this.getType().getMaxAmount());
}
public boolean isStackable() {
@@ -58,11 +91,9 @@ public class ItemStack {
}
public boolean isDamageableItem() {
if (!this.cachedIsEmpty && this.getType().getMaxDurability() > 0) {
NBTCompound tag = this.getNBT();
return tag == null || !tag.getBoolean("Unbreakable");
}
return false;
return !this.cachedIsEmpty && this.getMaxDamage() > 0
&& (this.nbt == null || !this.nbt.getBoolean("Unbreakable"))
&& !this.getComponentOr(ComponentTypes.UNBREAKABLE, false);
}
public boolean isDamaged() {
@@ -70,17 +101,27 @@ public class ItemStack {
}
public int getDamageValue() {
if (nbt == null) return 0;
NBTInt damage = this.nbt.getTagOfTypeOrNull("Damage", NBTInt.class);
return damage == null ? 0 : damage.getAsInt();
if (this.nbt != null) {
NBTInt damage = this.nbt.getTagOfTypeOrNull("Damage", NBTInt.class);
if (damage != null) {
return damage.getAsInt();
}
}
return this.getComponentOr(DAMAGE, 0);
}
public void setDamageValue(int damage) {
this.getOrCreateTag().setTag("Damage", new NBTInt(Math.max(0, damage)));
int cappedDamage = Math.max(0, damage);
// set in legacy nbt
this.getOrCreateTag().setTag("Damage", new NBTInt(cappedDamage));
// set in components
this.setComponent(DAMAGE, cappedDamage);
}
public int getMaxDamage() {
return this.getType().getMaxDurability();
return this.getComponentOr(MAX_DAMAGE,
// fallback to legacy specified max durability
this.getType().getMaxDurability());
}
public NBTCompound getOrCreateTag() {
@@ -125,7 +166,12 @@ public class ItemStack {
}
public ItemStack copy() {
return cachedIsEmpty ? EMPTY : new ItemStack(type, amount, nbt == null ? null : nbt.copy(), legacyData);
return cachedIsEmpty ? EMPTY : new ItemStack(
type, amount,
nbt == null ? null : nbt.copy(),
components == null ? null : components.copy(),
legacyData
);
}
@Nullable
@@ -137,6 +183,58 @@ public class ItemStack {
this.nbt = nbt;
}
public <T> T getComponentOr(ComponentType<T> type, T otherValue) {
if (this.hasComponentPatches()) {
return this.getComponents().getOr(type, otherValue);
}
return this.getType().getComponents().getOr(type, otherValue);
}
public <T> Optional<T> getComponent(ComponentType<T> type) {
if (this.hasComponentPatches()) {
return this.getComponents().getOptional(type);
}
return this.getType().getComponents().getOptional(type);
}
public <T> void setComponent(ComponentType<T> type, T value) {
this.getComponents().set(type, value);
}
public <T> void unsetComponent(ComponentType<T> type) {
this.getComponents().unset(type);
}
public <T> void setComponent(ComponentType<T> type, Optional<T> value) {
this.getComponents().set(type, value);
}
public boolean hasComponent(ComponentType<?> type) {
if (this.hasComponentPatches()) {
return this.getComponents().has(type);
}
return this.getType().getComponents().has(type);
}
public boolean hasComponentPatches() {
return this.components != null && !this.components.getPatches().isEmpty();
}
public PatchableComponentMap getComponents() {
if (this.components == null) { // lazy load on access
this.components = new PatchableComponentMap(
this.type.getComponents(), new HashMap<>(4));
}
return this.components;
}
/**
* @param components if set null will reset to components of {@link ItemType}
*/
public void setComponents(@Nullable PatchableComponentMap components) {
this.components = components;
}
public int getLegacyData() {
return legacyData;
}
@@ -152,49 +250,101 @@ public class ItemStack {
}
public boolean isEnchanted(ClientVersion version) {
String tagName = getEnchantmentsTagName(version);
return !isEmpty() && this.nbt != null && this.nbt.getCompoundListTagOrNull(tagName) != null && !this.nbt.getCompoundListTagOrNull(tagName).getTags().isEmpty();
}
private List<Enchantment> getEnchantments(@Nullable NBTCompound nbt, ClientVersion version) {
String tagName = getEnchantmentsTagName(version);
if (nbt == null || nbt.getCompoundListTagOrNull(tagName) == null)
return new ArrayList<>(0);
NBTList<NBTCompound> nbtList = nbt.getCompoundListTagOrNull(tagName);
List<NBTCompound> compounds = nbtList.getTags();
List<Enchantment> enchantments = new ArrayList<>(compounds.size());
for (NBTCompound compound : compounds) {
EnchantmentType type = getEnchantmentTypeFromTag(compound, version);
if (type != null) {
NBTShort levelTag = compound.getTagOfTypeOrNull("lvl", NBTShort.class);
int level = levelTag.getAsInt();
Enchantment enchantment = Enchantment.builder().type(type).level(level).build();
enchantments.add(enchantment);
}
if (this.isEmpty()) {
return false;
}
return enchantments;
// check for components
if (!this.getComponentOr(ENCHANTMENTS, ItemEnchantments.EMPTY).isEmpty()
|| !this.getComponentOr(STORED_ENCHANTMENTS, ItemEnchantments.EMPTY).isEmpty()) {
return true;
}
// check for legacy nbt
if (this.nbt != null) {
String tagName = this.getEnchantmentsTagName(version);
NBTList<NBTCompound> enchantments = this.nbt.getCompoundListTagOrNull(tagName);
return enchantments != null && !enchantments.getTags().isEmpty();
}
return false;
}
public List<Enchantment> getEnchantments(ClientVersion version) {
return getEnchantments(this.nbt, version);
if (this.isEmpty()) {
return new ArrayList<>(0);
}
// check for components
Optional<ItemEnchantments> optEnchantments = this.getComponent(ENCHANTMENTS);
Optional<ItemEnchantments> optStoredEnchantments = this.getComponent(STORED_ENCHANTMENTS);
if (optEnchantments.isPresent() || optStoredEnchantments.isPresent()) {
ItemEnchantments enchantments = optEnchantments.orElse(ItemEnchantments.EMPTY);
ItemEnchantments storedEnchantments = optStoredEnchantments.orElse(ItemEnchantments.EMPTY);
List<Enchantment> enchantmentsList = new ArrayList<>(
enchantments.getEnchantmentCount() + storedEnchantments.getEnchantmentCount());
for (Map.Entry<EnchantmentType, Integer> enchantment : enchantments) {
enchantmentsList.add(new Enchantment(enchantment.getKey(), enchantment.getValue()));
}
for (Map.Entry<EnchantmentType, Integer> enchantment : storedEnchantments) {
enchantmentsList.add(new Enchantment(enchantment.getKey(), enchantment.getValue()));
}
return enchantmentsList;
}
// check for legacy nbt
if (this.nbt != null) {
String tagName = this.getEnchantmentsTagName(version);
NBTList<NBTCompound> nbtList = this.nbt.getCompoundListTagOrNull(tagName);
if (nbtList != null) {
List<NBTCompound> compounds = nbtList.getTags();
List<Enchantment> enchantments = new ArrayList<>(compounds.size());
for (NBTCompound compound : compounds) {
EnchantmentType type = getEnchantmentTypeFromTag(compound, version);
if (type != null) {
NBTShort levelTag = compound.getTagOfTypeOrNull("lvl", NBTShort.class);
int level = levelTag.getAsInt();
Enchantment enchantment = Enchantment.builder().type(type).level(level).build();
enchantments.add(enchantment);
}
}
return enchantments;
}
}
return new ArrayList<>(0);
}
public int getEnchantmentLevel(EnchantmentType enchantment, ClientVersion version) {
if (isEnchanted(version)) {
// isEnchanted() is true, so we can assume that nbt is not null
assert nbt != null;
String tagName = getEnchantmentsTagName(version);
for (NBTCompound base : nbt.getCompoundListTagOrNull(tagName).getTags()) {
EnchantmentType type = getEnchantmentTypeFromTag(base, version);
if (enchantment == type) {
NBTShort nbtShort = base.getTagOfTypeOrNull("lvl", NBTShort.class);
if (nbtShort == null) return 0; // this might need to be set to 1
return nbtShort.getAsInt();
if (this.isEmpty()) {
return 0;
}
// check for components
Optional<ItemEnchantments> optEnchantments = this.getComponent(ENCHANTMENTS);
if (optEnchantments.isPresent()) {
int level = optEnchantments.get().getEnchantmentLevel(enchantment);
if (level > 0) {
return level;
}
}
Optional<ItemEnchantments> optStoredEnchantments = this.getComponent(STORED_ENCHANTMENTS);
if (optStoredEnchantments.isPresent()) {
int level = optStoredEnchantments.get().getEnchantmentLevel(enchantment);
if (level > 0) {
return level;
}
}
if (this.nbt != null) {
String tagName = this.getEnchantmentsTagName(version);
NBTList<NBTCompound> nbtList = this.nbt.getCompoundListTagOrNull(tagName);
if (nbtList != null) {
for (NBTCompound base : nbtList.getTags()) {
EnchantmentType type = getEnchantmentTypeFromTag(base, version);
if (enchantment == type) {
NBTShort nbtShort = base.getTagOfTypeOrNull("lvl", NBTShort.class);
return nbtShort != null ? nbtShort.getAsInt() : 0;
}
}
}
}
@@ -202,8 +352,7 @@ public class ItemStack {
return 0;
}
@Nullable
private static EnchantmentType getEnchantmentTypeFromTag(NBTCompound tag, ClientVersion version) {
private static @Nullable EnchantmentType getEnchantmentTypeFromTag(NBTCompound tag, ClientVersion version) {
if (version.isNewerThanOrEquals(ClientVersion.V_1_13)) {
String id = tag.getStringTagValueOrNull("id");
return EnchantmentTypes.getByName(id);
@@ -214,6 +363,7 @@ public class ItemStack {
}
public void setEnchantments(List<Enchantment> enchantments, ClientVersion version) {
// set in legacy nbt
nbt = getOrCreateTag(); // Create tag if null
String tagName = getEnchantmentsTagName(version);
if (enchantments.isEmpty()) {
@@ -237,8 +387,20 @@ public class ItemStack {
assert nbt != null; // NBT was created in getOrCreateTag()
nbt.setTag(tagName, new NBTList<>(NBTType.COMPOUND, list));
}
// set in components
Map<EnchantmentType, Integer> enchantmentsMap = new HashMap<>(enchantments.size());
for (Enchantment enchantment : enchantments) {
enchantmentsMap.put(enchantment.getType(), enchantment.getLevel());
}
ComponentType<ItemEnchantments> componentType = this.type == ItemTypes.ENCHANTED_BOOK
? STORED_ENCHANTMENTS : ENCHANTMENTS;
Optional<ItemEnchantments> prevEnchantments = this.getComponent(componentType);
boolean showInTooltip = prevEnchantments.map(ItemEnchantments::isShowInTooltip).orElse(true);
this.setComponent(componentType, new ItemEnchantments(enchantmentsMap, showInTooltip));
}
@Deprecated
public String getEnchantmentsTagName(ClientVersion version) {
String tagName = version.isNewerThanOrEquals(ClientVersion.V_1_13) ? "Enchantments" : "ench";
if (type == ItemTypes.ENCHANTED_BOOK) {
@@ -256,7 +418,10 @@ public class ItemStack {
}
public static boolean isSameItemSameTags(ItemStack stack, ItemStack otherStack) {
return stack.is(otherStack.getType()) && ItemStack.tagMatches(stack, otherStack);
return stack.is(otherStack.getType())
&& (stack.isEmpty() && otherStack.isEmpty()
|| (ItemStack.tagMatches(stack, otherStack)
&& Objects.equals(stack.components, otherStack.components)));
}
public static boolean tagMatches(ItemStack left, ItemStack right) {
@@ -269,7 +434,8 @@ public class ItemStack {
if (right == null) {
return left.isEmpty();
}
return Objects.equals(left.nbt, right.nbt);
return Objects.equals(left.nbt, right.nbt)
&& Objects.equals(left.components, right.components);
}
@Override
@@ -281,6 +447,7 @@ public class ItemStack {
return getType().equals(itemStack.getType())
&& amount == itemStack.amount
&& Objects.equals(nbt, itemStack.nbt)
&& Objects.equals(components, itemStack.components)
&& legacyData == itemStack.legacyData;
}
return false;
@@ -294,7 +461,8 @@ public class ItemStack {
String identifier = type == null ? "null" : type.getName().toString();
int maxAmount = getType().getMaxAmount();
return "ItemStack[type=" + identifier + ", amount=" + amount + "/" + maxAmount
+ ", nbt tag names: " + (nbt != null ? nbt.getTagNames() : "[null]") + ", legacyData=" + legacyData + "]";
+ ", nbt tag names: " + (nbt != null ? nbt.getTagNames() : "[null]")
+ ", legacyData=" + legacyData + ", components=" + components + "]";
}
}
@@ -310,6 +478,7 @@ public class ItemStack {
private ItemType type;
private int amount = 1;
private NBTCompound nbt = null;
private PatchableComponentMap components = null;
private int legacyData = -1;
public Builder type(ItemType type) {
@@ -327,13 +496,18 @@ public class ItemStack {
return this;
}
public Builder components(@Nullable PatchableComponentMap components) {
this.components = components;
return this;
}
public Builder legacyData(int legacyData) {
this.legacyData = legacyData;
return this;
}
public ItemStack build() {
return new ItemStack(type, amount, nbt, legacyData);
return new ItemStack(type, amount, nbt, components, legacyData);
}
}
@@ -0,0 +1,24 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.item.armormaterial;
import com.github.retrooper.packetevents.protocol.mapper.MappedEntity;
public interface ArmorMaterial extends MappedEntity {
}
@@ -0,0 +1,90 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.item.armormaterial;
import com.github.retrooper.packetevents.protocol.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 java.util.HashMap;
import java.util.Map;
public class ArmorMaterials {
private static final Map<String, ArmorMaterial> MATERIAL_MAP = new HashMap<>();
private static final Map<Byte, Map<Integer, ArmorMaterial>> MATERIAL_ID_MAP = new HashMap<>();
private static final TypesBuilder TYPES_BUILDER = new TypesBuilder("item/item_armor_material_mappings");
public static ArmorMaterial define(String key) {
TypesBuilderData data = TYPES_BUILDER.define(key);
ArmorMaterial instrument = new ArmorMaterial() {
@Override
public ResourceLocation getName() {
return data.getName();
}
@Override
public int getId(ClientVersion version) {
return TYPES_BUILDER.getDataIndex(version);
}
@Override
public boolean equals(Object obj) {
if (obj instanceof ArmorMaterial) {
return getName().equals(((ArmorMaterial) obj).getName());
}
return false;
}
};
MappingHelper.registerMapping(TYPES_BUILDER, MATERIAL_MAP, MATERIAL_ID_MAP, instrument);
return instrument;
}
// with key
public static ArmorMaterial getByName(String name) {
return MATERIAL_MAP.get(name);
}
public static ArmorMaterial getById(ClientVersion version, int id) {
int index = TYPES_BUILDER.getDataIndex(version);
Map<Integer, ArmorMaterial> idMap = MATERIAL_ID_MAP.get((byte) index);
return idMap.get(id);
}
public static final ArmorMaterial LEATHER = define("leather");
public static final ArmorMaterial CHAINMAIL = define("chainmail");
public static final ArmorMaterial IRON = define("iron");
public static final ArmorMaterial GOLD = define("gold");
public static final ArmorMaterial DIAMOND = define("diamond");
// Added with 1.13
public static final ArmorMaterial TURTLE = define("turtle");
// Added with 1.16
public static final ArmorMaterial NETHERITE = define("netherite");
// Added with 1.20.5
public static final ArmorMaterial ARMADILLO = define("armadillo");
static {
TYPES_BUILDER.unloadFileMappings();
}
}
@@ -0,0 +1,41 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.item.banner;
import com.github.retrooper.packetevents.protocol.mapper.MappedEntity;
import com.github.retrooper.packetevents.resources.ResourceLocation;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
public interface BannerPattern extends MappedEntity {
ResourceLocation getAssetId();
String getTranslationKey();
static BannerPattern readDirect(PacketWrapper<?> wrapper) {
ResourceLocation assetId = wrapper.readIdentifier();
String translationKey = wrapper.readString();
return new StaticBannerPattern(assetId, translationKey);
}
static void writeDirect(PacketWrapper<?> wrapper, BannerPattern pattern) {
wrapper.writeIdentifier(pattern.getAssetId());
wrapper.writeString(pattern.getTranslationKey());
}
}
@@ -0,0 +1,133 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.item.banner;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.resources.ResourceLocation;
import com.github.retrooper.packetevents.util.mappings.MappingHelper;
import com.github.retrooper.packetevents.util.mappings.TypesBuilder;
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
import java.util.HashMap;
import java.util.Map;
public class BannerPatterns {
private static final Map<String, BannerPattern> PATTERN_TYPE_MAP = new HashMap<>();
private static final Map<Byte, Map<Integer, BannerPattern>> PATTERN_TYPE_ID_MAP = new HashMap<>();
private static final TypesBuilder TYPES_BUILDER = new TypesBuilder("item/item_banner_pattern_mappings");
public static BannerPattern define(String key) {
ResourceLocation assetId = ResourceLocation.minecraft(key);
String translationKey = "block.minecraft.banner." + key;
return define(key, assetId, translationKey);
}
public static BannerPattern define(String key, ResourceLocation assetId, String translationKey) {
TypesBuilderData data = TYPES_BUILDER.define(key);
BannerPattern pattern = new BannerPattern() {
@Override
public ResourceLocation getAssetId() {
return assetId;
}
@Override
public String getTranslationKey() {
return translationKey;
}
@Override
public ResourceLocation getName() {
return data.getName();
}
@Override
public int getId(ClientVersion version) {
return TYPES_BUILDER.getDataIndex(version);
}
@Override
public boolean equals(Object obj) {
if (obj instanceof BannerPattern) {
return getName().equals(((BannerPattern) obj).getName());
}
return false;
}
};
MappingHelper.registerMapping(TYPES_BUILDER, PATTERN_TYPE_MAP, PATTERN_TYPE_ID_MAP, pattern);
return pattern;
}
// with key
public static BannerPattern getByName(String name) {
return PATTERN_TYPE_MAP.get(name);
}
public static BannerPattern getById(ClientVersion version, int id) {
int index = TYPES_BUILDER.getDataIndex(version);
Map<Integer, BannerPattern> idMap = PATTERN_TYPE_ID_MAP.get((byte) index);
return idMap.get(id);
}
public static final BannerPattern SQUARE_BOTTOM_LEFT = define("square_bottom_left");
public static final BannerPattern STRIPE_BOTTOM = define("stripe_bottom");
public static final BannerPattern CREEPER = define("creeper");
public static final BannerPattern HALF_HORIZONTAL = define("half_horizontal");
public static final BannerPattern STRIPE_MIDDLE = define("stripe_middle");
public static final BannerPattern BASE = define("base");
public static final BannerPattern DIAGONAL_UP_RIGHT = define("diagonal_up_right");
public static final BannerPattern HALF_HORIZONTAL_BOTTOM = define("half_horizontal_bottom");
public static final BannerPattern SMALL_STRIPES = define("small_stripes");
public static final BannerPattern GRADIENT_UP = define("gradient_up");
public static final BannerPattern CIRCLE = define("circle");
public static final BannerPattern STRIPE_DOWNLEFT = define("stripe_downleft");
public static final BannerPattern RHOMBUS = define("rhombus");
public static final BannerPattern TRIANGLES_BOTTOM = define("triangles_bottom");
public static final BannerPattern STRIPE_CENTER = define("stripe_center");
public static final BannerPattern SQUARE_BOTTOM_RIGHT = define("square_bottom_right");
public static final BannerPattern DIAGONAL_RIGHT = define("diagonal_right");
public static final BannerPattern MOJANG = define("mojang");
public static final BannerPattern STRIPE_LEFT = define("stripe_left");
public static final BannerPattern SQUARE_TOP_LEFT = define("square_top_left");
public static final BannerPattern TRIANGLE_BOTTOM = define("triangle_bottom");
public static final BannerPattern SKULL = define("skull");
public static final BannerPattern SQUARE_TOP_RIGHT = define("square_top_right");
public static final BannerPattern GLOBE = define("globe");
public static final BannerPattern STRIPE_TOP = define("stripe_top");
public static final BannerPattern CROSS = define("cross");
public static final BannerPattern BRICKS = define("bricks");
public static final BannerPattern HALF_VERTICAL = define("half_vertical");
public static final BannerPattern STRIPE_DOWNRIGHT = define("stripe_downright");
public static final BannerPattern TRIANGLES_TOP = define("triangles_top");
public static final BannerPattern STRIPE_RIGHT = define("stripe_right");
public static final BannerPattern DIAGONAL_UP_LEFT = define("diagonal_up_left");
public static final BannerPattern HALF_VERTICAL_RIGHT = define("half_vertical_right");
public static final BannerPattern TRIANGLE_TOP = define("triangle_top");
public static final BannerPattern FLOWER = define("flower");
public static final BannerPattern STRAIGHT_CROSS = define("straight_cross");
public static final BannerPattern GRADIENT = define("gradient");
public static final BannerPattern CURLY_BORDER = define("curly_border");
public static final BannerPattern BORDER = define("border");
public static final BannerPattern PIGLIN = define("piglin");
public static final BannerPattern DIAGONAL_LEFT = define("diagonal_left");
static {
TYPES_BUILDER.unloadFileMappings();
}
}
@@ -0,0 +1,74 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.item.banner;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.resources.ResourceLocation;
import java.util.Objects;
public class StaticBannerPattern implements BannerPattern {
private final ResourceLocation assetId;
private final String translationKey;
public StaticBannerPattern(ResourceLocation assetId, String translationKey) {
this.assetId = assetId;
this.translationKey = translationKey;
}
@Override
public ResourceLocation getAssetId() {
return this.assetId;
}
@Override
public String getTranslationKey() {
return this.translationKey;
}
@Override
public ResourceLocation getName() {
throw new UnsupportedOperationException();
}
@Override
public int getId(ClientVersion version) {
throw new UnsupportedOperationException();
}
@Override
public boolean isRegistered() {
return false;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof StaticBannerPattern)) return false;
StaticBannerPattern that = (StaticBannerPattern) obj;
if (!this.assetId.equals(that.assetId)) return false;
return this.translationKey.equals(that.translationKey);
}
@Override
public int hashCode() {
return Objects.hash(this.assetId, this.translationKey);
}
}
@@ -19,13 +19,12 @@
package com.github.retrooper.packetevents.protocol.item.enchantment;
import com.github.retrooper.packetevents.protocol.item.enchantment.type.EnchantmentType;
import com.github.retrooper.packetevents.protocol.item.enchantment.type.EnchantmentTypes;
public class Enchantment {
private EnchantmentType type;
private int level;
private Enchantment(EnchantmentType type, int level) {
public Enchantment(EnchantmentType type, int level) {
this.type = type;
this.level = level;
}
@@ -20,28 +20,30 @@ package com.github.retrooper.packetevents.protocol.item.enchantment.type;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.resources.ResourceLocation;
import com.github.retrooper.packetevents.util.TypesBuilder;
import com.github.retrooper.packetevents.util.TypesBuilderData;
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 org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.Map;
public class EnchantmentTypes {
private static final Map<String, String> STRING_UPDATER = new HashMap<>();
static {
// renamed in 24w03a, during the 1.20.5 update
STRING_UPDATER.put("minecraft:sweeping", "minecraft:sweeping_edge");
}
private static final Map<String, EnchantmentType> ENCHANTMENT_TYPE_MAPPINGS = new HashMap<>();
private static final Map<Byte, Map<Integer, EnchantmentType>> ENCHANTMENT_TYPE_ID_MAPPINGS = new HashMap<>();
private static final TypesBuilder TYPES_BUILDER = new TypesBuilder("enchantment/enchantment_type_mappings",
ClientVersion.V_1_12,
ClientVersion.V_1_13,
ClientVersion.V_1_14,
ClientVersion.V_1_16,
ClientVersion.V_1_19);
private static final TypesBuilder TYPES_BUILDER = new TypesBuilder("enchantment/enchantment_type_mappings");
public static EnchantmentType define(String key) {
TypesBuilderData data = TYPES_BUILDER.define(key);
EnchantmentType enchantmentType = new EnchantmentType() {
private final int[] ids = data.getData();
@Override
public ResourceLocation getName() {
return data.getName();
@@ -49,8 +51,7 @@ public class EnchantmentTypes {
@Override
public int getId(ClientVersion version) {
int index = TYPES_BUILDER.getDataIndex(version);
return ids[index];
return MappingHelper.getId(version, TYPES_BUILDER, data);
}
@Override
@@ -62,18 +63,14 @@ public class EnchantmentTypes {
}
};
ENCHANTMENT_TYPE_MAPPINGS.put(enchantmentType.getName().toString(), enchantmentType);
for (ClientVersion version : TYPES_BUILDER.getVersions()) {
int index = TYPES_BUILDER.getDataIndex(version);
Map<Integer, EnchantmentType> typeIdMap = ENCHANTMENT_TYPE_ID_MAPPINGS.computeIfAbsent((byte) index, k -> new HashMap<>());
typeIdMap.put(enchantmentType.getId(version), enchantmentType);
}
MappingHelper.registerMapping(TYPES_BUILDER, ENCHANTMENT_TYPE_MAPPINGS, ENCHANTMENT_TYPE_ID_MAPPINGS, enchantmentType);
return enchantmentType;
}
@Nullable
public static EnchantmentType getByName(String name) {
return ENCHANTMENT_TYPE_MAPPINGS.get(name);
String fixedName = STRING_UPDATER.getOrDefault(name, name);
return ENCHANTMENT_TYPE_MAPPINGS.get(fixedName);
}
@Nullable
@@ -102,7 +99,7 @@ public class EnchantmentTypes {
public static final EnchantmentType KNOCKBACK = define("knockback");
public static final EnchantmentType FIRE_ASPECT = define("fire_aspect");
public static final EnchantmentType MOB_LOOTING = define("looting");
public static final EnchantmentType SWEEPING_EDGE = define("sweeping");
public static final EnchantmentType SWEEPING_EDGE = define("sweeping_edge");
public static final EnchantmentType BLOCK_EFFICIENCY = define("efficiency");
public static final EnchantmentType SILK_TOUCH = define("silk_touch");
public static final EnchantmentType UNBREAKING = define("unbreaking");
@@ -123,6 +120,11 @@ public class EnchantmentTypes {
public static final EnchantmentType MENDING = define("mending");
public static final EnchantmentType VANISHING_CURSE = define("vanishing_curse");
// Added in 1.20.5
public static final EnchantmentType DENSITY = define("density");
public static final EnchantmentType BREACH = define("breach");
public static final EnchantmentType WIND_BURST = define("wind_burst");
static {
TYPES_BUILDER.unloadFileMappings();
}
@@ -0,0 +1,53 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.item.instrument;
import com.github.retrooper.packetevents.protocol.mapper.MappedEntity;
import com.github.retrooper.packetevents.protocol.sound.Sound;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
public interface Instrument extends MappedEntity {
Sound getSound();
int getUseDuration();
float getRange();
static Instrument read(PacketWrapper<?> wrapper) {
return wrapper.readMappedEntityOrDirect(Instruments::getById, Instrument::readDirect);
}
static Instrument readDirect(PacketWrapper<?> wrapper) {
Sound sound = Sound.read(wrapper);
int useDuration = wrapper.readVarInt();
float range = wrapper.readFloat();
return new StaticInstrument(sound, useDuration, range);
}
static void write(PacketWrapper<?> wrapper, Instrument instrument) {
wrapper.writeMappedEntityOrDirect(instrument, Instrument::writeDirect);
}
static void writeDirect(PacketWrapper<?> wrapper, Instrument instrument) {
Sound.write(wrapper, instrument.getSound());
wrapper.writeVarInt(instrument.getUseDuration());
wrapper.writeFloat(instrument.getRange());
}
}
@@ -0,0 +1,106 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.item.instrument;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.protocol.sound.Sound;
import com.github.retrooper.packetevents.protocol.sound.Sounds;
import com.github.retrooper.packetevents.resources.ResourceLocation;
import com.github.retrooper.packetevents.util.mappings.MappingHelper;
import com.github.retrooper.packetevents.util.mappings.TypesBuilder;
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
import java.util.HashMap;
import java.util.Map;
public class Instruments {
private static final Map<String, Instrument> INSTRUMENT_MAP = new HashMap<>();
private static final Map<Byte, Map<Integer, Instrument>> INSTRUMENT_ID_MAP = new HashMap<>();
private static final TypesBuilder TYPES_BUILDER = new TypesBuilder("item/item_instrument_mappings");
public static Instrument define(String key, Sound sound) {
// vanilla defaults for goat horns
return define(key, sound, 140, 256f);
}
public static Instrument define(String key, Sound sound, int useDuration, float range) {
TypesBuilderData data = TYPES_BUILDER.define(key);
Instrument instrument = new Instrument() {
@Override
public Sound getSound() {
return sound;
}
@Override
public int getUseDuration() {
return useDuration;
}
@Override
public float getRange() {
return range;
}
@Override
public ResourceLocation getName() {
return data.getName();
}
@Override
public int getId(ClientVersion version) {
return MappingHelper.getId(version, TYPES_BUILDER, data);
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Instrument) {
return getName().equals(((Instrument) obj).getName());
}
return false;
}
};
MappingHelper.registerMapping(TYPES_BUILDER, INSTRUMENT_MAP, INSTRUMENT_ID_MAP, instrument);
return instrument;
}
// with key
public static Instrument getByName(String name) {
return INSTRUMENT_MAP.get(name);
}
public static Instrument getById(ClientVersion version, int id) {
int index = TYPES_BUILDER.getDataIndex(version);
Map<Integer, Instrument> idMap = INSTRUMENT_ID_MAP.get((byte) index);
return idMap.get(id);
}
public static final Instrument PONDER_GOAT_HORN = define("ponder_goat_horn", Sounds.ITEM_GOAT_HORN_SOUND_0);
public static final Instrument SING_GOAT_HORN = define("sing_goat_horn", Sounds.ITEM_GOAT_HORN_SOUND_1);
public static final Instrument SEEK_GOAT_HORN = define("seek_goat_horn", Sounds.ITEM_GOAT_HORN_SOUND_2);
public static final Instrument FEEL_GOAT_HORN = define("feel_goat_horn", Sounds.ITEM_GOAT_HORN_SOUND_3);
public static final Instrument ADMIRE_GOAT_HORN = define("admire_goat_horn", Sounds.ITEM_GOAT_HORN_SOUND_4);
public static final Instrument CALL_GOAT_HORN = define("call_goat_horn", Sounds.ITEM_GOAT_HORN_SOUND_5);
public static final Instrument YEARN_GOAT_HORN = define("yearn_goat_horn", Sounds.ITEM_GOAT_HORN_SOUND_6);
public static final Instrument DREAM_GOAT_HORN = define("dream_goat_horn", Sounds.ITEM_GOAT_HORN_SOUND_7);
static {
TYPES_BUILDER.unloadFileMappings();
}
}
@@ -0,0 +1,83 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.item.instrument;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.protocol.sound.Sound;
import com.github.retrooper.packetevents.resources.ResourceLocation;
import java.util.Objects;
public class StaticInstrument implements Instrument {
private final Sound sound;
private final int useDuration;
private final float range;
public StaticInstrument(Sound sound, int useDuration, float range) {
this.sound = sound;
this.useDuration = useDuration;
this.range = range;
}
@Override
public Sound getSound() {
return this.sound;
}
@Override
public int getUseDuration() {
return this.useDuration;
}
@Override
public float getRange() {
return this.range;
}
@Override
public ResourceLocation getName() {
throw new UnsupportedOperationException();
}
@Override
public int getId(ClientVersion version) {
throw new UnsupportedOperationException();
}
@Override
public boolean isRegistered() {
return false;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof StaticInstrument)) return false;
StaticInstrument that = (StaticInstrument) obj;
if (this.useDuration != that.useDuration) return false;
if (Float.compare(that.range, this.range) != 0) return false;
return this.sound.equals(that.sound);
}
@Override
public int hashCode() {
return Objects.hash(this.sound, this.useDuration, this.range);
}
}
@@ -0,0 +1,35 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.item.mapdecoration;
import com.github.retrooper.packetevents.protocol.mapper.MappedEntity;
import com.github.retrooper.packetevents.resources.ResourceLocation;
public interface MapDecorationType extends MappedEntity {
ResourceLocation getAssetId();
boolean isShowOnItemFrame();
int getMapColor();
boolean isExplorationMapElement();
boolean isTrackCount();
}
@@ -0,0 +1,207 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.item.mapdecoration;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.resources.ResourceLocation;
import com.github.retrooper.packetevents.util.mappings.MappingHelper;
import com.github.retrooper.packetevents.util.mappings.TypesBuilder;
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.Map;
import static com.github.retrooper.packetevents.resources.ResourceLocation.minecraft;
public class MapDecorationTypes {
private static final Map<String, MapDecorationType> DECORATION_TYPE_MAP = new HashMap<>();
private static final Map<Byte, Map<Integer, MapDecorationType>> DECORATION_TYPE_ID_MAP = new HashMap<>();
private static final TypesBuilder TYPES_BUILDER = new TypesBuilder("item/item_map_decoration_type_mappings");
public static MapDecorationType define(String key, boolean showOnItemFrame, boolean trackCount) {
return define(key, minecraft(key), showOnItemFrame, trackCount);
}
public static MapDecorationType define(
String key, ResourceLocation assetId,
boolean showOnItemFrame, boolean trackCount
) {
return define(key, assetId, showOnItemFrame,
-1, false, trackCount);
}
public static MapDecorationType define(
String key,
boolean showOnItemFrame, int mapColor,
boolean explorationMapElement, boolean trackCount
) {
return define(key, minecraft(key),
showOnItemFrame, mapColor, explorationMapElement, trackCount);
}
public static MapDecorationType define(
String key, ResourceLocation assetId,
boolean showOnItemFrame, int mapColor,
boolean explorationMapElement, boolean trackCount
) {
TypesBuilderData data = TYPES_BUILDER.define(key);
MapDecorationType potionType = new MapDecorationType() {
@Override
public ResourceLocation getAssetId() {
return assetId;
}
@Override
public boolean isShowOnItemFrame() {
return showOnItemFrame;
}
@Override
public int getMapColor() {
return mapColor;
}
@Override
public boolean isExplorationMapElement() {
return explorationMapElement;
}
@Override
public boolean isTrackCount() {
return trackCount;
}
@Override
public ResourceLocation getName() {
return data.getName();
}
@Override
public int getId(ClientVersion version) {
return MappingHelper.getId(version, TYPES_BUILDER, data);
}
@Override
public boolean equals(Object obj) {
if (obj instanceof MapDecorationType) {
return this.getName().equals(((MapDecorationType) obj).getName());
}
return false;
}
};
MappingHelper.registerMapping(TYPES_BUILDER, DECORATION_TYPE_MAP, DECORATION_TYPE_ID_MAP, potionType);
return potionType;
}
public static @Nullable MapDecorationType getByName(String name) {
return DECORATION_TYPE_MAP.get(name);
}
public static @Nullable MapDecorationType getById(int id, ClientVersion version) {
int index = TYPES_BUILDER.getDataIndex(version);
Map<Integer, MapDecorationType> idMap = DECORATION_TYPE_ID_MAP.get((byte) index);
return idMap.get(id);
}
// color constants used by vanilla
private static final int LIGHT_GRAY_COLOR = 0x999999;
private static final int COPPER_COLOR = 0xC26B4C;
public static final MapDecorationType PLAYER = define("player",
false, true);
public static final MapDecorationType FRAME = define("frame",
true, true);
public static final MapDecorationType RED_MARKER = define("red_marker",
false, true);
public static final MapDecorationType BLUE_MARKER = define("blue_marker",
false, true);
public static final MapDecorationType TARGET_X = define("target_x",
true, false);
public static final MapDecorationType TARGET_POINT = define("target_point",
true, false);
public static final MapDecorationType PLAYER_OFF_MAP = define("player_off_map",
false, true);
public static final MapDecorationType PLAYER_OFF_LIMITS = define("player_off_limits",
false, true);
public static final MapDecorationType MANSION = define("mansion",
true, 0x524C44, true, false);
public static final MapDecorationType MONUMENT = define("monument",
true, 0x3A7265, true, false);
public static final MapDecorationType BANNER_WHITE = define("banner_white",
minecraft("white_banner"), true, true);
public static final MapDecorationType BANNER_ORANGE = define("banner_orange",
minecraft("orange_banner"), true, true);
public static final MapDecorationType BANNER_MAGENTA = define("banner_magenta",
minecraft("magenta_banner"), true, true);
public static final MapDecorationType BANNER_LIGHT_BLUE = define("banner_light_blue",
minecraft("light_blue_banner"), true, true);
public static final MapDecorationType BANNER_YELLOW = define("banner_yellow",
minecraft("yellow_banner"), true, true);
public static final MapDecorationType BANNER_LIME = define("banner_lime",
minecraft("lime_banner"), true, true);
public static final MapDecorationType BANNER_PINK = define("banner_pink",
minecraft("pink_banner"), true, true);
public static final MapDecorationType BANNER_GRAY = define("banner_gray",
minecraft("gray_banner"), true, true);
public static final MapDecorationType BANNER_LIGHT_GRAY = define("banner_light_gray",
minecraft("light_gray_banner"), true, true);
public static final MapDecorationType BANNER_CYAN = define("banner_cyan",
minecraft("cyan_banner"), true, true);
public static final MapDecorationType BANNER_PURPLE = define("banner_purple",
minecraft("purple_banner"), true, true);
public static final MapDecorationType BANNER_BLUE = define("banner_blue",
minecraft("blue_banner"), true, true);
public static final MapDecorationType BANNER_BROWN = define("banner_brown",
minecraft("brown_banner"), true, true);
public static final MapDecorationType BANNER_GREEN = define("banner_green",
minecraft("green_banner"), true, true);
public static final MapDecorationType BANNER_RED = define("banner_red",
minecraft("red_banner"), true, true);
public static final MapDecorationType BANNER_BLACK = define("banner_black",
minecraft("black_banner"), true, true);
public static final MapDecorationType RED_X = define("red_x",
true, false);
// Added with 1.20.2
public static final MapDecorationType VILLAGE_DESERT = define("village_desert", minecraft("desert_village"),
true, LIGHT_GRAY_COLOR, true, false);
public static final MapDecorationType VILLAGE_PLAINS = define("village_plains", minecraft("plains_village"),
true, LIGHT_GRAY_COLOR, true, false);
public static final MapDecorationType VILLAGE_SAVANNA = define("village_savanna", minecraft("savanna_village"),
true, LIGHT_GRAY_COLOR, true, false);
public static final MapDecorationType VILLAGE_SNOWY = define("village_snowy", minecraft("snowy_village"),
true, LIGHT_GRAY_COLOR, true, false);
public static final MapDecorationType VILLAGE_TAIGA = define("village_taiga", minecraft("taiga_village"),
true, LIGHT_GRAY_COLOR, true, false);
public static final MapDecorationType JUNGLE_TEMPLE = define("jungle_temple",
true, LIGHT_GRAY_COLOR, true, false);
public static final MapDecorationType SWAMP_HUT = define("swamp_hut",
true, LIGHT_GRAY_COLOR, true, false);
// Added with 1.20.5
public static final MapDecorationType TRIAL_CHAMBERS = define("trial_chambers",
true, COPPER_COLOR, true, false);
static {
TYPES_BUILDER.unloadFileMappings();
}
}
@@ -0,0 +1,106 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.item.trimmaterial;
import com.github.retrooper.packetevents.protocol.item.armormaterial.ArmorMaterial;
import com.github.retrooper.packetevents.protocol.item.type.ItemType;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.resources.ResourceLocation;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
import java.util.Objects;
public class StaticTrimMaterial implements TrimMaterial {
private final String assetName;
private final ItemType ingredient;
private final float itemModelIndex;
private final Map<ArmorMaterial, String> overrideArmorMaterials;
private final Component description;
public StaticTrimMaterial(
String assetName, ItemType ingredient, float itemModelIndex,
Map<ArmorMaterial, String> overrideArmorMaterials, Component description
) {
this.assetName = assetName;
this.ingredient = ingredient;
this.itemModelIndex = itemModelIndex;
this.overrideArmorMaterials = overrideArmorMaterials;
this.description = description;
}
@Override
public ResourceLocation getName() {
throw new UnsupportedOperationException();
}
@Override
public int getId(ClientVersion version) {
throw new UnsupportedOperationException();
}
@Override
public boolean isRegistered() {
return false;
}
@Override
public String getAssetName() {
return this.assetName;
}
@Override
public ItemType getIngredient() {
return this.ingredient;
}
@Override
public float getItemModelIndex() {
return this.itemModelIndex;
}
@Override
public Map<ArmorMaterial, String> getOverrideArmorMaterials() {
return this.overrideArmorMaterials;
}
@Override
public Component getDescription() {
return this.description;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof StaticTrimMaterial)) return false;
StaticTrimMaterial material = (StaticTrimMaterial) obj;
if (Float.compare(material.itemModelIndex, this.itemModelIndex) != 0) return false;
if (!this.assetName.equals(material.assetName)) return false;
if (!this.ingredient.equals(material.ingredient)) return false;
if (!this.overrideArmorMaterials.equals(material.overrideArmorMaterials)) return false;
return this.description.equals(material.description);
}
@Override
public int hashCode() {
return Objects.hash(this.assetName, this.ingredient, this.itemModelIndex, this.overrideArmorMaterials, this.description);
}
}
@@ -0,0 +1,75 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.item.trimmaterial;
import com.github.retrooper.packetevents.protocol.item.armormaterial.ArmorMaterial;
import com.github.retrooper.packetevents.protocol.item.armormaterial.ArmorMaterials;
import com.github.retrooper.packetevents.protocol.item.type.ItemType;
import com.github.retrooper.packetevents.protocol.item.type.ItemTypes;
import com.github.retrooper.packetevents.protocol.mapper.MappedEntity;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
public interface TrimMaterial extends MappedEntity {
String getAssetName();
ItemType getIngredient();
float getItemModelIndex();
default @Nullable String getArmorMaterialOverride(ArmorMaterial armorMaterial) {
return this.getOverrideArmorMaterials().get(armorMaterial);
}
Map<ArmorMaterial, String> getOverrideArmorMaterials();
Component getDescription();
static TrimMaterial read(PacketWrapper<?> wrapper) {
return wrapper.readMappedEntityOrDirect(TrimMaterials::getById, TrimMaterial::readDirect);
}
static TrimMaterial readDirect(PacketWrapper<?> wrapper) {
String assetName = wrapper.readString();
ItemType ingredient = wrapper.readMappedEntity(ItemTypes::getById);
float itemModelIndex = wrapper.readFloat();
Map<ArmorMaterial, String> overrideArmorMaterials = wrapper.readMap(
ew -> ew.readMappedEntity(ArmorMaterials::getById),
PacketWrapper::readString);
Component description = wrapper.readComponent();
return new StaticTrimMaterial(assetName, ingredient, itemModelIndex, overrideArmorMaterials, description);
}
static void write(PacketWrapper<?> wrapper, TrimMaterial material) {
wrapper.writeMappedEntityOrDirect(material, TrimMaterial::writeDirect);
}
static void writeDirect(PacketWrapper<?> wrapper, TrimMaterial material) {
wrapper.writeString(material.getAssetName());
wrapper.writeMappedEntity(material.getIngredient());
wrapper.writeFloat(material.getItemModelIndex());
wrapper.writeMap(material.getOverrideArmorMaterials(),
PacketWrapper::writeMappedEntity, PacketWrapper::writeString);
wrapper.writeComponent(material.getDescription());
}
}
@@ -0,0 +1,136 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.item.trimmaterial;
import com.github.retrooper.packetevents.protocol.item.armormaterial.ArmorMaterial;
import com.github.retrooper.packetevents.protocol.item.armormaterial.ArmorMaterials;
import com.github.retrooper.packetevents.protocol.item.type.ItemType;
import com.github.retrooper.packetevents.protocol.item.type.ItemTypes;
import com.github.retrooper.packetevents.protocol.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 net.kyori.adventure.text.Component;
import java.util.HashMap;
import java.util.Map;
import static net.kyori.adventure.text.Component.translatable;
import static net.kyori.adventure.text.format.TextColor.color;
public class TrimMaterials {
private static final Map<String, TrimMaterial> PATTERN_TYPE_MAP = new HashMap<>();
private static final Map<Byte, Map<Integer, TrimMaterial>> PATTERN_TYPE_ID_MAP = new HashMap<>();
private static final TypesBuilder TYPES_BUILDER = new TypesBuilder("item/item_trim_material_mappings");
public static TrimMaterial define(String key, ItemType ingredient, float itemModelIndex, int color) {
// darken own armor material - if present
Map<ArmorMaterial, String> overrideArmorMaterials = new HashMap<>(2);
String armorMaterialId = ResourceLocation.minecraft(key).toString();
ArmorMaterial armorMaterial = ArmorMaterials.getByName(armorMaterialId);
if (armorMaterial != null) {
overrideArmorMaterials.put(armorMaterial, key + "_darker");
}
Component description = translatable("trim_material.minecraft." + key, color(color));
return define(key, key, ingredient, itemModelIndex, overrideArmorMaterials, description);
}
public static TrimMaterial define(
String key, String assetName, ItemType ingredient, float itemModelIndex,
Map<ArmorMaterial, String> overrideArmorMaterials, Component description
) {
TypesBuilderData data = TYPES_BUILDER.define(key);
TrimMaterial pattern = new TrimMaterial() {
@Override
public String getAssetName() {
return assetName;
}
@Override
public ItemType getIngredient() {
return ingredient;
}
@Override
public float getItemModelIndex() {
return itemModelIndex;
}
@Override
public Map<ArmorMaterial, String> getOverrideArmorMaterials() {
return overrideArmorMaterials;
}
@Override
public Component getDescription() {
return description;
}
@Override
public ResourceLocation getName() {
return data.getName();
}
@Override
public int getId(ClientVersion version) {
return TYPES_BUILDER.getDataIndex(version);
}
@Override
public boolean equals(Object obj) {
if (obj instanceof TrimMaterial) {
return this.getName().equals(((TrimMaterial) obj).getName());
}
return false;
}
};
MappingHelper.registerMapping(TYPES_BUILDER, PATTERN_TYPE_MAP, PATTERN_TYPE_ID_MAP, pattern);
return pattern;
}
// with key
public static TrimMaterial getByName(String name) {
return PATTERN_TYPE_MAP.get(name);
}
public static TrimMaterial getById(ClientVersion version, int id) {
int index = TYPES_BUILDER.getDataIndex(version);
Map<Integer, TrimMaterial> idMap = PATTERN_TYPE_ID_MAP.get((byte) index);
return idMap.get(id);
}
// Added in 1.19.4
public static final TrimMaterial AMETHYST = define("amethyst", ItemTypes.AMETHYST_SHARD, 1f, 0x9A5CC6);
public static final TrimMaterial COPPER = define("copper", ItemTypes.COPPER_INGOT, 0.5f, 0xB4684D);
public static final TrimMaterial DIAMOND = define("diamond", ItemTypes.DIAMOND, 0.8f, 0x6EECD2);
public static final TrimMaterial EMERALD = define("emerald", ItemTypes.EMERALD, 0.7f, 0x11A036);
public static final TrimMaterial GOLD = define("gold", ItemTypes.GOLD_INGOT, 0.6f, 0xDEB12D);
public static final TrimMaterial IRON = define("iron", ItemTypes.IRON_INGOT, 0.2f, 0xECECEC);
public static final TrimMaterial LAPIS = define("lapis", ItemTypes.LAPIS_LAZULI, 0.9f, 0x416E97);
public static final TrimMaterial NETHERITE = define("netherite", ItemTypes.NETHERITE_INGOT, 0.3f, 0x625859);
public static final TrimMaterial QUARTZ = define("quartz", ItemTypes.QUARTZ, 0.1f, 0xE3D4C4);
public static final TrimMaterial REDSTONE = define("redstone", ItemTypes.REDSTONE, 0.4f, 0x971607);
static {
TYPES_BUILDER.unloadFileMappings();
}
}
@@ -0,0 +1,95 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.item.trimpattern;
import com.github.retrooper.packetevents.protocol.item.type.ItemType;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.resources.ResourceLocation;
import net.kyori.adventure.text.Component;
import java.util.Objects;
public class StaticTrimPattern implements TrimPattern {
private final ResourceLocation assetId;
private final ItemType templateItem;
private final Component description;
private final boolean decal;
public StaticTrimPattern(
ResourceLocation assetId, ItemType templateItem,
Component description, boolean decal
) {
this.assetId = assetId;
this.templateItem = templateItem;
this.description = description;
this.decal = decal;
}
@Override
public ResourceLocation getName() {
throw new UnsupportedOperationException();
}
@Override
public int getId(ClientVersion version) {
throw new UnsupportedOperationException();
}
@Override
public boolean isRegistered() {
return false;
}
@Override
public ResourceLocation getAssetId() {
return this.assetId;
}
@Override
public ItemType getTemplateItem() {
return this.templateItem;
}
@Override
public Component getDescription() {
return this.description;
}
@Override
public boolean isDecal() {
return this.decal;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof StaticTrimPattern)) return false;
StaticTrimPattern pattern = (StaticTrimPattern) obj;
if (this.decal != pattern.decal) return false;
if (!this.assetId.equals(pattern.assetId)) return false;
if (!this.templateItem.equals(pattern.templateItem)) return false;
return this.description.equals(pattern.description);
}
@Override
public int hashCode() {
return Objects.hash(this.assetId, this.templateItem, this.description, this.decal);
}
}
@@ -0,0 +1,60 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.item.trimpattern;
import com.github.retrooper.packetevents.protocol.item.type.ItemType;
import com.github.retrooper.packetevents.protocol.item.type.ItemTypes;
import com.github.retrooper.packetevents.protocol.mapper.MappedEntity;
import com.github.retrooper.packetevents.resources.ResourceLocation;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import net.kyori.adventure.text.Component;
public interface TrimPattern extends MappedEntity {
ResourceLocation getAssetId();
ItemType getTemplateItem();
Component getDescription();
boolean isDecal();
static TrimPattern read(PacketWrapper<?> wrapper) {
return wrapper.readMappedEntityOrDirect(TrimPatterns::getById, TrimPattern::readDirect);
}
static TrimPattern readDirect(PacketWrapper<?> wrapper) {
ResourceLocation assetId = wrapper.readIdentifier();
ItemType templateItem = wrapper.readMappedEntity(ItemTypes::getById);
Component description = wrapper.readComponent();
boolean decal = wrapper.readBoolean();
return new StaticTrimPattern(assetId, templateItem, description, decal);
}
static void write(PacketWrapper<?> wrapper, TrimPattern pattern) {
wrapper.writeMappedEntityOrDirect(pattern, TrimPattern::writeDirect);
}
static void writeDirect(PacketWrapper<?> wrapper, TrimPattern pattern) {
wrapper.writeIdentifier(pattern.getAssetId());
wrapper.writeMappedEntity(pattern.getTemplateItem());
wrapper.writeComponent(pattern.getDescription());
wrapper.writeBoolean(pattern.isDecal());
}
}
@@ -0,0 +1,133 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.item.trimpattern;
import com.github.retrooper.packetevents.protocol.item.type.ItemType;
import com.github.retrooper.packetevents.protocol.item.type.ItemTypes;
import com.github.retrooper.packetevents.protocol.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 net.kyori.adventure.text.Component;
import java.util.HashMap;
import java.util.Map;
public class TrimPatterns {
private static final Map<String, TrimPattern> PATTERN_TYPE_MAP = new HashMap<>();
private static final Map<Byte, Map<Integer, TrimPattern>> PATTERN_TYPE_ID_MAP = new HashMap<>();
private static final TypesBuilder TYPES_BUILDER = new TypesBuilder("item/item_trim_pattern_mappings");
public static TrimPattern define(String key) {
ResourceLocation assetId = ResourceLocation.minecraft(key);
ItemType templateItem = ItemTypes.getByName(assetId + "_armor_trim_smithing_template");
Component description = Component.translatable("trim_pattern.minecraft." + key);
boolean decal = false;
return define(key, assetId, templateItem, description, decal);
}
public static TrimPattern define(
String key, ResourceLocation assetId, ItemType templateItem,
Component description, boolean decal
) {
TypesBuilderData data = TYPES_BUILDER.define(key);
TrimPattern pattern = new TrimPattern() {
@Override
public ResourceLocation getAssetId() {
return assetId;
}
@Override
public ItemType getTemplateItem() {
return templateItem;
}
@Override
public Component getDescription() {
return description;
}
@Override
public boolean isDecal() {
return decal;
}
@Override
public ResourceLocation getName() {
return data.getName();
}
@Override
public int getId(ClientVersion version) {
return TYPES_BUILDER.getDataIndex(version);
}
@Override
public boolean equals(Object obj) {
if (obj instanceof TrimPattern) {
return this.getName().equals(((TrimPattern) obj).getName());
}
return false;
}
};
MappingHelper.registerMapping(TYPES_BUILDER, PATTERN_TYPE_MAP, PATTERN_TYPE_ID_MAP, pattern);
return pattern;
}
// with key
public static TrimPattern getByName(String name) {
return PATTERN_TYPE_MAP.get(name);
}
public static TrimPattern getById(ClientVersion version, int id) {
int index = TYPES_BUILDER.getDataIndex(version);
Map<Integer, TrimPattern> idMap = PATTERN_TYPE_ID_MAP.get((byte) index);
return idMap.get(id);
}
// Added in 1.19.4
public static final TrimPattern COAST = define("coast");
public static final TrimPattern DUNE = define("dune");
public static final TrimPattern EYE = define("eye");
public static final TrimPattern RIB = define("rib");
public static final TrimPattern SENTRY = define("sentry");
public static final TrimPattern SNOUT = define("snout");
public static final TrimPattern SPIRE = define("spire");
public static final TrimPattern TIDE = define("tide");
public static final TrimPattern VEX = define("vex");
public static final TrimPattern WARD = define("ward");
public static final TrimPattern WILD = define("wild");
// Added in 1.20
public static final TrimPattern RAISER = define("raiser");
public static final TrimPattern HOST = define("host");
public static final TrimPattern SILENCE = define("silence");
public static final TrimPattern SHAPER = define("shaper");
public static final TrimPattern WAYFINDER = define("wayfinder");
// Added in 1.20.5
public static final TrimPattern BOLT = define("bolt");
public static final TrimPattern FLOW = define("flow");
static {
TYPES_BUILDER.unloadFileMappings();
}
}
@@ -18,6 +18,7 @@
package com.github.retrooper.packetevents.protocol.item.type;
import com.github.retrooper.packetevents.protocol.component.StaticComponentMap;
import com.github.retrooper.packetevents.protocol.mapper.MappedEntity;
import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
import org.jetbrains.annotations.Nullable;
@@ -39,4 +40,8 @@ public interface ItemType extends MappedEntity {
Set<ItemTypes.ItemAttribute> getAttributes();
boolean hasAttribute(ItemTypes.ItemAttribute attribute);
default StaticComponentMap getComponents() {
return StaticComponentMap.EMPTY;
}
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,58 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.mapper;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.resources.ResourceLocation;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
public class GenericMappedEntity implements StaticMappedEntity {
private final int id;
public GenericMappedEntity(ClientVersion ignoredVersion, int id) {
this(id);
}
public GenericMappedEntity(int id) {
this.id = id;
}
public static GenericMappedEntity getById(ClientVersion version, int id) {
return new GenericMappedEntity(version, id);
}
public static GenericMappedEntity read(PacketWrapper<?> wrapper) {
return wrapper.readMappedEntity(GenericMappedEntity::new);
}
public static void write(PacketWrapper<?> wrapper, GenericMappedEntity entity) {
wrapper.writeMappedEntity(entity);
}
@Override
public int getId() {
return this.id;
}
@Override
public ResourceLocation getName() {
throw new UnsupportedOperationException();
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 retrooper and contributors
* 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
@@ -22,7 +22,12 @@ import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.resources.ResourceLocation;
public interface MappedEntity {
ResourceLocation getName();
int getId(ClientVersion version);
default boolean isRegistered() {
return true;
}
}
@@ -0,0 +1,83 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.mapper;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.resources.ResourceLocation;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiFunction;
/**
* Either a key to a specific tag or a list of possible entities.
*/
public class MappedEntitySet<T> {
private final @Nullable ResourceLocation tagKey;
private final @Nullable List<T> entities;
public MappedEntitySet(ResourceLocation tagKey) {
this(tagKey, null);
}
public MappedEntitySet(List<T> entities) {
this(null, entities);
}
public MappedEntitySet(
@Nullable ResourceLocation tagKey,
@Nullable List<T> entities
) {
if (tagKey == null && entities == null) {
throw new IllegalArgumentException("Illegal generic holder set: either tag key or holder ids have to be set");
}
this.tagKey = tagKey;
this.entities = entities;
}
public static <Z extends MappedEntity> MappedEntitySet<Z> read(
PacketWrapper<?> wrapper, BiFunction<ClientVersion, Integer, Z> getter) {
int count = wrapper.readVarInt() - 1;
if (count == -1) {
return new MappedEntitySet<>(wrapper.readIdentifier(), null);
}
List<Z> entities = new ArrayList<>(Math.min(count, 65536));
for (int i = 0; i < count; i++) {
entities.add(wrapper.readMappedEntity(getter));
}
return new MappedEntitySet<>(null, entities);
}
public static <Z extends MappedEntity> void write(PacketWrapper<?> wrapper, MappedEntitySet<Z> set) {
if (set.tagKey != null) {
wrapper.writeByte(0);
wrapper.writeIdentifier(set.tagKey);
return;
}
assert set.entities != null; // can't be null, verified in ctor
wrapper.writeVarInt(set.entities.size() + 1);
for (Z entity : set.entities) {
wrapper.writeMappedEntity(entity);
}
}
}
@@ -94,4 +94,9 @@ public class NBTByte extends NBTNumber {
public NBTByte copy() {
return this;
}
@Override
public String toString() {
return "Byte(" + value + ")";
}
}
@@ -62,4 +62,9 @@ public class NBTByteArray extends NBT {
System.arraycopy(this.array, 0, abyte, 0, this.array.length);
return new NBTByteArray(abyte);
}
@Override
public String toString() {
return "ByteArray(" + Arrays.toString(array) + ")";
}
}
@@ -18,6 +18,8 @@
package com.github.retrooper.packetevents.protocol.nbt;
import org.jetbrains.annotations.Nullable;
import java.text.MessageFormat;
import java.util.Collections;
import java.util.LinkedHashMap;
@@ -45,6 +47,10 @@ public class NBTCompound extends NBT {
return Collections.unmodifiableMap(tags);
}
public int size() {
return tags.size();
}
public NBT getTagOrThrow(String key) {
NBT tag = getTagOrNull(key);
if (tag == null) {
@@ -53,7 +59,7 @@ public class NBTCompound extends NBT {
return tag;
}
public NBT getTagOrNull(String key) {
public @Nullable NBT getTagOrNull(String key) {
return tags.get(key);
}
@@ -68,7 +74,7 @@ public class NBTCompound extends NBT {
}
@SuppressWarnings("unchecked")
public <T extends NBT> T getTagOfTypeOrNull(String key, Class<T> type) {
public <T extends NBT> @Nullable T getTagOfTypeOrNull(String key, Class<T> type) {
NBT tag = getTagOrNull(key);
if (type.isInstance(tag)) {
return (T) tag;
@@ -86,7 +92,7 @@ public class NBTCompound extends NBT {
}
@SuppressWarnings("unchecked")
public <T extends NBT> NBTList<T> getTagListOfTypeOrNull(String key, Class<T> type) {
public <T extends NBT> @Nullable NBTList<T> getTagListOfTypeOrNull(String key, Class<T> type) {
NBTList<? extends NBT> list = getTagOfTypeOrNull(key, NBTList.class);
if ((list != null) && type.isAssignableFrom(list.getTagsType().getNBTClass())) {
return (NBTList<T>) list;
@@ -98,7 +104,7 @@ public class NBTCompound extends NBT {
return getTagOfTypeOrThrow(key, NBTCompound.class);
}
public NBTCompound getCompoundTagOrNull(String key) {
public @Nullable NBTCompound getCompoundTagOrNull(String key) {
return getTagOfTypeOrNull(key, NBTCompound.class);
}
@@ -106,7 +112,7 @@ public class NBTCompound extends NBT {
return getTagOfTypeOrThrow(key, NBTNumber.class);
}
public NBTNumber getNumberTagOrNull(String key) {
public @Nullable NBTNumber getNumberTagOrNull(String key) {
return getTagOfTypeOrNull(key, NBTNumber.class);
}
@@ -114,7 +120,7 @@ public class NBTCompound extends NBT {
return getTagOfTypeOrThrow(key, NBTString.class);
}
public NBTString getStringTagOrNull(String key) {
public @Nullable NBTString getStringTagOrNull(String key) {
return getTagOfTypeOrNull(key, NBTString.class);
}
@@ -122,7 +128,7 @@ public class NBTCompound extends NBT {
return getTagListOfTypeOrThrow(key, NBTCompound.class);
}
public NBTList<NBTCompound> getCompoundListTagOrNull(String key) {
public @Nullable NBTList<NBTCompound> getCompoundListTagOrNull(String key) {
return getTagListOfTypeOrNull(key, NBTCompound.class);
}
@@ -130,7 +136,7 @@ public class NBTCompound extends NBT {
return getTagListOfTypeOrThrow(key, NBTNumber.class);
}
public NBTList<NBTNumber> getNumberListTagOrNull(String key) {
public @Nullable NBTList<NBTNumber> getNumberListTagOrNull(String key) {
return getTagListOfTypeOrNull(key, NBTNumber.class);
}
@@ -138,7 +144,7 @@ public class NBTCompound extends NBT {
return getTagListOfTypeOrThrow(key, NBTString.class);
}
public NBTList<NBTString> getStringListTagOrNull(String key) {
public @Nullable NBTList<NBTString> getStringListTagOrNull(String key) {
return getTagListOfTypeOrNull(key, NBTString.class);
}
@@ -146,7 +152,7 @@ public class NBTCompound extends NBT {
return getStringTagOrThrow(key).getValue();
}
public String getStringTagValueOrNull(String key) {
public @Nullable String getStringTagValueOrNull(String key) {
NBT tag = getTagOrNull(key);
if (tag instanceof NBTString) {
return ((NBTString) tag).getValue();
@@ -222,4 +228,8 @@ public class NBTCompound extends NBT {
return tags.hashCode();
}
@Override
public String toString() {
return "Compound{" + tags + "}";
}
}
@@ -90,4 +90,9 @@ public class NBTDouble extends NBTNumber {
public NBTDouble copy() {
return this;
}
@Override
public String toString() {
return "Double(" + value + ")";
}
}
@@ -47,4 +47,9 @@ public class NBTEnd extends NBT {
public NBTEnd copy() {
return this;
}
@Override
public String toString() {
return "END";
}
}
@@ -90,4 +90,9 @@ public class NBTFloat extends NBTNumber {
public NBTFloat copy() {
return this;
}
@Override
public String toString() {
return "Float(" + value + ")";
}
}
@@ -90,4 +90,9 @@ public class NBTInt extends NBTNumber {
public NBTInt copy() {
return this;
}
@Override
public String toString() {
return "Int(" + value + ")";
}
}
@@ -63,4 +63,9 @@ public class NBTIntArray extends NBT {
System.arraycopy(this.array, 0, aint, 0, this.array.length);
return new NBTIntArray(aint);
}
@Override
public String toString() {
return "IntArray(" + Arrays.toString(array) + ")";
}
}
@@ -87,8 +87,16 @@ public class NBTList<T extends NBT> extends NBT {
tags.add(tag);
}
public void addTagUnsafe(int index, NBT nbt) {
addTag(index, (T) nbt);
}
public void addTagUnsafe(NBT nbt) {
addTag((T)nbt);
addTag((T) nbt);
}
public void removeTag(int index) {
tags.remove(index);
}
protected void validateAddTag(T tag) {
@@ -126,4 +134,9 @@ public class NBTList<T extends NBT> extends NBT {
}
return new NBTList<>(type, newTags);
}
@Override
public String toString() {
return "List(" + tags + ")";
}
}
@@ -90,4 +90,9 @@ public class NBTLong extends NBTNumber {
public NBTLong copy() {
return this;
}
@Override
public String toString() {
return "Long(" + value + ")";
}
}
@@ -63,4 +63,9 @@ public class NBTLongArray extends NBT {
System.arraycopy(this.array, 0, along, 0, this.array.length);
return new NBTLongArray(along);
}
@Override
public String toString() {
return "LongArray(" + Arrays.toString(array) + ")";
}
}
@@ -89,4 +89,9 @@ public class NBTShort extends NBTNumber {
public NBTShort copy() {
return this;
}
@Override
public String toString() {
return "Short(" + value + ")";
}
}
@@ -61,4 +61,9 @@ public class NBTString extends NBT {
public NBTString copy() {
return this;
}
@Override
public String toString() {
return "String(" + string + ")";
}
}
@@ -33,12 +33,12 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
public class NBTCodec {
//PacketEvents start: JSON -> NBT conversion method
@Deprecated
public static NBT jsonToNBT(JsonElement element) {
//Deal with the primitives first
if (element instanceof JsonPrimitive) {
@@ -102,6 +102,7 @@ public class NBTCodec {
//PacketEvents end
//PacketEvents start - NBT to JSON conversion
@Deprecated
public static JsonElement nbtToJson(NBT nbt, boolean parseByteAsBool) {
//TODO once I make my own nbt implementation, make a toJSON method that each nbt class implements to make this a one liner
if (nbt instanceof NBTNumber) {
@@ -147,11 +148,7 @@ public class NBTCodec {
}
//PacketEvents end
public static NBTCompound readNBTFromBuffer(Object byteBuf, ServerVersion serverVersion) {
return (NBTCompound) readRawNBTFromBuffer(byteBuf, serverVersion);
}
public static NBT readRawNBTFromBuffer(Object byteBuf, ServerVersion serverVersion) {
public static NBT readNBTFromBuffer(Object byteBuf, ServerVersion serverVersion) {
if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_8)) {
try {
final boolean named = serverVersion.isOlderThan(ServerVersion.V_1_20_2);
@@ -37,12 +37,16 @@ import com.github.retrooper.packetevents.protocol.packettype.clientbound.Clientb
import com.github.retrooper.packetevents.protocol.packettype.clientbound.ClientboundPacketType_1_19_4;
import com.github.retrooper.packetevents.protocol.packettype.clientbound.ClientboundPacketType_1_20_2;
import com.github.retrooper.packetevents.protocol.packettype.clientbound.ClientboundPacketType_1_20_3;
import com.github.retrooper.packetevents.protocol.packettype.clientbound.ClientboundPacketType_1_20_5;
import com.github.retrooper.packetevents.protocol.packettype.clientbound.ClientboundPacketType_1_7_10;
import com.github.retrooper.packetevents.protocol.packettype.clientbound.ClientboundPacketType_1_8;
import com.github.retrooper.packetevents.protocol.packettype.clientbound.ClientboundPacketType_1_9;
import com.github.retrooper.packetevents.protocol.packettype.clientbound.ClientboundPacketType_1_9_3;
import com.github.retrooper.packetevents.protocol.packettype.config.clientbound.ClientboundConfigPacketType_1_20_2;
import com.github.retrooper.packetevents.protocol.packettype.config.clientbound.ClientboundConfigPacketType_1_20_3;
import com.github.retrooper.packetevents.protocol.packettype.config.clientbound.ClientboundConfigPacketType_1_20_5;
import com.github.retrooper.packetevents.protocol.packettype.config.serverbound.ServerboundConfigPacketType_1_20_2;
import com.github.retrooper.packetevents.protocol.packettype.config.serverbound.ServerboundConfigPacketType_1_20_5;
import com.github.retrooper.packetevents.protocol.packettype.serverbound.ServerboundPacketType_1_12;
import com.github.retrooper.packetevents.protocol.packettype.serverbound.ServerboundPacketType_1_12_1;
import com.github.retrooper.packetevents.protocol.packettype.serverbound.ServerboundPacketType_1_13;
@@ -57,6 +61,7 @@ import com.github.retrooper.packetevents.protocol.packettype.serverbound.Serverb
import com.github.retrooper.packetevents.protocol.packettype.serverbound.ServerboundPacketType_1_19_4;
import com.github.retrooper.packetevents.protocol.packettype.serverbound.ServerboundPacketType_1_20_2;
import com.github.retrooper.packetevents.protocol.packettype.serverbound.ServerboundPacketType_1_20_3;
import com.github.retrooper.packetevents.protocol.packettype.serverbound.ServerboundPacketType_1_20_5;
import com.github.retrooper.packetevents.protocol.packettype.serverbound.ServerboundPacketType_1_7_10;
import com.github.retrooper.packetevents.protocol.packettype.serverbound.ServerboundPacketType_1_8;
import com.github.retrooper.packetevents.protocol.packettype.serverbound.ServerboundPacketType_1_9;
@@ -69,7 +74,9 @@ import java.util.HashMap;
import java.util.Map;
public final class PacketType {
private static boolean PREPARED = false;
//TODO UPDATE Update packet type mappings (clientbound pt. 1)
private static final VersionMapper CLIENTBOUND_PLAY_VERSION_MAPPER = new VersionMapper(
ClientVersion.V_1_7_10,
@@ -92,7 +99,8 @@ public final class PacketType {
ClientVersion.V_1_19_3,
ClientVersion.V_1_19_4,
ClientVersion.V_1_20_2,
ClientVersion.V_1_20_3);
ClientVersion.V_1_20_3,
ClientVersion.V_1_20_5);
//TODO UPDATE Update packet type mappings (serverbound pt. 1)
private static final VersionMapper SERVERBOUND_PLAY_VERSION_MAPPER = new VersionMapper(
@@ -112,16 +120,23 @@ public final class PacketType {
ClientVersion.V_1_19_3,
ClientVersion.V_1_19_4,
ClientVersion.V_1_20_2,
ClientVersion.V_1_20_3);
ClientVersion.V_1_20_3,
ClientVersion.V_1_20_5);
//TODO UPDATE Update packet type mappings (config clientbound pt. 1)
// TODO UPDATE Update packet type mappings (config clientbound pt. 1)
private static final VersionMapper CLIENTBOUND_CONFIG_VERSION_MAPPER = new VersionMapper(
ClientVersion.V_1_20_2,
ClientVersion.V_1_20_3);
ClientVersion.V_1_20_3,
ClientVersion.V_1_20_5);
// TODO UPDATE Update packet type mappings (config serverbound pt. 1)
private static final VersionMapper SERVERBOUND_CONFIG_VERSION_MAPPER = new VersionMapper(
ClientVersion.V_1_20_2,
ClientVersion.V_1_20_5);
public static void prepare() {
PacketType.Play.Client.load();
PacketType.Play.Server.load();
PacketType.Configuration.Client.load();
PacketType.Configuration.Server.load();
PREPARED = true;
}
@@ -158,7 +173,7 @@ public final class PacketType {
}
case CONFIGURATION:
if (side == PacketSide.CLIENT) {
return Configuration.Client.getById(packetID);
return Configuration.Client.getById(version, packetID);
} else {
return Configuration.Server.getById(version, packetID);
}
@@ -168,13 +183,15 @@ public final class PacketType {
}
public static class Handshaking {
public enum Client implements PacketTypeConstant, ServerBoundPacket {
HANDSHAKE(0),
/**
* Technically not part of the current protocol, but clients older than 1.7 will send this to initiate Server List Ping.
* 1.8 and newer servers will handle it correctly though.
*/
LEGACY_SERVER_LIST_PING(254);//0xFE in hex
LEGACY_SERVER_LIST_PING(0xFE);
private final int id;
@@ -186,7 +203,7 @@ public final class PacketType {
public static PacketTypeCommon getById(int packetID) {
if (packetID == 0) {
return HANDSHAKE;
} else if (packetID == 254) {
} else if (packetID == 0xFE) {
return LEGACY_SERVER_LIST_PING;
} else {
return null;
@@ -204,7 +221,8 @@ public final class PacketType {
}
public enum Server implements PacketTypeConstant, ClientBoundPacket {
LEGACY_SERVER_LIST_RESPONSE(254); //0xFE in hex
LEGACY_SERVER_LIST_RESPONSE(0xFE);
private final int id;
@@ -214,7 +232,7 @@ public final class PacketType {
@Nullable
public static PacketTypeCommon getById(int packetID) {
return packetID == 254 ? LEGACY_SERVER_LIST_RESPONSE : null;
return packetID == 0xFE ? LEGACY_SERVER_LIST_RESPONSE : null;
}
public int getId() {
@@ -229,9 +247,11 @@ public final class PacketType {
}
public static class Status {
public enum Client implements PacketTypeConstant, ServerBoundPacket {
REQUEST(0),
PING(1);
REQUEST(0x00),
PING(0x01);
private final int id;
@@ -254,7 +274,6 @@ public final class PacketType {
return id;
}
@Override
public PacketSide getSide() {
return PacketSide.CLIENT;
@@ -262,8 +281,9 @@ public final class PacketType {
}
public enum Server implements PacketTypeConstant, ClientBoundPacket {
RESPONSE(0),
PONG(1);
RESPONSE(0x00),
PONG(0x01);
private final int id;
@@ -294,13 +314,20 @@ public final class PacketType {
}
public static class Login {
public enum Client implements PacketTypeConstant, ServerBoundPacket {
LOGIN_START(0),
ENCRYPTION_RESPONSE(1),
///Added in 1.13
LOGIN_PLUGIN_RESPONSE(2),
//Added in 1.20.2
LOGIN_SUCCESS_ACK(3);
LOGIN_START(0x00),
ENCRYPTION_RESPONSE(0x01),
// Added in 1.13
LOGIN_PLUGIN_RESPONSE(0x02),
// Added in 1.20.2
LOGIN_SUCCESS_ACK(0x03),
// Added in 1.20.5
COOKIE_RESPONSE(0x04);
private final int id;
@@ -310,16 +337,19 @@ public final class PacketType {
@Nullable
public static PacketTypeCommon getById(int packetID) {
if (packetID == 0) {
return LOGIN_START;
} else if (packetID == 1) {
return ENCRYPTION_RESPONSE;
} else if (packetID == 2) {
return LOGIN_PLUGIN_RESPONSE;
} else if (packetID == 3) {
return LOGIN_SUCCESS_ACK;
} else {
return null;
switch (packetID) {
case 0x00:
return LOGIN_START;
case 0x01:
return ENCRYPTION_RESPONSE;
case 0x02:
return LOGIN_PLUGIN_RESPONSE;
case 0x03:
return LOGIN_SUCCESS_ACK;
case 0x04:
return COOKIE_RESPONSE;
default:
return null;
}
}
@@ -334,13 +364,19 @@ public final class PacketType {
}
public enum Server implements PacketTypeConstant, ClientBoundPacket {
DISCONNECT(0),
ENCRYPTION_REQUEST(1),
LOGIN_SUCCESS(2),
//Added in 1.8
SET_COMPRESSION(3),
///Added in 1.13
LOGIN_PLUGIN_REQUEST(4);
DISCONNECT(0x00),
ENCRYPTION_REQUEST(0x01),
LOGIN_SUCCESS(0x02),
// Added in 1.8
SET_COMPRESSION(0x03),
// Added in 1.13
LOGIN_PLUGIN_REQUEST(0x04),
// Added in 1.20.5
COOKIE_REQUEST(0x05);
private final int id;
@@ -351,16 +387,18 @@ public final class PacketType {
@Nullable
public static PacketTypeCommon getById(int packetID) {
switch (packetID) {
case 0:
case 0x00:
return DISCONNECT;
case 1:
case 0x01:
return ENCRYPTION_REQUEST;
case 2:
case 0x02:
return LOGIN_SUCCESS;
case 3:
case 0x03:
return SET_COMPRESSION;
case 4:
case 0x04:
return LOGIN_PLUGIN_REQUEST;
case 0x05:
return COOKIE_REQUEST;
default:
return null;
}
@@ -380,43 +418,72 @@ public final class PacketType {
// Added in 1.20.2
public static class Configuration {
public enum Client implements PacketTypeConstant, ServerBoundPacket {
public enum Client implements PacketTypeCommon, ServerBoundPacket {
CLIENT_SETTINGS(0x00),
PLUGIN_MESSAGE(0x01),
CONFIGURATION_END_ACK(0x02),
KEEP_ALIVE(0x03),
PONG(0x04),
RESOURCE_PACK_STATUS(0x05);
CLIENT_SETTINGS,
PLUGIN_MESSAGE,
CONFIGURATION_END_ACK,
KEEP_ALIVE,
PONG,
RESOURCE_PACK_STATUS,
private final int id;
// Added in 1.20.5
COOKIE_RESPONSE,
SELECT_KNOWN_PACKS;
Client(int id) {
this.id = id;
private static int INDEX = 0;
private static final Map<Byte, Map<Integer, PacketTypeCommon>> PACKET_TYPE_ID_MAP = new HashMap<>();
private final int[] ids;
Client() {
this.ids = new int[SERVERBOUND_CONFIG_VERSION_MAPPER.getVersions().length];
Arrays.fill(this.ids, -1);
}
public static void load() {
INDEX = 0;
loadPacketIds(ServerboundConfigPacketType_1_20_2.values());
loadPacketIds(ServerboundConfigPacketType_1_20_5.values());
// TODO UPDATE Update packet type mappings (config serverbound pt. 2)
}
private static void loadPacketIds(Enum<?>[] enumConstants) {
int index = INDEX;
for (Enum<?> constant : enumConstants) {
int id = constant.ordinal();
Configuration.Client value = Configuration.Client.valueOf(constant.name());
value.ids[index] = id;
Map<Integer, PacketTypeCommon> packetIdMap = PACKET_TYPE_ID_MAP.computeIfAbsent((byte) index, k -> new HashMap<>());
packetIdMap.put(id, value);
}
INDEX++;
}
public static @Nullable PacketTypeCommon getById(int packetId) {
switch (packetId) {
case 0x00:
return CLIENT_SETTINGS;
case 0x01:
return PLUGIN_MESSAGE;
case 0x02:
return CONFIGURATION_END_ACK;
case 0x03:
return KEEP_ALIVE;
case 0x04:
return PONG;
case 0x05:
return RESOURCE_PACK_STATUS;
default:
return null;
return getById(ClientVersion.getLatest(), packetId);
}
public static @Nullable PacketTypeCommon getById(ClientVersion version, int packetId) {
if (!PREPARED) {
PacketType.prepare();
}
int index = SERVERBOUND_CONFIG_VERSION_MAPPER.getIndex(version);
Map<Integer, PacketTypeCommon> map = PACKET_TYPE_ID_MAP.get((byte) index);
return map.get(packetId);
}
@Deprecated
public int getId() {
return this.getId(ClientVersion.getLatest());
}
@Override
public int getId() {
return this.id;
public int getId(ClientVersion version) {
if (!PREPARED) {
PacketType.prepare();
}
int index = SERVERBOUND_CONFIG_VERSION_MAPPER.getIndex(version);
return this.ids[index];
}
@Override
@@ -437,8 +504,15 @@ public final class PacketType {
UPDATE_ENABLED_FEATURES,
UPDATE_TAGS,
// added in 1.20.3
RESOURCE_PACK_REMOVE;
// Added in 1.20.3
RESOURCE_PACK_REMOVE,
// Added in 1.20.5
COOKIE_REQUEST,
RESET_CHAT,
STORE_COOKIE,
TRANSFER,
SELECT_KNOWN_PACKS;
private static int INDEX = 0;
private static final Map<Byte, Map<Integer, PacketTypeCommon>> PACKET_TYPE_ID_MAP = new HashMap<>();
@@ -453,6 +527,7 @@ public final class PacketType {
INDEX = 0;
loadPacketIds(ClientboundConfigPacketType_1_20_2.values());
loadPacketIds(ClientboundConfigPacketType_1_20_3.values());
loadPacketIds(ClientboundConfigPacketType_1_20_5.values());
// TODO UPDATE Update packet type mappings (config clientbound pt. 2)
}
@@ -503,8 +578,10 @@ public final class PacketType {
}
public static class Play {
public enum Client implements PacketTypeCommon, ServerBoundPacket {
//Packets that no longer exist on the latest version
// Packets which no longer exist on the latest version
CHAT_PREVIEW,
TELEPORT_CONFIRM,
@@ -557,18 +634,28 @@ public final class PacketType {
SPECTATE,
PLAYER_BLOCK_PLACEMENT,
USE_ITEM,
//Added in 1.19
// Added in 1.19
CHAT_COMMAND,
//Added in 1.19.1
// Added in 1.19.1
CHAT_ACK,
//Added in 1.19.3
// Added in 1.19.3
CHAT_SESSION_UPDATE,
//Added in 1.20.2
// Added in 1.20.2
CHUNK_BATCH_ACK,
CONFIGURATION_ACK,
DEBUG_PING,
//Added in 1.20.3
SLOT_STATE_CHANGE;
// Added in 1.20.3
SLOT_STATE_CHANGE,
// Added in 1.20.5
CHAT_COMMAND_UNSIGNED,
COOKIE_RESPONSE,
DEBUG_SAMPLE_SUBSCRIPTION;
private static int INDEX = 0;
private static final Map<Byte, Map<Integer, PacketTypeCommon>> PACKET_TYPE_ID_MAP = new HashMap<>();
@@ -621,6 +708,7 @@ public final class PacketType {
loadPacketIds(ServerboundPacketType_1_19_4.values());
loadPacketIds(ServerboundPacketType_1_20_2.values());
loadPacketIds(ServerboundPacketType_1_20_3.values());
loadPacketIds(ServerboundPacketType_1_20_5.values());
//TODO UPDATE Update packet type mappings (serverbound pt. 2)
}
@@ -639,7 +727,8 @@ public final class PacketType {
}
public enum Server implements PacketTypeCommon, ClientBoundPacket {
//Packets that are no longer present on latest version
// Packets which are no longer exist on the latest version
SET_COMPRESSION,
MAP_CHUNK_BULK,
UPDATE_ENTITY_NBT,
@@ -662,7 +751,7 @@ public final class PacketType {
UPDATE_ENABLED_FEATURES,
SPAWN_PLAYER,
//Okay these are normal ones
// Still existing packets
WINDOW_CONFIRMATION,
SPAWN_ENTITY,
SPAWN_EXPERIENCE_ORB,
@@ -762,37 +851,44 @@ public final class PacketType {
TAGS,
CHAT_MESSAGE,
//Added in 1.19
// Added in 1.19
ACKNOWLEDGE_BLOCK_CHANGES,
SERVER_DATA,
SYSTEM_CHAT_MESSAGE,
//Added in 1.19.1
// Added in 1.19.1
DELETE_CHAT,
CUSTOM_CHAT_COMPLETIONS,
//Added in 1.19.3
// Added in 1.19.3
DISGUISED_CHAT,
PLAYER_INFO_REMOVE,
PLAYER_INFO_UPDATE,
//Added in 1.19.4
// Added in 1.19.4
DAMAGE_EVENT,
HURT_ANIMATION,
BUNDLE,
CHUNK_BIOMES,
//Added in 1.20.2
// Added in 1.20.2
CHUNK_BATCH_END,
CHUNK_BATCH_BEGIN,
DEBUG_PONG,
CONFIGURATION_START,
//Added in 1.20.3
// Added in 1.20.3
RESET_SCORE,
RESOURCE_PACK_REMOVE,
TICKING_STATE,
TICKING_STEP;
TICKING_STEP,
// Added in 1.20.5
COOKIE_REQUEST,
DEBUG_SAMPLE,
STORE_COOKIE,
TRANSFER,
PROJECTILE_POWER;
private static int INDEX = 0;
private static final Map<Byte, Map<Integer, PacketTypeCommon>> PACKET_TYPE_ID_MAP = new HashMap<>();
@@ -861,6 +957,7 @@ public final class PacketType {
loadPacketIds(ClientboundPacketType_1_19_4.values());
loadPacketIds(ClientboundPacketType_1_20_2.values());
loadPacketIds(ClientboundPacketType_1_20_3.values());
loadPacketIds(ClientboundPacketType_1_20_5.values());
//TODO UPDATE Update packet type mappings (clientbound pt. 2)
}
}
@@ -0,0 +1,145 @@
/*
* 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.packettype.clientbound;
public enum ClientboundPacketType_1_20_5 {
BUNDLE,
SPAWN_ENTITY,
SPAWN_EXPERIENCE_ORB,
ENTITY_ANIMATION,
STATISTICS,
ACKNOWLEDGE_BLOCK_CHANGES,
BLOCK_BREAK_ANIMATION,
BLOCK_ENTITY_DATA,
BLOCK_ACTION,
BLOCK_CHANGE,
BOSS_BAR,
SERVER_DIFFICULTY,
CHUNK_BATCH_END,
CHUNK_BATCH_BEGIN,
CHUNK_BIOMES,
CLEAR_TITLES,
TAB_COMPLETE,
DECLARE_COMMANDS,
CLOSE_WINDOW,
WINDOW_ITEMS,
WINDOW_PROPERTY,
SET_SLOT,
COOKIE_REQUEST, // New packet
SET_COOLDOWN,
CUSTOM_CHAT_COMPLETIONS,
PLUGIN_MESSAGE,
DAMAGE_EVENT,
DEBUG_SAMPLE, // New packet
DELETE_CHAT,
DISCONNECT,
DISGUISED_CHAT,
ENTITY_STATUS,
EXPLOSION,
UNLOAD_CHUNK,
CHANGE_GAME_STATE,
OPEN_HORSE_WINDOW,
HURT_ANIMATION,
INITIALIZE_WORLD_BORDER,
KEEP_ALIVE,
CHUNK_DATA,
EFFECT,
PARTICLE,
UPDATE_LIGHT,
JOIN_GAME,
MAP_DATA,
MERCHANT_OFFERS,
ENTITY_RELATIVE_MOVE,
ENTITY_RELATIVE_MOVE_AND_ROTATION,
ENTITY_ROTATION,
VEHICLE_MOVE,
OPEN_BOOK,
OPEN_WINDOW,
OPEN_SIGN_EDITOR,
PING,
DEBUG_PONG,
CRAFT_RECIPE_RESPONSE,
PLAYER_ABILITIES,
CHAT_MESSAGE,
END_COMBAT_EVENT,
ENTER_COMBAT_EVENT,
DEATH_COMBAT_EVENT,
PLAYER_INFO_REMOVE,
PLAYER_INFO_UPDATE,
FACE_PLAYER,
PLAYER_POSITION_AND_LOOK,
UNLOCK_RECIPES,
DESTROY_ENTITIES,
REMOVE_ENTITY_EFFECT,
RESET_SCORE,
RESOURCE_PACK_REMOVE,
RESOURCE_PACK_SEND,
RESPAWN,
ENTITY_HEAD_LOOK,
MULTI_BLOCK_CHANGE,
SELECT_ADVANCEMENTS_TAB,
SERVER_DATA,
ACTION_BAR,
WORLD_BORDER_CENTER,
WORLD_BORDER_LERP_SIZE,
WORLD_BORDER_SIZE,
WORLD_BORDER_WARNING_DELAY,
WORLD_BORDER_WARNING_REACH,
CAMERA,
HELD_ITEM_CHANGE,
UPDATE_VIEW_POSITION,
UPDATE_VIEW_DISTANCE,
SPAWN_POSITION,
DISPLAY_SCOREBOARD,
ENTITY_METADATA,
ATTACH_ENTITY,
ENTITY_VELOCITY,
ENTITY_EQUIPMENT,
SET_EXPERIENCE,
UPDATE_HEALTH,
SCOREBOARD_OBJECTIVE,
SET_PASSENGERS,
TEAMS,
UPDATE_SCORE,
UPDATE_SIMULATION_DISTANCE,
SET_TITLE_SUBTITLE,
TIME_UPDATE,
SET_TITLE_TEXT,
SET_TITLE_TIMES,
ENTITY_SOUND_EFFECT,
SOUND_EFFECT,
CONFIGURATION_START,
STOP_SOUND,
STORE_COOKIE, // New packet
SYSTEM_CHAT_MESSAGE,
PLAYER_LIST_HEADER_AND_FOOTER,
NBT_QUERY_RESPONSE,
COLLECT_ITEM,
ENTITY_TELEPORT,
TICKING_STATE,
TICKING_STEP,
TRANSFER, // New packet
UPDATE_ADVANCEMENTS,
UPDATE_ATTRIBUTES,
ENTITY_EFFECT,
DECLARE_RECIPES,
TAGS,
PROJECTILE_POWER, // New packet
}
@@ -0,0 +1,38 @@
/*
* 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.packettype.config.clientbound;
public enum ClientboundConfigPacketType_1_20_5 {
COOKIE_REQUEST, // New packet
PLUGIN_MESSAGE,
DISCONNECT,
CONFIGURATION_END,
KEEP_ALIVE,
PING,
RESET_CHAT, // New packet
REGISTRY_DATA,
RESOURCE_PACK_REMOVE,
RESOURCE_PACK_SEND,
STORE_COOKIE, // New packet
TRANSFER, // New packet
UPDATE_ENABLED_FEATURES,
UPDATE_TAGS,
SELECT_KNOWN_PACKS, // New packet
}
@@ -0,0 +1,29 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.packettype.config.serverbound;
public enum ServerboundConfigPacketType_1_20_2 {
CLIENT_SETTINGS,
PLUGIN_MESSAGE,
CONFIGURATION_END_ACK,
KEEP_ALIVE,
PONG,
RESOURCE_PACK_STATUS,
}
@@ -0,0 +1,31 @@
/*
* 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.packettype.config.serverbound;
public enum ServerboundConfigPacketType_1_20_5 {
CLIENT_SETTINGS,
COOKIE_RESPONSE, // New packet
PLUGIN_MESSAGE,
CONFIGURATION_END_ACK,
KEEP_ALIVE,
PONG,
RESOURCE_PACK_STATUS,
SELECT_KNOWN_PACKS, // New packet
}
@@ -0,0 +1,81 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.packettype.serverbound;
public enum ServerboundPacketType_1_20_5 {
TELEPORT_CONFIRM,
QUERY_BLOCK_NBT,
SET_DIFFICULTY,
CHAT_ACK,
CHAT_COMMAND_UNSIGNED, // "New" packet
CHAT_COMMAND,
CHAT_MESSAGE,
CHAT_SESSION_UPDATE,
CHUNK_BATCH_ACK,
CLIENT_STATUS,
CLIENT_SETTINGS,
TAB_COMPLETE,
CONFIGURATION_ACK,
CLICK_WINDOW_BUTTON,
CLICK_WINDOW,
CLOSE_WINDOW,
SLOT_STATE_CHANGE,
COOKIE_RESPONSE, // New packet
PLUGIN_MESSAGE,
DEBUG_SAMPLE_SUBSCRIPTION, // New packet
EDIT_BOOK,
QUERY_ENTITY_NBT,
INTERACT_ENTITY,
GENERATE_STRUCTURE,
KEEP_ALIVE,
LOCK_DIFFICULTY,
PLAYER_POSITION,
PLAYER_POSITION_AND_ROTATION,
PLAYER_ROTATION,
PLAYER_FLYING,
VEHICLE_MOVE,
STEER_BOAT,
PICK_ITEM,
DEBUG_PING,
CRAFT_RECIPE_REQUEST,
PLAYER_ABILITIES,
PLAYER_DIGGING,
ENTITY_ACTION,
STEER_VEHICLE,
PONG,
SET_RECIPE_BOOK_STATE,
SET_DISPLAYED_RECIPE,
NAME_ITEM,
RESOURCE_PACK_STATUS,
ADVANCEMENT_TAB,
SELECT_TRADE,
SET_BEACON_EFFECT,
HELD_ITEM_CHANGE,
UPDATE_COMMAND_BLOCK,
UPDATE_COMMAND_BLOCK_MINECART,
CREATIVE_INVENTORY_ACTION,
UPDATE_JIGSAW_BLOCK,
UPDATE_STRUCTURE_BLOCK,
UPDATE_SIGN,
ANIMATION,
SPECTATE,
PLAYER_BLOCK_PLACEMENT,
USE_ITEM,
}
@@ -20,33 +20,47 @@ package com.github.retrooper.packetevents.protocol.particle;
import com.github.retrooper.packetevents.protocol.particle.data.ParticleData;
import com.github.retrooper.packetevents.protocol.particle.type.ParticleType;
import com.github.retrooper.packetevents.protocol.particle.type.ParticleTypes;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
public class Particle {
private ParticleType type;
private ParticleData data;
public class Particle<T extends ParticleData> {
public Particle(ParticleType type, ParticleData data) {
private ParticleType<T> type;
private T data;
public Particle(ParticleType<T> type, T data) {
this.type = type;
this.data = data;
}
public Particle(ParticleType type) {
this(type, new ParticleData());
public Particle(ParticleType<T> type) {
this(type, ParticleData.emptyData());
}
public ParticleType getType() {
return type;
@SuppressWarnings("unchecked") // will work on runtime
public static Particle<?> read(PacketWrapper<?> wrapper) {
ParticleType<?> type = wrapper.readMappedEntity(ParticleTypes::getById);
return new Particle<>((ParticleType<ParticleData>) type, type.readData(wrapper));
}
public void setType(ParticleType type) {
public static <T extends ParticleData> void write(PacketWrapper<?> wrapper, Particle<T> particle) {
wrapper.writeMappedEntity(particle.type);
particle.getType().writeData(wrapper, particle.data);
}
public ParticleType<T> getType() {
return this.type;
}
public void setType(ParticleType<T> type) {
this.type = type;
}
public ParticleData getData() {
return data;
public T getData() {
return this.data;
}
public void setData(ParticleData data) {
public void setData(T data) {
this.data = data;
}
}
@@ -0,0 +1,55 @@
/*
* 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.particle.data;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
public class ParticleColorData extends ParticleData {
private int color;
public ParticleColorData(int color) {
this.color = color;
}
public static ParticleColorData read(PacketWrapper<?> wrapper) {
int color = wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_20_5) ? wrapper.readInt() : 0;
return new ParticleColorData(color);
}
public static void write(PacketWrapper<?> wrapper, ParticleColorData data) {
if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_20_5)) {
wrapper.writeInt(data.color);
}
}
public int getColor() {
return this.color;
}
public void setColor(int color) {
this.color = color;
}
@Override
public boolean isEmpty() {
return false;
}
}
Loaded 100 of 266 files, more files were not shown because too many files have changed in this diff. Show more