Compare commits

...
Author SHA1 Message Date
retrooper 8f7ec3d38a PacketEvents 2.1.0 release 2023-11-27 19:18:01 +01:00
retrooper 41969994b2 EntityMetadataProvider has been added, to allow potential packetevents addons to add on to our metadata abstraction. 2023-11-27 19:01:12 +01:00
retrooper 4a2146d16d Merge pull request #622 from rexlManu/2.0
Relocate only the gson and legacy
2023-11-16 20:02:18 +01:00
Emmanuel Lampe 079a2fcc53 Relocate kyori legacy and gson separate for bungeecord 2023-11-15 03:17:02 +01:00
Emmanuel Lampe b9d4ed6a60 Relocate kyori legacy and gson separate 2023-11-15 03:16:09 +01:00
retrooper aec45f19e4 Merge pull request #619 from KaspianDev/fix-merchantoffers
Fix merchant offers always being empty
2023-11-10 17:17:31 +01:00
KaspianDev 0aaa4f42b1 Fix merchant offers always being empty 2023-11-10 16:52:49 +01:00
retrooper 75dfc63d3b Merge pull request #618 from SoSeDiK/blockId
Expose block id to BaseChunk
2023-11-07 18:34:37 +01:00
retrooper ac501a26b2 Fix the way we access NetworkManager (recent server builds have changed it) 2023-11-04 23:03:23 +01:00
SoSeDiK 3ebf39d3bd Expose block id to BaseChunk 2023-11-03 21:17:20 +02:00
retrooper 363931875f Stop depending on funkemunky jars. 2023-11-01 11:11:55 +01:00
retrooper b1802fbc0c Merge pull request #613 from 4drian3d/velocity-changes
Some Velocity module improvements
2023-11-01 10:30:18 +01:00
retrooper 9f9cdca53a Fix connection state issues and casting issues with events 2023-11-01 10:29:27 +01:00
Adrian 00c85f3e41 Some Velocity module improvements
- Removed PostOrder LATE usage
- Use Injected PluginContainer
- Disabled debug mode by default
- Replace deprecated method
2023-10-17 10:36:18 -05:00
retrooper b48a91bcee PotionTypes.getById works now 2023-10-11 19:18:47 +02:00
retrooper 709edd8b21 Merge pull request #610 from AbhigyaKrishna/2.0
Retain backward compatibility with adventure 5.0.0
2023-10-11 18:57:45 +02:00
retrooper 90edf6002e PotionTypes now requires a version to work correctly. 2023-10-11 18:04:30 +02:00
retrooper 4e151f8dfb Pushing out 2.1.0 snapshot for 1.20.2 update 2023-10-07 17:14:07 +02:00
retrooper 0165e8a4ac Merge pull request #607 from booky10/dev/1.20.2
1.20.2 update
2023-10-06 23:48:39 +02:00
retrooper 385000b608 * Add full support for PacketConfigReceive & SendEvent
* WrapperConfigClientClientSettings renamed to WrapperConfigClientSettings
2023-10-06 23:42:54 +02:00
booky10 a1b7c947a0 Use ServerVersion instead of ClientVersion for potion effects 2023-10-03 14:58:31 +02:00
Abhigya ab5163bc66 Retain backward compatibility with adventure 5.0.0 2023-10-02 00:41:27 +05:30
booky10 38b25b6d48 Fix wrapper name for debug pong packet
It's not chunk related, just a copy-paste error
2023-09-27 22:42:25 +02:00
booky10 9d5d4858cf Fix blockstate mappings index 2023-09-23 00:48:32 +02:00
booky10 2e6c43ba06 Extract dimension information from registry data packet instead of login packet 2023-09-22 20:32:30 +02:00
booky10 f180a4a172 Fix packet wrapper constructor parameter types 2023-09-22 20:31:56 +02:00
booky10 5ce6b8bf9e Fix missing clientbound configuration packettype 2023-09-22 20:24:22 +02:00
booky10 b61602741b Rebase on latest changes 2023-09-22 20:24:08 +02:00
booky10 13ba9e7b81 Switch protocol after receiving signaling packet 2023-09-22 20:18:00 +02:00
booky10 d4c9444fd5 Separate encoder and decoder protocol state 2023-09-22 20:17:11 +02:00
booky10 b6c079af66 Add packet wrappers for nearly all new packets in 1.20.2
Only one missing is tags update, which already didn't have a wrapper before
2023-09-22 20:17:11 +02:00
booky10 a18d288079 Update packet structures for 1.20.2 2023-09-22 20:17:09 +02:00
booky10 c3d8f91e85 Update all mappings for 1.20.2 2023-09-22 20:16:37 +02:00
retrooper 0ca2f5c50a Minor tweaks to velocity (update api) 2023-09-22 15:21:47 +02:00
retrooper cdc7ed36e0 PacketEvents 2.0.2 update 2023-09-13 16:01:41 +02:00
retrooper 5d63308a22 Delete WrapperPlayServerChunkData default values 2023-09-13 15:36:20 +02:00
retrooper 214706dbb6 Fix update checker colors 2023-09-12 00:59:18 +02:00
retrooper fa3b563c70 2.0.1 release 2023-09-12 00:36:31 +02:00
retrooper 55e31483e7 Changes to naming of WrapperPlayServerHurtAnimation 2023-09-12 00:02:38 +02:00
retrooper aa34910468 Update User#getWorldNBT usages to handle a nullable value. 2023-09-11 23:35:11 +02:00
retrooper 5e44913a5e Sending packets on proxies is now supported!
* ChannelInjector#isProxy added to detect if our implementation is running on a proxy
2023-08-31 20:25:27 +02:00
retrooper b8dc964112 Add jenkins builds on README 2023-08-31 10:40:57 +02:00
retrooper 890844fb60 Fix broken link in README 2023-08-31 10:40:08 +02:00
retrooper fc57c9e077 Update README 2023-08-31 09:46:32 +02:00
retrooper f12ef113aa Fixed packet-modification on BungeeCord. 2023-08-26 22:35:29 +02:00
retrooper e8144ece97 Minor fix to 1.12 item type mappings. 2023-08-24 18:42:48 +02:00
retrooper b611ad5522 Update to 1.20 bungeecord API for packetevents 2.0.0 2023-08-22 19:47:15 +02:00
retrooper 53e1014c8d Cleanup to build.gradle for 2.0.0 rollout 2023-08-22 19:15:43 +02:00
retrooper 69f992a984 PacketEvents 2.0.0 release rollout 2023-08-22 19:12:53 +02:00
retrooper fde9db39b7 Update README 2023-08-22 18:19:26 +02:00
retrooper 6c6a2535c8 Don't think getEntityById is a function that can be fixed 2023-08-22 18:01:31 +02:00
retrooper 23d06075dd Fix BungeeCord injector, you may now listen to packets on proxies. 2023-08-22 17:39:19 +02:00
retrooper 926fd1ae50 Set default values for data inside ChunkData wrapper 2023-08-22 15:04:12 +02:00
AoElite 756add003f Catch exceptions not throwables for events 2023-08-17 18:48:14 -04:00
retrooper 800ffafb96 Update README.md 2023-07-15 19:16:11 +02:00
AoElite ba2d9ae9f0 Merge pull request #598 from clrxbl/fix/chest-block-attributes
Fix chest block attribute order
2023-07-04 18:20:33 -04:00
Michael 31d07e4a39 Fix chest block attribute order 2023-07-05 00:07:12 +02:00
retrooper ec36a5d1d8 Set reEncodeByDefault to true by default 2023-06-29 11:53:04 +02:00
retrooper 08ba59e1d9 Merge pull request #596 from SamB440/fix/mosaic
More block tag fixes
2023-06-28 19:47:51 +02:00
retrooper 851c74e827 Merge pull request #597 from SamB440/feat/item-tags-one-twenty
Update ItemTags to 1.20
2023-06-28 19:47:05 +02:00
SamB440 b31893e035 Update ItemTags to 1.20 2023-06-27 13:51:35 +01:00
SamB440 4718fb985d Might as well add all new 1.20 tags 2023-06-26 22:07:18 +01:00
SamB440 aed9bc14fa Add SWORD_EFFICIENT block tag 2023-06-26 21:56:30 +01:00
SamB440 1daad13da3 Mosaic + step sound blocks 2023-06-26 21:43:58 +01:00
retrooper 65a984e805 Fix NPC#updateTabPing 2023-06-26 22:15:30 +02:00
retrooper a923b950f6 Add getters for WrapperPlayServerBlockChange 2023-06-25 00:29:02 +02:00
retrooper ac5790411f MessageSignData is no longer an optional in chat message wrapper, but the signature bytes can be set to length 0, to indicate that it is not present, otherwise it is. 2023-06-25 00:25:07 +02:00
retrooper cd3449ade2 Newer chat message wrappers extend chat message_v_16 to simplify usage for users aiming 1.16+ 2023-06-23 20:27:25 +02:00
retrooper 75af221f77 Account for fake players that trigger onJoin event. 2023-06-19 17:48:36 +02:00
retrooper 6f9b2cf5e9 Deprecate ChatMessage_v1_19_3 2023-06-19 17:39:32 +02:00
retrooper 4b4dd492cf Fix ChatMessage_v1_19_3#setChatContent 2023-06-19 17:35:35 +02:00
retrooper 68471d32c8 Fix ChatMessage_v1_19_3#setChatContent to update the plainContent 2023-06-18 08:50:33 +02:00
retrooper b7d0ce9518 Make ChatMessage_v1_19_3#unsignedChatContent nullable, getter returns an optional 2023-06-17 23:35:46 +02:00
retrooper 58abfc0c1e Merge pull request #594 from AbhigyaKrishna/2.0
1.19.3 ChatMessage fix
2023-06-17 23:31:48 +02:00
AbhigyaKrishna a3f6adac2f More effective case check for 1.19.1 chat component 2023-06-18 02:53:39 +05:30
AbhigyaKrishna f0c9af4464 Revert "Fix ChatMessageProcessor_v1_19_3's unsignedChatContent being null"
This reverts commit f43fff899f.
2023-06-18 02:52:25 +05:30
retrooper f43fff899f Fix ChatMessageProcessor_v1_19_3's unsignedChatContent being null 2023-06-17 23:14:33 +02:00
AbhigyaKrishna 9291fd8953 1.19.3 ChatMessage fix 2023-06-18 02:34:48 +05:30
retrooper feb975010e Fix 1.19.3+ outgoing chat processing. LastSeenMessages -> LastSeenMessages.Packed 2023-06-16 22:47:15 +02:00
retrooper 5c34c8e6c3 Cleanup of Optional uses 2023-06-16 22:46:11 +02:00
retrooper 8aaf40fc74 Now able to detect 1.20.1 servers. 2023-06-14 23:21:10 +02:00
retrooper c6fcab2923 Merge remote-tracking branch 'origin/2.0' into 2.0 2023-06-14 17:55:27 +02:00
retrooper 64006b91a4 Fix particle importing on 1.8 2023-06-14 17:55:09 +02:00
DefineOutside 625a66f45a Merge pull request #592 from AoElite/2.0
Add cracked state value
2023-06-12 21:13:44 -05:00
AoElite 0c6208f931 add cracked state value 2023-06-12 22:11:37 -04:00
retrooper be32f464c5 Merge pull request #591 from SamB440/fix/block-tags
Fix missing block tag states
2023-06-12 22:13:12 +02:00
SamB440 3389baf40e More missing block tag states 2023-06-12 20:45:26 +01:00
retrooper edc85e68e8 Update copyright year 2023-06-12 20:14:05 +02:00
SamB440 3f9f093934 Fix missing block tag states 2023-06-12 19:09:25 +01:00
retrooper 31426cc69c Add WrapperPlayServerBundle wrapper. 2023-06-12 19:54:33 +02:00
retrooper cec8c9789f SHAPER_ARMOR_TRIM_SMITHING_TEMPLATE fixed 2023-06-12 17:30:38 +02:00
retrooper f771e15ce0 * Added new StateTypes for 1.20 minecraft
* SUSPICIOUS_SAND now has an assigned tool(a shovel), and has been updated (since 1.20)
2023-06-12 17:04:28 +02:00
retrooper 68a3702cd6 ItemType key is always lowercased 2023-06-12 15:21:59 +02:00
retrooper 8f4f688fb8 Update WrappedBlockState mappings, still need to add new state types i believe 2023-06-12 00:35:54 +02:00
retrooper 0a380344c5 Updated particle type mappings to 1.20 minecraft 2023-06-11 23:16:46 +02:00
retrooper ab458ded62 Rename "var_long" to "long" in EntityDataTypes 2023-06-11 22:50:12 +02:00
retrooper 3bc78c1aec ItemType mappings updated, new item types added to API 2023-06-11 22:22:39 +02:00
retrooper 0feebb6819 Fix chat wrapper for 1.19.3+ 2023-06-11 12:34:52 +02:00
retrooper cdb48e0ab6 Fix chat & encryption wrapper (salt signature processing) 2023-06-11 12:20:41 +02:00
retrooper 85e819d72f Fix AdventureReflectionUtil 2023-06-11 10:50:10 +02:00
retrooper 10d44fe3cb Update adventure to 4.14.0 2023-06-11 10:31:34 +02:00
retrooper 6b5ada3c5d Update all wrappers for 1.20 minecraft 2023-06-11 10:08:45 +02:00
retrooper 2f0861c7b7 Update build.gradle to spigot 1.20 2023-06-11 09:45:17 +02:00
DefineOutside abc8695a29 Merge pull request #590 from AoElite/2.0
Add 1.20 protocol
2023-06-08 08:01:42 -05:00
AoElite c6577646ce remove _0 2023-06-08 07:50:12 -04:00
AoElite a6c68b2d0e minimal 1.20 update 2023-06-07 18:12:59 -04:00
DefineOutside 23e0861192 Merge pull request #585 from ammodev/2.0
fix: Block State 1.19.4
2023-06-01 08:49:51 -05:00
MWHunter 7539aa345c add better debug to entity metadata 2023-05-29 18:52:30 -05:00
Simon 2a076a61a0 fix: Accidental code deletion
Due to me not wanting to push my own sorting for imports and stuff I accidentally deleted some lines of code. Now fixed.
2023-05-27 00:54:12 +02:00
Simon bf0ec04cec fix: Block State 1.19.4
Fixed a bug in which the block state could not be mapped. Used in the new BlockDisplays
2023-05-27 00:47:55 +02:00
DefineOutside fea687bba9 Merge pull request #584 from Offenderify/fix/block_data_packet
Fix block entity data packet
2023-05-23 20:34:55 -05:00
DefineOutside 25e83d6181 Merge pull request #579 from minus1ms/2.0
Add WrapperPlayServerDeclareCommands
2023-05-23 20:32:53 -05:00
Offenderify 95a91bb1f2 fix: block entity data packet 2023-05-20 15:10:58 +03:00
MWHunter e1e057eabb fix some 1.8 errors and exceptions 2023-05-14 16:36:47 -05:00
retrooper f81120f8ed Merge pull request #575 from Aseeef/2.0
Added a Conversion Util to convert to/from PacketEvents to Bukkit Particles
2023-05-13 20:31:26 +02:00
minus1ms e44ad5edc2 better name of method
read is more self-explaining than get
2023-05-01 18:10:06 +02:00
minus1ms c35d0854bc Added nullable annotation where it should be 2023-05-01 18:01:47 +02:00
minus1ms 47dbb5e9c0 Add WrapperPlayServerDeclareCommands
added WrapperPlayServerDeclareCommands

im not sure if i did Parsers and Node in good way and im not sure if these are in good packages, everything works as intended
2023-04-30 18:47:55 +02:00
Aseeef 702894dd07 Merge branch 'retrooper:2.0' into 2.0 2023-04-26 17:05:54 -04:00
MWHunter 4801196942 move adventure serializer to adventure util package 2023-04-24 10:24:47 -05:00
retrooper c88a9c412c Ignore modern spoofed players 2023-04-23 22:42:13 +02:00
retrooper 4012472404 Merge pull request #564 from cheaterSK/2.0
Fix WrapperPlayClientChatCommand and WrapperPlayClientChatMessage
2023-04-23 22:39:03 +02:00
retrooper 54f3f3c221 Minor fixes to WrapperPlayClientChatCommand 2023-04-23 22:37:55 +02:00
cheaterSK 873557151b Merge branch 'retrooper:2.0' into 2.0 2023-04-23 17:34:10 +02:00
MWHunter 32e96f3f51 include other included non-latest gson versions 2023-04-22 18:09:41 -05:00
MWHunter cdffd10999 Update adventure to support new chat components 2023-04-22 17:49:38 -05:00
aseef 1524a546d8 Merge remote-tracking branch 'origin/2.0' into 2.0
# Conflicts:
#	spigot/src/main/java/io/github/retrooper/packetevents/util/SpigotReflectionUtil.java
2023-04-15 15:06:58 -04:00
aseef 40d7be6236 * added a conversion util to convert between bukkit and packet events particles 2023-04-15 15:03:08 -04:00
retrooper 98b2b7b631 Fix exceptions on Spigot 2023-04-09 07:21:49 +02:00
retrooper 54704811b3 Fix code duplication in spigot encoder 2023-04-07 20:02:53 +02:00
retrooper 54241497b5 fix imports 2023-04-07 19:41:27 +02:00
retrooper 99637743f5 I've made a severe and continuous lapse of my judgment. and I don't expect to be forgiven. I'm simply here to apologize. so what we came across that day in the woods was obviously unplanned.2 Jan 2018 2023-04-07 19:39:56 +02:00
retrooper 702452c3a1 Final fix for missing imports. 2023-04-07 19:38:11 +02:00
retrooper 7e424cd46b Bruh 2023-04-07 19:36:01 +02:00
retrooper 58401fc18e Fix import errors again.. 2023-04-07 19:34:41 +02:00
retrooper 7285eeff5a Fix missing import in PacketEventsImplHelper
Sorry, I'm editing this in GitHub website cause I'm working on different branches in parallel
2023-04-07 19:31:01 +02:00
retrooper cfb57e7a99 Add handleClientBoundPacket to PacketEventsImplHelper
This helps reduce code duplication when implementing encoders and decoders that have similar functionality on other platforms.
2023-04-07 19:27:22 +02:00
MWHunter 93cd6f39f9 fix isReplaceable() 2023-04-04 20:26:42 -05:00
MWHunter 9975706ba8 update statetypes, itemtypes, block tags to experimental datapack 2023-04-02 13:13:23 -05:00
retrooper 9b88a9ef98 Minor correction to EntityDataTypes 2023-04-02 18:55:33 +02:00
retrooper 548c6183a4 Added the EntityDataType registries, added in 1.19.4 2023-04-02 18:50:12 +02:00
DefineOutside 19d271881c Merge pull request #510 from UserNugget/1.20-experimental-features
'1.20 experimental features' support
2023-04-02 10:19:51 -05:00
MWHunter a64978cb0a delete unmaintained classes 2023-04-02 10:15:28 -05:00
MWHunter 527beda70f allow users to flag events as needing re-encoding, for performance reasons 2023-04-02 10:14:07 -05:00
MWHunter 127421a1d2 add sniffer 2023-04-02 09:53:34 -05:00
MWHunter 4a188bd116 don't eat exceptions 2023-04-02 09:50:59 -05:00
MWHunter cd6db40a0d add runTask() functionality to folia compat utils 2023-04-01 15:16:11 -05:00
MWHunter d050c10eab make isFolia() public 2023-04-01 15:09:57 -05:00
MWHunter 82e5b68119 update folia compat utility 2023-04-01 15:03:40 -05:00
MWHunter 3f00e1d817 more folia support utils 2023-04-01 14:50:47 -05:00
MWHunter 7296072bcb folia support 2023-04-01 14:41:39 -05:00
DefineOutside 132ae43496 Merge pull request #565 from LemonCaramel/fix/server-data
fix WrapperPlayServerData issue in 1.19.4
2023-03-28 08:38:49 -05:00
LemonCaramel 2465ba9306 fix WrapperPlayServerData issue in 1.19.4 2023-03-27 09:24:39 +09:00
cheaterSK 2e10b151c9 Fix WrapperPlayClientChatCommand and WrapperPlayClientChatMessage for 1.19 2023-03-26 17:12:22 +02:00
cheaterSK 9a338cd897 Fix WrapperPlayClientChatCommand 2023-03-26 16:32:12 +02:00
retrooper 7c0bac33df Fix WrapperLoginClientLoginStart for 1.19.4 2023-03-21 22:56:50 +01:00
MWHunter db8c4ce08d register new entity mappings 2023-03-18 21:10:03 -04:00
MWHunter af52640237 fix entity mappings 2023-03-18 20:59:42 -04:00
MWHunter b6d71a79a1 mark default block states 2023-03-17 19:26:02 -05:00
DefineOutside 407257c2ce Merge pull request #558 from MachineBreaker/pooled-bytebuffers
Use Pooled ByteBuffer in SpigotReflectionUtil for decoding/encoding ItemStacks
2023-03-17 17:44:30 -05:00
Alejandro Martinez 19e7bc6190 Use Pooled ByteBuffers in decodeBukkitItemStack & encodeBukkitItemStack 2023-03-17 16:15:23 -06:00
retrooper e0beccff4d Merge remote-tracking branch 'origin/2.0' into 2.0 2023-03-17 21:57:31 +01:00
retrooper 1728e667ea Push 2023-03-17 21:57:03 +01:00
retrooper c2cce6fac7 Merge pull request #550 from AbhigyaKrishna/2.0
Adventure Backward Compatibility (<4.9.0) support
2023-03-17 19:07:08 +01:00
retrooper 9cf38bc325 Merge pull request #556 from maximbreitman/2.0
Add accessors to WrapperPlayServerPlayerInfoUpdate.PlayerInfo
2023-03-17 19:06:00 +01:00
maximbreitman c0522d7836 Add accessors to WrapperPlayServerPlayerInfoUpdate.PlayerInfo 2023-03-17 17:31:47 +03:00
DefineOutside dc1ac3beb3 Merge pull request #555 from MachineBreaker/patch-2
Log getDefaultState in Config Level
2023-03-16 16:34:48 -05:00
MachineBreaker d59a11a340 Log getDefaultState in Config Level
Prevent spamming the console with:
[ac.grim.grimac.shaded.com.github.retrooper.packetevents.PacketEventsAPI] Default state for lantern is null. Returning AIR
2023-03-16 15:29:36 -06:00
MWHunter a8e95c23ac initial 1.19.4 support 2023-03-15 22:31:29 -05:00
DefineOutside 607b8dde56 Update LegacyFlexibleStorage.java 2023-03-14 12:06:06 -05:00
Abhigya a0ccfb4875 Legacy Adventure (<4.9.0) support 2023-03-13 16:02:35 +05:30
retrooper afcf98e2c8 Merge pull request #549 from Aseeef/2.0
Fixed Adventure API & Build Issues
2023-03-12 18:41:25 +01:00
aseef 51d74ae7ea * relocated adventure api
* fixed velocity repo url
2023-03-12 13:33:13 -04:00
retrooper 7b6308c4e0 Merge pull request #546 from jtJava/2.0
Expose NPC channels and remove unnecessary parameters
2023-03-09 22:14:50 +01:00
jtJava cdbe0df0f3 Expose NPC channels and remove unnecessary parameters 2023-03-08 16:29:58 -06:00
DefineOutside d799ba7190 Merge pull request #543 from Aseeef/2.0
Marker interfaces to packet types
2023-03-01 20:25:43 -06:00
aseef 8c03d2e3a0 Merge remote-tracking branch 'origin/2.0' into 2.0 2023-03-01 21:19:19 -05:00
aseef 7c2994e54d PacketTypes now implement a marker interface indicating whether the packets are client bound or server bound 2023-03-01 21:19:03 -05:00
aseef e1e61feebf reverted an accidental change 2023-03-01 21:18:46 -05:00
aseef e6fb117182 PacketTypes now implement a marker interface indicating whether the packets are client bound or server bound 2023-03-01 21:16:44 -05:00
retrooper a7aa3eae68 Merge pull request #540 from cheaterSK/2.0
feat: Add option in settings to disable color downsampling + fix actions/upgrade gradle
2023-02-20 16:20:20 +01:00
cheaterSK d38089a46a Upgrade gradle to 8.0.1, fix issues that came with it + freeze the version with ./gradlew in actions to avoid issues in future 2023-02-19 11:06:25 +01:00
cheaterSK e2a980adde Fix backwards compatibility 2023-02-18 10:09:09 +01:00
cheaterSK a4e116d34f Merge remote-tracking branch 'origin/2.0' into 2.0
# Conflicts:
#	api/src/main/java/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerPlayerInfo.java
2023-02-18 10:02:37 +01:00
retrooper 6b61682fe4 Merge pull request #538 from Aseeef/2.0
NPE + ConcurrentModification Exception Fix
2023-02-15 23:37:53 +01:00
MWHunter 0c4709ac57 fix exception when mojang sends DISCONNECT in STATUS state, for some reason 2023-02-13 12:09:23 -06:00
DefineOutside c6a542d206 Merge pull request #529 from ammodev/2.0
Version not being chosen correctly
2023-02-13 11:58:48 -06:00
MWHunter d67028f568 don't enable debug by default 2023-02-12 17:08:39 -06:00
aseef af48ee3938 Now creating a set using concurrenthashmap 2023-02-12 13:00:48 -05:00
aseef 945919c1e0 Merge remote-tracking branch 'origin/2.0' into 2.0 2023-02-12 08:32:04 -05:00
aseef 38de7a4b94 should fix concurrent modification exception 2023-02-12 08:30:32 -05:00
Aseeef 419232a075 Merge branch 'retrooper:2.0' into 2.0 2023-02-12 07:47:12 -05:00
aseef e705b2725d fixed a npe 2023-02-12 07:46:10 -05:00
MWHunter 004702f642 remove more unused internal methods 2023-02-11 16:24:13 -06:00
MWHunter 4c29d39292 clean up unused internal methods 2023-02-11 16:11:46 -06:00
MWHunter 24e8ff4fb4 fix fix setting components in EntityDataProvider 2023-02-03 12:59:05 -06:00
MWHunter cf61f74ade fix setting components in EntityDataProvider 2023-02-03 09:13:19 -06:00
MWHunter 72ab24b419 disable debug listener and reset the class 2023-02-02 22:11:14 -06:00
MWHunter 8c8357bfbc avoid modifying backing array 2023-02-02 16:53:16 -06:00
MWHunter 59d36b6e55 Revert "ensure we have recovery logic for missing transition to PLAY state"
This reverts commit 647c05fe98.
2023-02-02 13:25:09 -06:00
MWHunter decf5579a3 reverse lists sanely 2023-02-01 21:18:22 -06:00
MWHunter 187f5a54c6 Why do we not set protocol to GAME state if client version is unknown??? 2023-02-01 20:54:46 -06:00
MWHunter 647c05fe98 ensure we have recovery logic for missing transition to PLAY state 2023-02-01 20:50:46 -06:00
MWHunter a089b98f6d warn instead of debug on late injection 2023-02-01 20:45:43 -06:00
MWHunter 9d21b834cc reverting bc356c6d - not setting to GAME state if client version unknown? what is retrooper doing? 2023-02-01 20:43:38 -06:00
MWHunter 069e872204 print more exceptions? 2023-02-01 20:39:02 -06:00
Simon e945c9c56f Update build.gradle
Revert the changes on the version to fit current standards
2023-01-31 22:09:12 +01:00
SimonandJulian b8058b57d8 Update bungeecord/src/main/java/io/github/retrooper/packetevents/bungee/factory/BungeePacketEventsBuilder.java
Updated code style

Co-authored-by: Julian <53055251+NoJokeFNA@users.noreply.github.com>
2023-01-31 09:33:17 +01:00
retrooper 7ce167157a Merge pull request #442 from NoJokeFNA/feat/bungeecord
Cleaned up BungeeCord module
2023-01-30 19:47:05 +01:00
DefineOutside 0503e99c50 Merge pull request #530 from DietrichPaul/patch-1
fixed 1.7 block placement
2023-01-30 12:04:17 -06:00
MWHunter 413d5e1eb5 add toString for StateType 2023-01-29 17:47:55 -06:00
MWHunter 51ebbb7914 ignore more types of invalid handshakes with the server 2023-01-29 12:36:47 -06:00
Paul Dietrich 2b98d5c90b fixed 1.7 block placement 2023-01-29 11:05:28 +01:00
MWHunter 099ea9b7e9 fix race condition when sending packets to multiple people 2023-01-28 17:53:05 -06:00
Simon ce703febc3 Fixed a bug where the version would not be chosen correctly 2023-01-29 00:16:00 +01:00
Simon dce59f99fd Changed git ignore to include vscode files 2023-01-29 00:09:03 +01:00
UserNugget 5ff498b6f0 1.20 experimental blocks/items/tags 2023-01-28 11:21:07 +03:00
MWHunter 32b85dce18 add more methods to avoid forcing people to use clientVersion 2023-01-27 23:13:57 -06:00
MWHunter 89b8d823c4 avoid forcing people to specify clientversions for block data 2023-01-27 23:11:53 -06:00
MWHunter fc0f1eec68 default block state to server version 2023-01-27 22:36:05 -06:00
MWHunter 765fb79321 add modern conversions for WrappedBlockState 2023-01-27 22:34:55 -06:00
MWHunter eb42c1b473 warn instead of error if someone else removes our handlers on reloads/shutdowns 2023-01-27 20:58:02 -06:00
MWHunter ce484ecac5 support reloads 2023-01-27 20:20:44 -06:00
MWHunter cb3e4d33a7 properly handle sending -1 (survival) gamemode in player info 2023-01-27 19:43:34 -06:00
MWHunter 12c01eb2fa update chat wrappers to 1.19.3 2023-01-27 19:25:31 -06:00
MWHunter c4b8a17437 fix project setup by not setting java source and target compat in the base build.gradle 2023-01-27 17:13:24 -06:00
MWHunter 5dde544e07 correct gradle specifying submodules 2023-01-27 16:19:39 -06:00
MWHunter d16ad2154d hack around bungeecord's inability to process empty buffers 2023-01-27 13:31:01 -06:00
MWHunter 245da7a870 ignore handshaking exceptions 2023-01-27 12:55:08 -06:00
MWHunter 2a0b217718 revert last change 2023-01-27 12:23:17 -06:00
MWHunter 582cfa7b57 fix cancelling outbound packet kicking people on bungeecord 2023-01-27 12:18:11 -06:00
retrooper 1b295dc827 Merge pull request #486 from vytskalt/2.0
Safely limit team display name, prefix and suffix to appropriate lengths
2023-01-11 19:31:42 +01:00
retrooper a83248f70d Correctly limit all data in the wrapper differently depending on the protocol version. 2023-01-11 19:29:28 +01:00
retrooper 42a1375c00 Merge pull request #516 from RotMC/2.0
Fix NPE caused by attempting to initialize user before channel
2023-01-11 18:32:30 +01:00
Ryan Jones fbe89306f5 Merge branch 'retrooper:2.0' into 2.0 2023-01-09 11:40:31 -05:00
retrooper faeb2f55d3 * Update NPC API for 1.19.3
* Improve WrapperPlayServerPlayerInfoUpdate & WrapperPlayServerPlayerInfoRemove for easier use
2023-01-08 00:27:58 +01:00
DefineOutside 239cc09c9f fix headYaw not being sent 2023-01-05 16:41:28 -06:00
retrooper 6aac1faac4 Merge pull request #517 from iTzLucky28/2.0
Add Itemstack to WrapperPlayClientPlayerBlockPlacement constructor and replace Optional by regular objects
2023-01-03 22:54:20 +01:00
iTz_Lucky ea4ab05bff Add Itemstack to constructor and replace Optional by regular objects
Also less error prone, especially if they send null as Optional instead of Optional containing null
2023-01-02 08:13:29 +01:00
wordandahalf d53f39bbc7 Fix NPE caused by attempting to initialize user before channel 2023-01-01 16:50:55 -05:00
cheaterSK 8f28b71ee2 Merge branch 'retrooper:2.0' into 2.0 2022-12-31 17:28:36 +01:00
DefineOutside 58df1fcc91 Merge pull request #512 from epserv/2.0
Add SITTING pose to EntityPose
2022-12-29 20:39:32 -06:00
l_MrBoom_l 060b919fa3 Add SITTING pose to EntityPose 2022-12-24 23:07:33 +05:00
MWHunter 7d0d4aa672 fix weird spigot 1.8 bug 2022-12-21 16:57:49 -06:00
MWHunter e3cde54ab2 Simplify encoder/decoder, avoid bytebuf allocations 2022-12-21 16:20:59 -06:00
MWHunter d681345e41 Fix optional component serializers 2022-12-15 14:54:08 -06:00
MWHunter 3939b534ad make entity json data lazy 2022-12-15 13:53:57 -06:00
MWHunter a8afbd2a0b pool bytebufs 2022-12-15 13:34:41 -06:00
MWHunter 7d7cbb4445 Don't annotate non-sharable encoders/decoders as sharable 2022-12-14 17:54:58 -06:00
MWHunter 1c5dceb47d Update explosion packet to 1.19.3 2022-12-14 14:59:58 -06:00
MWHunter 876fbf6fbf Fix creating a new NBT tag which can desync inventory 2022-12-13 14:00:23 -06:00
MWHunter b469ce2a69 fix compilation 2022-12-13 00:31:14 -06:00
MWHunter 6f7823e8cb Use pipeline instead of address for tracking connections 2022-12-13 00:21:00 -06:00
MWHunter 2619a4398d Clean up previous attempts to try to fix race condition 2022-12-12 20:23:27 -06:00
MWHunter d411fe44fe Fix race condition due to ProtocolLib wrapping a Channel screwing with our hashmaps 2022-12-12 20:19:07 -06:00
MWHunter 67af517510 Try synchronization to fix weird race condition 2022-12-12 19:41:39 -06:00
MWHunter cce862bc57 Refactor methods dealing with Bukkit and Users 2022-12-12 18:20:48 -06:00
MWHunter 319750e3f9 Fix tag matches for empty tags 2022-12-12 16:42:20 -06:00
MWHunter 78ccd8b2d5 fix last commit 2022-12-12 14:07:11 -06:00
MWHunter 50ef62f4fb Fix some reflection methods on some shitty MCM jar 2022-12-12 14:06:42 -06:00
MWHunter 05a5b5284b More debug 2022-12-12 12:41:48 -06:00
MWHunter 8c6865405d actually fix bad ordering (not race condition!) of post send tasks 2022-12-11 19:29:14 -06:00
retrooper a204b5d521 Merge remote-tracking branch 'origin/2.0' into 2.0 2022-12-11 09:10:47 +01:00
retrooper da0128b330 Fixed user state transitioning to remain in sync with minecraft which should fix a bunch of errors where we do not recognize the packet id or properly read data of a packet, because our connection state is behind. We need to update the state as soon as we get the packet. 2022-12-11 09:10:15 +01:00
MWHunter 84b005a3b0 Handle vanilla now reading a fixed amount of bytes 2022-12-11 00:15:06 -06:00
MWHunter 38fd7eae6d Fix 1.19.3 chat messages not reading/writing chat type 2022-12-11 00:02:19 -06:00
MWHunter e3d08fa0de Try adding partial 1.19.3 chat packet support 2022-12-10 23:49:13 -06:00
retrooper 0da59c3585 Merge pull request #494 from iTzLucky28/2.0
Add getter/setter for WrapperPlayClientClickWindow
2022-12-11 00:31:35 +01:00
retrooper b4145fda44 Remove ClassUtil's unnecessary class simple name caching 2022-12-11 00:29:02 +01:00
retrooper 5df58a116d Fix race-condition in transitioning to PLAY state.
Post-tasks now run right after all listeners have processed the packet.

Tasks-after-send (only for outgoing packets) run after a packet has been sent

There's a difference so please make sure you're using the right one.
2022-12-10 21:21:22 +01:00
retrooper 7899d8cb46 Fix NBTCodec#nbtToJson 2022-12-10 21:03:51 +01:00
MWHunter b47e0f20ef More gracefully handle unknown block types 2022-12-09 18:16:28 -06:00
MWHunter 63a7121653 Update some mappings to 1.19.3 (Not everything is complete!) 2022-12-09 18:03:15 -06:00
MWHunter 7927c89ba2 Create a new bytebuf due to weird 1.8 bytebuf behavior 2022-12-09 15:10:08 -06:00
MWHunter db5c97a324 Protect against empty bytebuffers, remove large amount of decoder code 2022-12-09 00:35:44 -06:00
MWHunter d4b919430f Ignore via API if it returns -1 as player version 2022-12-08 19:16:39 -06:00
MWHunter d52df749fa Prevent bots scraping the internet from causing PE 2.0 error 2022-12-08 16:54:59 -06:00
MWHunter 63eac8f0f6 Prevent failed injection with multiple PacketEvents 2.0 plugins 2022-12-08 16:21:17 -06:00
cheaterSK 0d7a618d87 Merge branch 'retrooper:2.0' into 2.0 2022-12-08 22:38:15 +01:00
retrooper 7a8d440475 * Added WrapperPlayServerPlayerInfoUpdate (for minecraft 1.19.3+ versions)
* Minor optimization to WrapperPlayServerPlayerInfo (minecraft 1.19.2 and older can use this wrapper)
2022-12-08 19:27:41 +01:00
retrooper 89b63802ac Add WrapperPlayClientChatSessionUpdate 2022-12-08 18:24:27 +01:00
retrooper 17e8b51205 Add WrapperPlayServerUpdateEnabledFeatures 2022-12-08 17:11:51 +01:00
retrooper 8bb12b6913 Add WrapperPlayServerPlayerInfoRemove 2022-12-08 17:07:18 +01:00
retrooper 8a194d1ff6 Add WrapperPlayServerDisguisedChat (1.19.3 packet) 2022-12-08 17:01:31 +01:00
retrooper 45bc1e3d80 Map global 1.19.3 packet types 2022-12-08 16:54:10 +01:00
retrooper a812e22312 Map 1.19.3 packet types 2022-12-08 16:37:20 +01:00
DefineOutside b7c9015b39 Merge pull request #496 from ytnoos/2.0
Fix ViaVersion version check
2022-12-08 09:06:08 -06:00
Ytnoos 98c7c0d49c Fix ViaVersion version check 2022-12-08 11:35:56 +01:00
MWHunter dc10e3cca6 Support ViaBackwards on Paper servers 2022-12-07 17:01:48 -06:00
retrooper 54ae21fd5d Set autoProtocolTranslation to true 2022-12-07 23:45:21 +01:00
retrooper 5d851e849a Merge remote-tracking branch 'origin/2.0' into 2.0 2022-12-07 23:44:42 +01:00
retrooper 09ef7c2e80 Fix server-version detection issues & compression handling 2022-12-07 23:44:14 +01:00
MWHunter e8d7fc30a5 Don't try auto translating spigot protocol 2022-12-07 16:06:25 -06:00
MWHunter 5fbb6d7349 Refactor post tasks 2022-12-07 14:59:41 -06:00
MWHunter 28b67601c1 Fix concurrent modification exception 2022-12-07 14:47:26 -06:00
MWHunter ba02780727 Fix receive packet methods 2022-12-07 14:16:32 -06:00
MWHunter 2c756925a1 Injector rewrite for ViaVersion 4.5.0 2022-12-07 13:56:21 -06:00
iTz_Lucky ac37b708c0 Update WrapperPlayClientClickWindow
Getter and Setter for actionNumber in  WrapperPlayClientClickWindow
2022-12-03 04:03:25 +01:00
retrooper 6b92403dea Optimize ProtocolSupportUtil 2022-12-01 20:05:21 +01:00
cheaterSK f63da3d3d2 Fix Teams packet gamemode sometimes resulting in -1 2022-11-26 11:41:30 +01:00
cheaterSK de763c948c Fix legacy component parser 2022-11-26 10:52:55 +01:00
cheaterSK 4469b93ed9 feat: Add option in settings to disable color downsampling 2022-11-26 10:19:36 +01:00
DefineOutside 873c09d224 Merge pull request #474 from caoli5288/patch/user-dimension
Use User.dimension to improve ChunkReader_v1_9
2022-11-16 12:20:08 -06:00
DefineOutside 646b0a1050 Merge pull request #488 from AoElite/2.0
Allow NPC gamemode to be changable
2022-11-16 12:19:38 -06:00
AoElite 470975ca77 add method to update gamemode 2022-11-15 22:24:28 -05:00
AoElite 2005daa11f allow the gamemode of the npc to be changeable 2022-11-15 22:17:30 -05:00
VytskaLT e28f4e3993 Limit team display name, prefix and suffix to 16 characters 2022-11-06 18:11:19 +02:00
caoli5288 f9390aa69d fix #472 2022-08-26 20:27:26 +08:00
caoli5288 3f6bb1a03d Merge remote-tracking branch 'upstream/2.0' into patch/user-dimension 2022-08-26 20:26:23 +08:00
caoli5288 911dffccc2 fix #472 2022-08-24 13:51:54 +08:00
caoli5288 3368b7fcc5 fix #472 2022-08-24 13:33:34 +08:00
NoJokeFNA ea273ba4b6 feat: some more cleanup 2022-06-29 13:07:32 +02:00
NoJokeFNA f3b14030b1 feat: some cleanup 2022-06-28 11:33:04 +02:00
239 changed files with 108179 additions and 3717 deletions

No files matched your search

+9 -8
View File
@@ -11,9 +11,10 @@ jobs:
packages: write
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Set up JDK 8
uses: actions/setup-java@v2
uses: actions/setup-java@v3
with:
java-version: '8'
distribution: 'adopt'
@@ -21,34 +22,34 @@ jobs:
settings-path: ${{ github.workspace }} # location for the settings.xml file
- name: Build with Gradle
run: gradle shadowJar
run: chmod +x gradlew && ./gradlew shadowJar
- name: Upload build artifacts api
uses: actions/upload-artifact@v1
uses: actions/upload-artifact@v3
with:
name: api-build
path: api/build/libs
- name: Upload build artifacts spigot
uses: actions/upload-artifact@v1
uses: actions/upload-artifact@v3
with:
name: spigot-build
path: spigot/build/libs
- name: Upload build artifacts netty-common
uses: actions/upload-artifact@v1
uses: actions/upload-artifact@v3
with:
name: netty-common-build
path: netty-common/build/libs
- name: Upload build artifacts bungeecord
uses: actions/upload-artifact@v1
uses: actions/upload-artifact@v3
with:
name: bungeecord-build
path: bungeecord/build/libs
- name: Upload build artifacts velocity
uses: actions/upload-artifact@v1
uses: actions/upload-artifact@v3
with:
name: velocity-build
path: velocity/build/libs
+5
View File
@@ -102,6 +102,7 @@ $RECYCLE.BIN/
.gradle
build/
bin/
# Ignore Gradle GUI config
gradle-app.setting
@@ -118,3 +119,7 @@ run/
!gradle-wrapper.jar
/src/main/resources/plugin.yml
/.idea/
.vscode/
.project
.settings/
.classpath
+6 -13
View File
@@ -1,15 +1,17 @@
# packetevents
[![](https://jitpack.io/v/retrooper/packetevents.svg)](https://jitpack.io/#retrooper/packetevents)
[![](https://img.shields.io/badge/License-GPLv3-yellow.svg)](https://github.com/retrooper/packetevents/blob/2.0/LICENSE) [![](https://github.com/retrooper/packetevents/actions/workflows/build.yml/badge.svg)](https://github.com/retrooper/packetevents/actions) [![Discord](https://img.shields.io/badge/Discord-%235865F2.svg?style=for-the-badge&logo=discord&logoColor=white)](https://discord.gg/prqzNg9tRU)
PacketEvents is a powerful packet library. Our packet wrappers are efficient and easy to use. With our API, you can write code that runs on many platforms including Spigot, BungeeCord, Velocity, and even client-sided Fabric! Switch to PacketEvents today by joining \
PacketEvents is a fast and efficient multi-platform packet processing library. Our packet wrappers are easy to use with multi-version support. With our API you can write code that runs on Spigot, BungeeCord, Velocity, and Fabric! Switch to PacketEvents today by joining \
our [Discord Server](https://discord.me/packetevents) for help.
### Links
* [Find release builds on SpigotMC](https://www.spigotmc.org/resources/packetevents-api.80279/)
* [Find release builds on Modrinth](https://modrinth.com/plugin/packetevents)
* [Find development builds on Jenkins](https://ci.codemc.io/job/retrooper/job/packetevents)
* [View documentation on our JavaDocs Page](https://packetevents.github.io/javadocs)
### Setup
[Learn more](https://github.com/retrooper/packetevents/wiki/Setup-2.0)
[How to Setup PacketEvents](https://github.com/retrooper/packetevents/wiki/Depending-on-pre%E2%80%90built-PacketEvents)
### Sponsorships
[![](https://www.ej-technologies.com/images/product_banners/jprofiler_small.png)](https://www.ej-technologies.com/products/jprofiler/overview.html)
@@ -18,15 +20,6 @@ our [Discord Server](https://discord.me/packetevents) for help.
PacketEvents optionally collects statistics using [bStats](https://bstats.org/)\
Check out our [bStats page](https://bstats.org/plugin/bukkit/packetevents/11327)
This library is licensed under the GPLv3 (General Public License version 3). Here are a few sources to learn more about the license.\
[![](https://www.gnu.org/graphics/gplv3-with-text-136x68.png)](https://github.com/retrooper/packetevents/blob/2.0/LICENSE)
### GPL Resources
* https://www.gnu.org/philosophy/free-sw.html
* https://www.gnu.org/philosophy/free-sw.html#clarifying
* https://www.gnu.org/licenses/copyleft.en.html
* https://www.gnu.org/licenses/quick-guide-gplv3.html
* https://gpl-violations.org/faq/sourcecode-faq/
### Credit to these projects
[wiki.vg/Protocol](https://wiki.vg/Protocol)\
[netty](https://github.com/netty/netty)\
@@ -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, 0, 0);
private static final PEVersion VERSION = new PEVersion(2, 1, 0);
public EventManager getEventManager() {
return EVENT_MANAGER;
@@ -19,15 +19,16 @@
package com.github.retrooper.packetevents.event;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.exception.InvalidHandshakeException;
import org.jetbrains.annotations.Nullable;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
public class EventManager {
private final Map<Byte, HashSet<PacketListenerCommon>> listenersMap = new ConcurrentHashMap<>();
private final Map<Byte, Set<PacketListenerCommon>> listenersMap = new ConcurrentHashMap<>();
/**
* Call the PacketEvent.
@@ -44,13 +45,16 @@ public class EventManager {
public void callEvent(PacketEvent event, @Nullable Runnable postCallListenerAction) {
for (byte priority = PacketListenerPriority.LOWEST.getId(); priority <= PacketListenerPriority.MONITOR.getId(); priority++) {
HashSet<PacketListenerCommon> listeners = listenersMap.get(priority);
Set<PacketListenerCommon> listeners = listenersMap.get(priority);
if (listeners != null) {
for (PacketListenerCommon listener : listeners) {
try {
event.call(listener);
} catch (Throwable t) {
PacketEvents.getAPI().getLogger().log(Level.WARNING, "PacketEvents caught an unhandled exception while calling your listener.", t);
} catch (Exception t) {
// ignore handshake exceptions
if (t.getClass() != InvalidHandshakeException.class) {
PacketEvents.getAPI().getLogger().log(Level.WARNING, "PacketEvents caught an unhandled exception while calling your listener.", t);
}
}
if (postCallListenerAction != null) {
postCallListenerAction.run();
@@ -58,7 +62,8 @@ public class EventManager {
}
}
}
if (event instanceof ProtocolPacketEvent && PacketEvents.getAPI().getSettings().shouldListenersReadOnly()) {
// For performance reasons, we don't want to re-encode the packet if it's not needed.
if (event instanceof ProtocolPacketEvent && !((ProtocolPacketEvent<?>) event).needsReEncode()) {
((ProtocolPacketEvent<?>) event).setLastUsedWrapper(null);
}
@@ -76,9 +81,9 @@ public class EventManager {
*/
public PacketListenerCommon registerListener(PacketListenerCommon listener) {
byte priority = listener.getPriority().getId();
HashSet<PacketListenerCommon> listenerSet = listenersMap.get(priority);
Set<PacketListenerCommon> listenerSet = listenersMap.get(priority);
if (listenerSet == null) {
listenerSet = new HashSet<>();
listenerSet = ConcurrentHashMap.newKeySet();
}
listenerSet.add(listener);
listenersMap.put(priority, listenerSet);
@@ -98,7 +103,7 @@ public class EventManager {
}
public void unregisterListener(PacketListenerCommon listener) {
HashSet<PacketListenerCommon> listenerSet = listenersMap.get(listener.getPriority().getId());
Set<PacketListenerCommon> listenerSet = listenersMap.get(listener.getPriority().getId());
if (listenerSet == null) return;
listenerSet.remove(listener);
}
@@ -47,20 +47,13 @@ public class PacketReceiveEvent extends ProtocolPacketEvent<Object> {
@Override
public PacketReceiveEvent clone() {
if (this instanceof PacketHandshakeReceiveEvent) {
return ((PacketHandshakeReceiveEvent)this).clone();
}
else if (this instanceof PacketStatusReceiveEvent) {
return ((PacketStatusReceiveEvent)this).clone();
}
else if (this instanceof PacketLoginReceiveEvent) {
return ((PacketLoginReceiveEvent)this).clone();
}
else if (this instanceof PacketPlayReceiveEvent) {
return ((PacketPlayReceiveEvent)this).clone();
}
else {
return null;
try {
Object clonedBuffer = ByteBufHelper.retainedDuplicate(getByteBuf());
return new PacketReceiveEvent(getPacketId(), getPacketType(), getServerVersion(),
getChannel(), getUser(), getPlayer(), clonedBuffer);
} catch (PacketProcessException e) {
e.printStackTrace();
}
return null;
}
}
@@ -18,9 +18,7 @@
package com.github.retrooper.packetevents.event;
import com.github.retrooper.packetevents.event.simple.PacketLoginSendEvent;
import com.github.retrooper.packetevents.event.simple.PacketPlaySendEvent;
import com.github.retrooper.packetevents.event.simple.PacketStatusSendEvent;
import com.github.retrooper.packetevents.event.simple.PacketHandshakeSendEvent;
import com.github.retrooper.packetevents.exception.PacketProcessException;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.netty.buffer.ByteBufHelper;
@@ -28,7 +26,12 @@ import com.github.retrooper.packetevents.protocol.PacketSide;
import com.github.retrooper.packetevents.protocol.packettype.PacketTypeCommon;
import com.github.retrooper.packetevents.protocol.player.User;
import java.util.ArrayList;
import java.util.List;
public class PacketSendEvent extends ProtocolPacketEvent<Object> {
private List<Runnable> tasksAfterSend = null;
protected PacketSendEvent(Object channel, User user, Object player, Object rawByteBuf,
boolean autoProtocolTranslation) throws PacketProcessException {
super(PacketSide.SERVER, channel, user, player, rawByteBuf, autoProtocolTranslation);
@@ -48,19 +51,27 @@ public class PacketSendEvent extends ProtocolPacketEvent<Object> {
listener.onPacketSend(this);
}
public List<Runnable> getTasksAfterSend() {
if (tasksAfterSend == null) {
tasksAfterSend = new ArrayList<>();
}
return tasksAfterSend;
}
public boolean hasTasksAfterSend() {
return tasksAfterSend != null && !tasksAfterSend.isEmpty();
}
@Override
public PacketSendEvent clone() {
if (this instanceof PacketStatusSendEvent) {
return ((PacketStatusSendEvent)this).clone();
}
else if (this instanceof PacketLoginSendEvent) {
return ((PacketLoginSendEvent)this).clone();
}
else if (this instanceof PacketPlaySendEvent) {
return ((PacketPlaySendEvent)this).clone();
}
else {
return null;
try {
Object clonedBuffer = ByteBufHelper.retainedDuplicate(getByteBuf());
return new PacketSendEvent(getPacketId(), getPacketType(), getServerVersion(),
getChannel(), getUser(), getPlayer(), clonedBuffer);
} catch (PacketProcessException e) {
e.printStackTrace();
}
return null;
}
}
@@ -19,6 +19,7 @@
package com.github.retrooper.packetevents.event;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.exception.InvalidDisconnectPacketSend;
import com.github.retrooper.packetevents.exception.PacketProcessException;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.netty.buffer.ByteBufHelper;
@@ -51,6 +52,7 @@ public abstract class ProtocolPacketEvent<T> extends PacketEvent implements Play
private PacketWrapper<?> lastUsedWrapper;
private List<Runnable> postTasks = null;
private boolean cloned;
private boolean needsReEncode = PacketEvents.getAPI().getSettings().reEncodeByDefault();
public ProtocolPacketEvent(PacketSide packetSide, Object channel,
User user, T player, Object byteBuf,
@@ -76,12 +78,17 @@ public abstract class ProtocolPacketEvent<T> extends PacketEvent implements Play
throw new PacketProcessException("Failed to read the Packet ID of a packet. (Size: " + size + ")");
}
ClientVersion version = serverVersion.toClientVersion();
this.packetType = PacketType.getById(packetSide, user.getConnectionState(),
ConnectionState state = packetSide == PacketSide.CLIENT ? user.getDecoderState() : user.getEncoderState();
this.packetType = PacketType.getById(packetSide, state,
version, packetID);
if (this.packetType == null) {
throw new PacketProcessException("Failed to map the Packet ID " + packetID + " to a PacketType constant. Bound: " + packetSide.getOpposite() + ", Connection state: " + user.getConnectionState() + ", Server version: " + serverVersion.getReleaseName());
// mojang messed up and keeps sending disconnect packets in the wrong protocol state
if (PacketType.getById(packetSide, ConnectionState.PLAY, version, packetID) == PacketType.Play.Server.DISCONNECT) {
throw new InvalidDisconnectPacketSend();
}
throw new PacketProcessException("Failed to map the Packet ID " + packetID + " to a PacketType constant. Bound: " + packetSide.getOpposite() + ", Connection state: " + user.getDecoderState() + ", Server version: " + serverVersion.getReleaseName());
}
this.connectionState = user.getConnectionState();
this.connectionState = state;
}
public ProtocolPacketEvent(int packetID, PacketTypeCommon packetType, ServerVersion serverVersion, Object channel,
@@ -93,10 +100,21 @@ public abstract class ProtocolPacketEvent<T> extends PacketEvent implements Play
this.byteBuf = byteBuf;
this.packetID = packetID;
this.packetType = packetType;
this.connectionState = user.getConnectionState();
this.connectionState = (packetType != null && packetType.getSide() == PacketSide.SERVER)
? user.getEncoderState() : user.getDecoderState();
cloned = true;
}
public void markForReEncode(boolean needsReEncode) {
this.needsReEncode = needsReEncode;
}
public boolean needsReEncode() {
return needsReEncode;
}
public boolean isClone() {
return cloned;
}
@@ -151,7 +169,6 @@ public abstract class ProtocolPacketEvent<T> extends PacketEvent implements Play
this.byteBuf = byteBuf;
}
@Deprecated
public int getPacketId() {
return packetID;
}
@@ -41,7 +41,11 @@ public abstract class SimplePacketListenerAbstract extends PacketListenerCommon
onPacketStatusReceive((PacketStatusReceiveEvent) event);
} else if (event instanceof PacketLoginReceiveEvent) {
onPacketLoginReceive((PacketLoginReceiveEvent) event);
} else if (event instanceof PacketPlayReceiveEvent) {
}
else if (event instanceof PacketConfigReceiveEvent) {
onPacketConfigReceive((PacketConfigReceiveEvent) event);
}
else if (event instanceof PacketPlayReceiveEvent) {
onPacketPlayReceive((PacketPlayReceiveEvent) event);
}
}
@@ -52,7 +56,11 @@ public abstract class SimplePacketListenerAbstract extends PacketListenerCommon
onPacketStatusSend((PacketStatusSendEvent) event);
} else if (event instanceof PacketLoginSendEvent) {
onPacketLoginSend((PacketLoginSendEvent) event);
} else if (event instanceof PacketPlaySendEvent) {
}
else if (event instanceof PacketConfigSendEvent) {
onPacketConfigSend((PacketConfigSendEvent) event);
}
else if (event instanceof PacketPlaySendEvent) {
onPacketPlaySend((PacketPlaySendEvent) event);
}
}
@@ -72,6 +80,12 @@ public abstract class SimplePacketListenerAbstract extends PacketListenerCommon
public void onPacketLoginSend(PacketLoginSendEvent event) {
}
public void onPacketConfigReceive(PacketConfigReceiveEvent event) {
}
public void onPacketConfigSend(PacketConfigSendEvent event) {
}
public void onPacketPlayReceive(PacketPlayReceiveEvent event) {
}
@@ -0,0 +1,59 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 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.event.simple;
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.exception.PacketProcessException;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.netty.buffer.ByteBufHelper;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.protocol.packettype.PacketTypeCommon;
import com.github.retrooper.packetevents.protocol.player.User;
public class PacketConfigReceiveEvent extends PacketReceiveEvent {
public PacketConfigReceiveEvent(Object channel, User user,
Object player, Object rawByteBuf,
boolean autoProtocolTranslation) throws PacketProcessException {
super(channel, user, player, rawByteBuf, autoProtocolTranslation);
}
protected PacketConfigReceiveEvent(int packetId, PacketTypeCommon packetType,
ServerVersion serverVersion,
Object channel,
User user, Object player, Object byteBuf) throws PacketProcessException {
super(packetId, packetType, serverVersion, channel, user, player, byteBuf);
}
@Override
public PacketConfigReceiveEvent clone() {
try {
Object clonedBuffer = ByteBufHelper.retainedDuplicate(getByteBuf());
return new PacketConfigReceiveEvent(getPacketId(), getPacketType(), getServerVersion(),
getChannel(), getUser(), getPlayer(), clonedBuffer);
} catch (PacketProcessException e) {
e.printStackTrace();
}
return null;
}
public PacketType.Configuration.Client getPacketType() {
return (PacketType.Configuration.Client) super.getPacketType();
}
}
@@ -0,0 +1,59 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 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.event.simple;
import com.github.retrooper.packetevents.event.PacketSendEvent;
import com.github.retrooper.packetevents.exception.PacketProcessException;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.netty.buffer.ByteBufHelper;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.protocol.packettype.PacketTypeCommon;
import com.github.retrooper.packetevents.protocol.player.User;
public class PacketConfigSendEvent extends PacketSendEvent {
public PacketConfigSendEvent(Object channel, User user,
Object player, Object rawByteBuf,
boolean autoProtocolTranslation) throws PacketProcessException {
super(channel, user, player, rawByteBuf, autoProtocolTranslation);
}
protected PacketConfigSendEvent(int packetId, PacketTypeCommon packetType,
ServerVersion serverVersion,
Object channel,
User user, Object player, Object byteBuf) throws PacketProcessException {
super(packetId, packetType, serverVersion, channel, user, player, byteBuf);
}
@Override
public PacketConfigSendEvent clone() {
try {
Object clonedBuffer = ByteBufHelper.retainedDuplicate(getByteBuf());
return new PacketConfigSendEvent(getPacketId(), getPacketType(), getServerVersion(),
getChannel(), getUser(), getPlayer(), clonedBuffer);
} catch (PacketProcessException e) {
e.printStackTrace();
}
return null;
}
public PacketType.Configuration.Server getPacketType() {
return (PacketType.Configuration.Server) super.getPacketType();
}
}
@@ -0,0 +1,5 @@
package com.github.retrooper.packetevents.exception;
public class CancelPacketException extends RuntimeException {
public static final CancelPacketException INSTANCE = new CancelPacketException();
}
@@ -0,0 +1,4 @@
package com.github.retrooper.packetevents.exception;
public class InvalidDisconnectPacketSend extends RuntimeException {
}
@@ -0,0 +1,4 @@
package com.github.retrooper.packetevents.exception;
public class InvalidHandshakeException extends RuntimeException {
}
@@ -18,7 +18,7 @@
package com.github.retrooper.packetevents.exception;
public class PacketProcessException extends Exception {
public class PacketProcessException extends RuntimeException {
public PacketProcessException(String msg, Throwable cause) {
super(msg, cause);
}
@@ -18,9 +18,7 @@
package com.github.retrooper.packetevents.injector;
import com.github.retrooper.packetevents.protocol.ConnectionState;
import com.github.retrooper.packetevents.protocol.player.User;
import org.jetbrains.annotations.Nullable;
public interface ChannelInjector {
default boolean isServerBound() {
@@ -31,13 +29,9 @@ public interface ChannelInjector {
void uninject();
User getUser(Object channel);
void changeConnectionState(Object channel, @Nullable ConnectionState connectionState);
void updateUser(Object channel, User user);
void setPlayer(Object channel, Object player);
boolean hasPlayer(Object player);
boolean isProxy();
}
@@ -32,6 +32,7 @@ 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.wrapper.configuration.server.WrapperConfigServerRegistryData;
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;
@@ -71,44 +72,76 @@ public class InternalPacketListener extends PacketListenerAbstract {
PacketEvents.getAPI().getLogManager().debug("Mapped player UUID with their channel.");
//Update connection state(injectors might do some adjustments when we transition into PLAY state)
//This also updates it for the user instance
event.getPostTasks().add(() -> {
PacketEvents.getAPI().getInjector().changeConnectionState(channel, ConnectionState.PLAY);
PacketEvents.getAPI().getLogManager().debug("Transitioned " + profile.getName() + " into the PLAY state!");
});
// Switch the user's connection state to new state, but the variable event.getConnectionState() remains LOGIN
// We switch user state immediately to remain in sync with vanilla, allowing you to encode packets immediately
boolean proxy = PacketEvents.getAPI().getInjector().isProxy();
if (proxy ? event.getUser().getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_20_2)
: event.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_20_2)) {
user.setEncoderState(ConnectionState.CONFIGURATION);
} else {
user.setConnectionState(ConnectionState.PLAY);
}
}
// Join game can be used to update world height, and sets dimension data
// The server sends dimension information in configuration phase >= 1.20.2
else if (event.getPacketType() == PacketType.Configuration.Server.REGISTRY_DATA) {
WrapperConfigServerRegistryData registryData = new WrapperConfigServerRegistryData(event);
// Store world data
NBTCompound registryDataTag = registryData.getRegistryData();
if (registryDataTag != null) {
NBTList<NBTCompound> list = registryDataTag
.getCompoundTagOrNull("minecraft:dimension_type")
.getCompoundListTagOrNull("value");
user.setWorldNBT(list);
}
}
// The server sends dimension information in login packet for >= 1.17 and < 1.20.2
else if (event.getPacketType() == PacketType.Play.Server.JOIN_GAME) {
WrapperPlayServerJoinGame joinGame = new WrapperPlayServerJoinGame(event);
user.setEntityId(joinGame.getEntityId());
user.setDimension(joinGame.getDimension());
if (event.getServerVersion().isOlderThanOrEquals(ServerVersion.V_1_16_5)) {
return; // Fixed world height, no tags are sent to the client
}
// Store world height
NBTList<NBTCompound> list = joinGame.getDimensionCodec().getCompoundTagOrNull("minecraft:dimension_type").getCompoundListTagOrNull("value");
user.setWorldNBT(list);
// Store world data
NBTCompound dimensionCodec = joinGame.getDimensionCodec();
if (dimensionCodec != null) {
NBTList<NBTCompound> list = dimensionCodec
.getCompoundTagOrNull("minecraft:dimension_type")
.getCompoundListTagOrNull("value");
user.setWorldNBT(list);
}
// Update world height
NBTCompound worldNBT = user.getWorldNBT(joinGame.getDimension().getDimensionName()).getCompoundTagOrNull("element");
user.setMinWorldHeight(worldNBT.getNumberTagOrNull("min_y").getAsInt());
user.setTotalWorldHeight(worldNBT.getNumberTagOrNull("height").getAsInt());
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());
}
}
// Respawn is used to switch dimensions
else if (event.getPacketType() == PacketType.Play.Server.RESPAWN) {
WrapperPlayServerRespawn respawn = new WrapperPlayServerRespawn(event);
user.setDimension(respawn.getDimension());
if (event.getServerVersion().isOlderThanOrEquals(ServerVersion.V_1_16_5)) {
return; // Fixed world height, no tags are sent to the client
}
WrapperPlayServerRespawn respawn = new WrapperPlayServerRespawn(event);
NBTCompound worldNBT = user.getWorldNBT(respawn.getDimension().getDimensionName()).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());
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());
}
} else if (event.getPacketType() == PacketType.Play.Server.CONFIGURATION_START) {
user.setEncoderState(ConnectionState.CONFIGURATION);
} else if (event.getPacketType() == PacketType.Configuration.Server.CONFIGURATION_END) {
user.setEncoderState(ConnectionState.PLAY);
}
}
@@ -121,17 +154,17 @@ public class InternalPacketListener extends PacketListenerAbstract {
WrapperHandshakingClientHandshake handshake = new WrapperHandshakingClientHandshake(event);
ConnectionState nextState = handshake.getNextConnectionState();
ClientVersion clientVersion = handshake.getClientVersion();
if (clientVersion == ClientVersion.UNKNOWN) {
return;
}
//Update client version for this event call(and user)
user.setClientVersion(clientVersion);
PacketEvents.getAPI().getLogManager().debug("Processed " + address.getHostString() + ":" + address.getPort() + "'s client version. Client Version: " + clientVersion.getReleaseName());
event.getPostTasks().add(() -> {
//Transition into the LOGIN OR STATUS connection state
PacketEvents.getAPI().getInjector().changeConnectionState(channel, nextState);
PacketEvents.getAPI().getLogManager().debug("Transitioned " + address.getHostString() + ":" + address.getPort() + " into the " + nextState + " state!");
});
//Transition into LOGIN or STATUS connection state immediately, to remain in sync with vanilla
user.setConnectionState(nextState);
} else if (event.getPacketType() == PacketType.Login.Client.LOGIN_SUCCESS_ACK) {
user.setDecoderState(ConnectionState.CONFIGURATION);
} else if (event.getPacketType() == PacketType.Play.Client.CONFIGURATION_ACK) {
user.setDecoderState(ConnectionState.CONFIGURATION);
} else if (event.getPacketType() == PacketType.Configuration.Client.CONFIGURATION_END_ACK) {
user.setDecoderState(ConnectionState.PLAY);
}
}
}
}
@@ -20,12 +20,12 @@ package com.github.retrooper.packetevents.manager.protocol;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.netty.channel.ChannelHelper;
import com.github.retrooper.packetevents.protocol.ConnectionState;
import com.github.retrooper.packetevents.protocol.ProtocolVersion;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.protocol.player.User;
import com.github.retrooper.packetevents.util.PacketTransformationUtil;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import org.jetbrains.annotations.ApiStatus;
import java.util.Collection;
import java.util.Map;
@@ -34,6 +34,7 @@ import java.util.concurrent.ConcurrentHashMap;
public interface ProtocolManager {
Map<UUID, Object> CHANNELS = new ConcurrentHashMap<>();
// Use SocketAddress because ProtocolLib wraps Channels with NettyChannelProxy class
Map<Object, User> USERS = new ConcurrentHashMap<>();
default Collection<User> getUsers() {
@@ -91,67 +92,70 @@ public interface ProtocolManager {
}
}
//TODO Make it clear that this only updates the connection state in our user.
//Sometimes you should use getInjector().changeConnectionState because that can allow the injector to make adjustments.
//This is very important, especially on Spigot.
//As soon as we switch to the play state on spigot, our injector makes some adjustments.
default void changeConnectionState(Object channel, ConnectionState connectionState) {
getUser(channel).setConnectionState(connectionState);
}
default void setClientVersion(Object channel, ClientVersion version) {
getUser(channel).setClientVersion(version);
}
default Object[] transformWrappers(PacketWrapper<?> wrapper) {
@ApiStatus.Internal
default Object[] transformWrappers(PacketWrapper<?> wrapper, Object channel, boolean outgoing) {
//It is possible that our packet transformer util decides to transform one wrapper into multiple packets.
//(Correcting some mistakes on your end)
PacketWrapper<?>[] wrappers = PacketTransformationUtil.transform(wrapper);
Object[] buffers = new Object[wrappers.length];
for (int i = 0; i < wrappers.length; i++) {
wrappers[i].prepareForSend();
wrappers[i].prepareForSend(channel, outgoing);
buffers[i] = wrappers[i].buffer;
// Fix race condition when sending packets to multiple people (due to when the buffer is freed)
wrappers[i].buffer = null;
}
return buffers;
}
default void sendPacket(Object channel, PacketWrapper<?> wrapper) {
Object[] transformed = transformWrappers(wrapper);
Object[] transformed = transformWrappers(wrapper, channel, true);
sendPackets(channel, transformed);
}
default void sendPacketSilently(Object channel, PacketWrapper<?> wrapper) {
Object[] transformed = transformWrappers(wrapper);
Object[] transformed = transformWrappers(wrapper, channel, true);
sendPacketsSilently(channel, transformed);
}
default void writePacket(Object channel, PacketWrapper<?> wrapper) {
Object[] transformed = transformWrappers(wrapper);
Object[] transformed = transformWrappers(wrapper, channel, true);
writePackets(channel, transformed);
}
default void writePacketSilently(Object channel, PacketWrapper<?> wrapper) {
Object[] transformed = transformWrappers(wrapper);
Object[] transformed = transformWrappers(wrapper, channel, true);
writePacketsSilently(channel, transformed);
}
default void receivePacket(Object channel, PacketWrapper<?> wrapper) {
Object[] transformed = transformWrappers(wrapper);
Object[] transformed = transformWrappers(wrapper, channel, false);
receivePackets(channel, transformed);
}
default void receivePacketSilently(Object channel, PacketWrapper<?> wrapper) {
Object[] transformed = transformWrappers(wrapper);
Object[] transformed = transformWrappers(wrapper, channel, false);
receivePacketsSilently(channel, transformed);
}
default User getUser(Object channel) {
return USERS.get(channel);
Object pipeline = ChannelHelper.getPipeline(channel);
return USERS.get(pipeline);
}
default User removeUser(Object channel) {
Object pipeline = ChannelHelper.getPipeline(channel);
return USERS.remove(pipeline);
}
default void setUser(Object channel, User user) {
synchronized (channel) {
USERS.put(channel, user);
Object pipeline = ChannelHelper.getPipeline(channel);
USERS.put(pipeline, user);
}
PacketEvents.getAPI().getInjector().updateUser(channel, user);
}
@@ -46,7 +46,9 @@ public enum ServerVersion {
V_1_17(755), V_1_17_1(756),
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(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
V_1_20(763), V_1_20_1(763), V_1_20_2(764),
//TODO UPDATE Add server version constant
ERROR(-1, true);
@@ -81,6 +81,10 @@ public class ChannelHelper {
return Arrays.toString(pipelineHandlerNames(channel).toArray(new String[0]));
}
public static Object getPipeline(Object channel) {
return PacketEvents.getAPI().getNettyManager().getChannelOperator().getPipeline(channel);
}
public static Object getPipelineHandler(Object channel, String name) {
return PacketEvents.getAPI().getNettyManager().getChannelOperator().getPipelineHandler(channel, name);
}
@@ -89,6 +93,10 @@ public class ChannelHelper {
return PacketEvents.getAPI().getNettyManager().getChannelOperator().getPipelineContext(channel, handlerName);
}
public static Object pooledByteBuf(Object channel) {
return PacketEvents.getAPI().getNettyManager().getChannelOperator().pooledByteBuf(channel);
}
public static void runInEventLoop(Object channel, Runnable runnable) {
PacketEvents.getAPI().getNettyManager().getChannelOperator().runInEventLoop(channel, runnable);
}
@@ -20,26 +20,41 @@ package com.github.retrooper.packetevents.netty.channel;
import java.net.SocketAddress;
import java.util.List;
import java.util.Set;
public interface ChannelOperator {
Set<Class<? extends Throwable>> getIgnoredHandlerExceptions();
SocketAddress remoteAddress(Object channel);
SocketAddress localAddress(Object channel);
boolean isOpen(Object channel);
Object close(Object channel);
Object write(Object channel, Object buffer);
Object flush(Object channel);
Object writeAndFlush(Object channel, Object buffer);
Object fireChannelRead(Object channel, Object buffer);
Object writeInContext(Object channel, String ctx, Object buffer);
Object flushInContext(Object channel, String ctx);
Object writeAndFlushInContext(Object channel, String ctx, Object buffer);
Object fireChannelReadInContext(Object channel, String ctx, Object buffer);
List<String> pipelineHandlerNames(Object channel);
Object getPipelineHandler(Object channel, String name);
Object getPipelineContext(Object channel, String name);
Object getPipeline(Object channel);
void runInEventLoop(Object channel, Runnable runnable);
Object pooledByteBuf(Object channel);
}
@@ -23,7 +23,7 @@ package com.github.retrooper.packetevents.protocol;
* @since 1.8
*/
public enum ConnectionState {
HANDSHAKING, STATUS, LOGIN, PLAY;
HANDSHAKING, STATUS, LOGIN, PLAY, CONFIGURATION;
public static ConnectionState getById(int id) {
if (id >= values().length || id < 0) {
@@ -5,6 +5,7 @@ import org.jetbrains.annotations.Nullable;
import java.io.DataOutput;
import java.io.IOException;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;
import java.util.UUID;
@@ -32,6 +33,22 @@ public class LastSeenMessages {
return entries;
}
public static class Packed {
private List<MessageSignature.Packed> packedMessageSignatures;
public Packed(List<MessageSignature.Packed> packedMessageSignatures) {
this.packedMessageSignatures = packedMessageSignatures;
}
public List<MessageSignature.Packed> getPackedMessageSignatures() {
return packedMessageSignatures;
}
public void setPackedMessageSignatures(List<MessageSignature.Packed> packedMessageSignatures) {
this.packedMessageSignatures = packedMessageSignatures;
}
}
public static class Entry {
private final UUID uuid;
private final byte[] signature;
@@ -50,11 +67,11 @@ public class LastSeenMessages {
}
}
public static class Update {
public static class LegacyUpdate {
private final LastSeenMessages lastSeenMessages;
private final @Nullable Entry lastReceived;
public Update(LastSeenMessages lastSeenMessages, @Nullable Entry lastReceived) {
public LegacyUpdate(LastSeenMessages lastSeenMessages, @Nullable Entry lastReceived) {
this.lastSeenMessages = lastSeenMessages;
this.lastReceived = lastReceived;
}
@@ -67,4 +84,22 @@ public class LastSeenMessages {
return lastReceived;
}
}
public static class Update {
private final int offset;
private final BitSet acknowledged;
public Update(int offset, BitSet acknowledged) {
this.offset = offset;
this.acknowledged = acknowledged;
}
public int getOffset() {
return offset;
}
public BitSet getAcknowledged() {
return acknowledged;
}
}
}
@@ -0,0 +1,70 @@
/*
* 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.chat;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
public class MessageSignature {
private byte[] bytes;
public MessageSignature(byte[] bytes) {
this.bytes = bytes;
}
public byte[] getBytes() {
return bytes;
}
public void setBytes(byte[] bytes) {
this.bytes = bytes;
}
public static class Packed {
private int id;
private @Nullable MessageSignature fullSignature;
public Packed(@Nullable MessageSignature fullSignature) {
this.id = -1;
this.fullSignature = fullSignature;
}
public Packed(int id) {
this.id = id;
this.fullSignature = null;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Optional<MessageSignature> getFullSignature() {
return Optional.ofNullable(fullSignature);
}
public void setFullSignature(@Nullable MessageSignature fullSignature) {
this.fullSignature = fullSignature;
}
}
}
@@ -0,0 +1,102 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.chat;
import com.github.retrooper.packetevents.resources.ResourceLocation;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Optional;
public class Node {
private byte flags;
private List<Integer> children;
private Optional<Integer> 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) {
this.flags = flags;
this.children = children;
this.redirectNodeIndex = Optional.ofNullable(redirectNodeIndex);
this.name = Optional.ofNullable(name);
this.parserID = Optional.ofNullable(parserID);
this.properties = Optional.ofNullable(properties);
this.suggestionsType = Optional.ofNullable(suggestionsType);
}
public byte getFlags() {
return flags;
}
public void setFlags(byte flags) {
this.flags = flags;
}
public List<Integer> getChildren() {
return children;
}
public void setChildren(List<Integer> children) {
this.children = children;
}
public Optional<Integer> getRedirectNodeIndex() {
return redirectNodeIndex;
}
public void setRedirectNodeIndex(Optional<Integer> redirectNodeIndex) {
this.redirectNodeIndex = redirectNodeIndex;
}
public Optional<String> getName() {
return name;
}
public void setName(Optional<String> name) {
this.name = name;
}
public Optional<Integer> getParserID() {
return parserID;
}
public void setParserID(Optional<Integer> parserID) {
this.parserID = parserID;
}
public Optional<List<Object>> getProperties() {
return properties;
}
public void setProperties(Optional<List<Object>> properties) {
this.properties = properties;
}
public Optional<ResourceLocation> getSuggestionsType() {
return suggestionsType;
}
public void setSuggestionsType(Optional<ResourceLocation> suggestionsType) {
this.suggestionsType = suggestionsType;
}
}
@@ -0,0 +1,185 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.chat;
import com.github.retrooper.packetevents.resources.ResourceLocation;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
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("brigadier:entity",
packetWrapper -> Collections.singletonList(packetWrapper.readByte()),
(packetWrapper, properties) -> packetWrapper.writeByte(((Byte) properties.get(0)).intValue())
),
new Parser("brigadier:game_profile", null, null),
new Parser("brigadier:block_pos", null, null),
new Parser("brigadier:column_pos", null, null),
new Parser("brigadier:vec3", null, null),
new Parser("brigadier:vec2", null, null),
new Parser("brigadier:block_state", null, null),
new Parser("brigadier:block_predicate", null, null),
new Parser("brigadier:item_stack", null, null),
new Parser("brigadier:item_predicate", null, null),
new Parser("brigadier:color", null, null),
new Parser("brigadier:component", null, null),
new Parser("brigadier:message", null, null),
new Parser("brigadier:nbt", null, null),
new Parser("brigadier:nbt_tag", null, null),
new Parser("brigadier:nbt_path", null, null),
new Parser("brigadier:objective", null, null),
new Parser("brigadier:objective_criteria", null, null),
new Parser("brigadier:operation", null, null),
new Parser("brigadier:particle", null, null),
new Parser("brigadier:angle", null, null),
new Parser("brigadier:rotation", null, null),
new Parser("brigadier:scoreboard_slot", null, null),
new Parser("brigadier:score_holder",
packetWrapper -> Collections.singletonList(packetWrapper.readByte()),
(packetWrapper, properties) -> packetWrapper.writeByte(((Byte) properties.get(0)).intValue())
),
new Parser("brigadier:swizzle", null, null),
new Parser("brigadier:team", null, null),
new Parser("brigadier:item_slot", null, null),
new Parser("brigadier:resource_location", null, null),
new Parser("brigadier:function", null, null),
new Parser("brigadier:entity_anchor", null, null),
new Parser("brigadier:int_range", null, null),
new Parser("brigadier:float_range", null, null),
new Parser("brigadier:dimension", null, null),
new Parser("brigadier:gamemode", null, null),
new Parser("brigadier:time",
packetWrapper -> Collections.singletonList(packetWrapper.readInt()),
(packetWrapper, properties) -> packetWrapper.writeInt((int) properties.get(0))
),
new Parser("brigadier:resource_or_tag",
packetWrapper -> Collections.singletonList(packetWrapper.readIdentifier()),
(packetWrapper, properties) -> packetWrapper.writeIdentifier((ResourceLocation) properties.get(0))
),
new Parser("brigadier:resource_or_tag_key",
packetWrapper -> Collections.singletonList(packetWrapper.readIdentifier()),
(packetWrapper, properties) -> packetWrapper.writeIdentifier((ResourceLocation) properties.get(0))
),
new Parser("brigadier:resource",
packetWrapper -> Collections.singletonList(packetWrapper.readIdentifier()),
(packetWrapper, properties) -> packetWrapper.writeIdentifier((ResourceLocation) properties.get(0))
),
new Parser("brigadier:resource_key",
packetWrapper -> Collections.singletonList(packetWrapper.readIdentifier()),
(packetWrapper, properties) -> packetWrapper.writeIdentifier((ResourceLocation) properties.get(0))
),
new Parser("brigadier:template_mirror", null, null),
new Parser("brigadier:template_rotation", null, null),
new Parser("brigadier:heightmap", null, null),
new Parser("brigadier:uuid", null, null)
);
public static List<Parser> getParsers() {
return parsers;
}
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 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);
}
public Optional<List<Object>> readProperties(PacketWrapper<?> packetWrapper) {
return read.map(fn -> fn.apply(packetWrapper));
}
public void writeProperties(PacketWrapper<?> packetWrapper, List<Object> properties) {
write.ifPresent(fn -> fn.accept(packetWrapper, properties));
}
}
}
@@ -0,0 +1,41 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.chat;
import com.github.retrooper.packetevents.protocol.player.PublicProfileKey;
import java.util.UUID;
public class RemoteChatSession {
private final UUID sessionId;
private final PublicProfileKey publicProfileKey;
public RemoteChatSession(UUID sessionId, PublicProfileKey publicProfileKey) {
this.sessionId = sessionId;
this.publicProfileKey = publicProfileKey;
}
public UUID getSessionId() {
return sessionId;
}
public PublicProfileKey getPublicProfileKey() {
return publicProfileKey;
}
}
@@ -0,0 +1,27 @@
package com.github.retrooper.packetevents.protocol.chat;
public class SignedCommandArgument {
private String argument;
private byte[] signature;
public SignedCommandArgument(String argument, byte[] signature) {
this.argument = argument;
this.signature = signature;
}
public String getArgument() {
return argument;
}
public void setArgument(String argument) {
this.argument = argument;
}
public byte[] getSignature() {
return signature;
}
public void setSignature(byte[] signature) {
this.signature = signature;
}
}
@@ -24,10 +24,9 @@ import org.jetbrains.annotations.Nullable;
import java.time.Instant;
import java.util.UUID;
public class ChatMessage_v1_19 extends ChatMessage {
//We'll extend ChatMessage_v1_16 for now, hopefully no breaking changes in the future
public class ChatMessage_v1_19 extends ChatMessage_v1_16 {
private @Nullable Component unsignedChatContent;
private UUID senderUUID;
private Component senderDisplayName;
private @Nullable Component teamName;
private Instant timestamp;
@@ -37,9 +36,8 @@ public class ChatMessage_v1_19 extends ChatMessage {
public ChatMessage_v1_19(Component chatContent, @Nullable Component unsignedChatContent, ChatType type,
UUID senderUUID, Component senderDisplayName, @Nullable Component teamName, Instant timestamp,
long salt, byte[] signature) {
super(chatContent, type);
super(chatContent, type, senderUUID);
this.unsignedChatContent = unsignedChatContent;
this.senderUUID = senderUUID;
this.senderDisplayName = senderDisplayName;
this.teamName = teamName;
this.timestamp = timestamp;
@@ -51,10 +49,6 @@ public class ChatMessage_v1_19 extends ChatMessage {
return unsignedChatContent;
}
public UUID getSenderUUID() {
return senderUUID;
}
public Component getSenderDisplayName() {
return senderDisplayName;
}
@@ -79,10 +73,6 @@ public class ChatMessage_v1_19 extends ChatMessage {
this.unsignedChatContent = unsignedChatContent;
}
public void setSenderUUID(UUID senderUUID) {
this.senderUUID = senderUUID;
}
public void setSenderDisplayName(Component senderDisplayName) {
this.senderDisplayName = senderDisplayName;
}
@@ -26,11 +26,10 @@ import org.jetbrains.annotations.Nullable;
import java.time.Instant;
import java.util.UUID;
public class ChatMessage_v1_19_1 extends ChatMessage {
//We'll extend ChatMessage_v1_16 for now, hopefully no breaking changes in the future
public class ChatMessage_v1_19_1 extends ChatMessage_v1_16 {
private String plainContent;
private @Nullable Component unsignedChatContent;
private UUID senderUUID;
private ChatTypeBoundNetwork chatType;
private byte @Nullable [] previousSignature;
private byte[] signature;
@@ -46,10 +45,9 @@ public class ChatMessage_v1_19_1 extends ChatMessage {
Instant timestamp, long salt,
LastSeenMessages lastSeenMessages,
FilterMask filterMask) {
super(decoratedChatContent, chatType.getType());
super(decoratedChatContent, chatType.getType(), senderUUID);
this.plainContent = plainContent;
this.unsignedChatContent = unsignedChatContent;
this.senderUUID = senderUUID;
this.chatType = chatType;
this.previousSignature = previousSignature;
this.signature = signature;
@@ -79,14 +77,6 @@ public class ChatMessage_v1_19_1 extends ChatMessage {
this.unsignedChatContent = unsignedChatContent;
}
public UUID getSenderUUID() {
return senderUUID;
}
public void setSenderUUID(UUID senderUUID) {
this.senderUUID = senderUUID;
}
@Override
public ChatType getType() {
return chatType.getType();
@@ -0,0 +1,119 @@
package com.github.retrooper.packetevents.protocol.chat.message;
import com.github.retrooper.packetevents.protocol.chat.LastSeenMessages;
import com.github.retrooper.packetevents.protocol.chat.filter.FilterMask;
import com.github.retrooper.packetevents.util.adventure.AdventureSerializer;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.Nullable;
import java.time.Instant;
import java.util.Optional;
import java.util.UUID;
//We'll extend ChatMessage_v1_16 for now, hopefully no breaking changes in the future
public class ChatMessage_v1_19_3 extends ChatMessage_v1_16 {
int index;
byte[] signature;
String plainContent;
Instant timestamp;
long salt;
LastSeenMessages.Packed lastSeenMessagesPacked;
@Nullable Component unsignedChatContent;
FilterMask filterMask;
ChatMessage_v1_19_1.ChatTypeBoundNetwork chatType;
public ChatMessage_v1_19_3(UUID senderUUID, int index, byte[] signature, String plainContent, Instant timestamp, long salt, LastSeenMessages.Packed lastSeenMessagesPacked, @Nullable Component unsignedChatContent, FilterMask filterMask, ChatMessage_v1_19_1.ChatTypeBoundNetwork chatType) {
super(Component.text(plainContent), chatType.getType(), senderUUID);
this.index = index;
this.signature = signature;
this.plainContent = plainContent;
this.timestamp = timestamp;
this.salt = salt;
this.lastSeenMessagesPacked = lastSeenMessagesPacked;
this.unsignedChatContent = unsignedChatContent;
this.filterMask = filterMask;
this.chatType = chatType;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public byte[] getSignature() {
return signature;
}
public void setSignature(byte[] signature) {
this.signature = signature;
}
@Override
public Component getChatContent() {
return Component.text(plainContent);
}
@Deprecated
@Override
public void setChatContent(Component chatContent) {
throw new UnsupportedOperationException("PacketEvents is not able to serialize components to plain-text. Please use the #setPlainContent instead to update the content.");
}
public String getPlainContent() {
return plainContent;
}
public void setPlainContent(String plainContent) {
this.plainContent = plainContent;
}
public Instant getTimestamp() {
return timestamp;
}
public void setTimestamp(Instant timestamp) {
this.timestamp = timestamp;
}
public long getSalt() {
return salt;
}
public void setSalt(long salt) {
this.salt = salt;
}
public LastSeenMessages.Packed getLastSeenMessagesPacked() {
return lastSeenMessagesPacked;
}
public void setLastSeenMessagesPacked(LastSeenMessages.Packed lastSeenMessagesPacked) {
this.lastSeenMessagesPacked = lastSeenMessagesPacked;
}
public Optional<Component> getUnsignedChatContent() {
return Optional.ofNullable(unsignedChatContent);
}
public void setUnsignedChatContent(@Nullable Component unsignedChatContent) {
this.unsignedChatContent = unsignedChatContent;
}
public FilterMask getFilterMask() {
return filterMask;
}
public void setFilterMask(FilterMask filterMask) {
this.filterMask = filterMask;
}
public ChatMessage_v1_19_1.ChatTypeBoundNetwork getChatType() {
return chatType;
}
public void setChatType(ChatMessage_v1_19_1.ChatTypeBoundNetwork chatType) {
this.chatType = chatType;
}
}
@@ -40,7 +40,9 @@ public class ChatMessageProcessor_v1_19_1 implements ChatMessageProcessor {
byte[] signature = wrapper.readByteArray();
String plainContent = wrapper.readString(256);
Component chatContent = wrapper.readOptional(PacketWrapper::readComponent);
if (chatContent == null) {
if (chatContent == null && plainContent.isEmpty()) {
chatContent = Component.empty();
} else if (chatContent == null) {
chatContent = Component.text(plainContent);
}
Instant timestamp = wrapper.readTimestamp();
@@ -48,13 +50,7 @@ public class ChatMessageProcessor_v1_19_1 implements ChatMessageProcessor {
LastSeenMessages lastSeenMessages = wrapper.readLastSeenMessages();
Component unsignedChatContent = wrapper.readOptional(PacketWrapper::readComponent);
FilterMask filterMask = wrapper.readFilterMask();
int id = wrapper.readVarInt();
ChatType type = ChatTypes.getById(wrapper.getServerVersion().toClientVersion(), id);
Component name = wrapper.readComponent();
Component targetName = wrapper.readOptional(PacketWrapper::readComponent);
ChatMessage_v1_19_1.ChatTypeBoundNetwork chatType = new ChatMessage_v1_19_1.ChatTypeBoundNetwork(type, name, targetName);
ChatMessage_v1_19_1.ChatTypeBoundNetwork chatType = wrapper.readChatTypeBoundNetwork();
return new ChatMessage_v1_19_1(plainContent, chatContent, unsignedChatContent, senderUUID, chatType,
previousSignature, signature, timestamp, salt, lastSeenMessages, filterMask);
}
@@ -72,8 +68,6 @@ public class ChatMessageProcessor_v1_19_1 implements ChatMessageProcessor {
wrapper.writeLastSeenMessages(newData.getLastSeenMessages());
wrapper.writeOptional(newData.getUnsignedChatContent(), PacketWrapper::writeComponent);
wrapper.writeFilterMask(newData.getFilterMask());
wrapper.writeVarInt(newData.getChatType().getType().getId(wrapper.getServerVersion().toClientVersion()));
wrapper.writeComponent(newData.getChatType().getName());
wrapper.writeOptional(newData.getChatType().getTargetName(), PacketWrapper::writeComponent);
wrapper.writeChatTypeBoundNetwork(newData.getChatType());
}
}
@@ -0,0 +1,47 @@
package com.github.retrooper.packetevents.protocol.chat.message.reader.impl;
import com.github.retrooper.packetevents.protocol.chat.LastSeenMessages;
import com.github.retrooper.packetevents.protocol.chat.filter.FilterMask;
import com.github.retrooper.packetevents.protocol.chat.message.ChatMessage;
import com.github.retrooper.packetevents.protocol.chat.message.ChatMessage_v1_19_1;
import com.github.retrooper.packetevents.protocol.chat.message.ChatMessage_v1_19_3;
import com.github.retrooper.packetevents.protocol.chat.message.reader.ChatMessageProcessor;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.NotNull;
import java.time.Instant;
import java.util.UUID;
public class ChatMessageProcessor_v1_19_3 implements ChatMessageProcessor {
@Override
public ChatMessage readChatMessage(@NotNull PacketWrapper<?> wrapper) {
UUID senderUUID = wrapper.readUUID();
int index = wrapper.readVarInt();
byte[] signature = wrapper.readOptional((w) -> w.readBytes(256));
String plainContent = wrapper.readString(256);
Instant timestamp = wrapper.readTimestamp();
long salt = wrapper.readLong();
LastSeenMessages.Packed lastSeenMessagesPacked = wrapper.readLastSeenMessagesPacked();
Component unsignedChatContent = wrapper.readOptional(PacketWrapper::readComponent);
FilterMask filterMask = wrapper.readFilterMask();
ChatMessage_v1_19_1.ChatTypeBoundNetwork chatType = wrapper.readChatTypeBoundNetwork();
return new ChatMessage_v1_19_3(senderUUID, index, signature, plainContent, timestamp, salt, lastSeenMessagesPacked, unsignedChatContent, filterMask, chatType);
}
@Override
public void writeChatMessage(@NotNull PacketWrapper<?> wrapper, @NotNull ChatMessage data) {
ChatMessage_v1_19_3 newData = (ChatMessage_v1_19_3) data;
wrapper.writeUUID(newData.getSenderUUID());
wrapper.writeVarInt(newData.getIndex());
wrapper.writeOptional(newData.getSignature(), PacketWrapper::writeBytes);
wrapper.writeString(newData.getPlainContent());
wrapper.writeTimestamp(newData.getTimestamp());
wrapper.writeLong(newData.getSalt());
wrapper.writeLastSeenMessagesPacked(newData.getLastSeenMessagesPacked());
wrapper.writeOptional(newData.getUnsignedChatContent().orElse(null), PacketWrapper::writeComponent);
wrapper.writeFilterMask(newData.getFilterMask());
wrapper.writeChatTypeBoundNetwork(newData.getChatType());
}
}
@@ -21,6 +21,7 @@ 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.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;
@@ -31,12 +32,8 @@ 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.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.*;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import net.kyori.adventure.text.Component;
import java.util.HashMap;
import java.util.Map;
@@ -59,7 +56,9 @@ public class EntityDataTypes {
ClientVersion.V_1_11,
ClientVersion.V_1_13,
ClientVersion.V_1_14,
ClientVersion.V_1_19);
ClientVersion.V_1_19,
ClientVersion.V_1_19_3,
ClientVersion.V_1_19_4);
public static final EntityDataType<Byte> BYTE = define("byte", PacketWrapper::readByte, PacketWrapper::writeByte);
@@ -79,13 +78,15 @@ public class EntityDataTypes {
}
});
public static final EntityDataType<Long> LONG = define("long", PacketWrapper::readVarLong, PacketWrapper::writeVarLong);
public static final EntityDataType<Float> FLOAT = define("float", PacketWrapper::readFloat, PacketWrapper::writeFloat);
public static final EntityDataType<String> STRING = define("string", PacketWrapper::readString, PacketWrapper::writeString);
public static final EntityDataType<Component> COMPONENT = define("component", PacketWrapper::readComponent, PacketWrapper::writeComponent);
public static final EntityDataType<String> COMPONENT = define("component", PacketWrapper::readComponentJSON, PacketWrapper::writeComponentJSON);
public static final EntityDataType<Optional<Component>> OPTIONAL_COMPONENT = define("optional_component", readOptionalComponentDeserializer(), writeOptionalComponentSerializer());
public static final EntityDataType<Optional<String>> OPTIONAL_COMPONENT = define("optional_component", readOptionalComponentDeserializer(), writeOptionalComponentSerializer());
public static final EntityDataType<ItemStack> ITEMSTACK = define("itemstack", PacketWrapper::readItemStack, PacketWrapper::writeItemStack);
@@ -136,6 +137,9 @@ public class EntityDataTypes {
(PacketWrapper<?> wrapper, Optional<UUID> value) ->
wrapper.writeOptional(value.orElse(null), PacketWrapper::writeUUID));
public static final EntityDataType<Integer> BLOCK_STATE = define("block_state",
readIntDeserializer(), writeIntSerializer());
public static final EntityDataType<Integer> OPTIONAL_BLOCK_STATE = define("optional_block_state", readIntDeserializer(), writeIntSerializer());
public static final EntityDataType<NBTCompound> NBT = define("nbt", PacketWrapper::readNBT, PacketWrapper::writeNBT);
@@ -176,6 +180,29 @@ public class EntityDataTypes {
public static final EntityDataType<Integer> PAINTING_VARIANT_TYPE = define("painting_variant_type", readIntDeserializer(), writeIntSerializer());
public static final EntityDataType<SnifferState> SNIFFER_STATE = define("sniffer_state", (PacketWrapper<?> wrapper) -> {
int id = wrapper.readVarInt();
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) -> {
wrapper.writeFloat(value.x);
wrapper.writeFloat(value.y);
wrapper.writeFloat(value.z);
});
public static final EntityDataType<Quaternion4f> QUATERNION = define("quaternion",
(PacketWrapper<?> wrapper) -> new Quaternion4f(wrapper.readFloat(), wrapper.readFloat(), wrapper.readFloat(), wrapper.readFloat()),
(PacketWrapper<?> wrapper, Quaternion4f value) -> {
wrapper.writeFloat(value.getX());
wrapper.writeFloat(value.getY());
wrapper.writeFloat(value.getZ());
wrapper.writeFloat(value.getW());
});
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);
@@ -232,7 +259,7 @@ public class EntityDataTypes {
private static <T> Function<PacketWrapper<?>, T> readOptionalComponentDeserializer() {
return (PacketWrapper<?> wrapper) -> {
if (wrapper.readBoolean()) {
return (T) Optional.of(wrapper.readComponent());
return (T) Optional.of(wrapper.readString());
} else {
return (T) Optional.empty();
}
@@ -242,10 +269,10 @@ public class EntityDataTypes {
private static <T> BiConsumer<PacketWrapper<?>, T> writeOptionalComponentSerializer() {
return (PacketWrapper<?> wrapper, T value) -> {
if (value instanceof Optional) {
Optional<Component> optional = (Optional<Component>) value;
Optional<String> optional = (Optional<String>) value;
if (optional.isPresent()) {
wrapper.writeBoolean(true);
wrapper.writeComponent(optional.get());
wrapper.writeString(optional.get());
} else {
wrapper.writeBoolean(false);
}
@@ -0,0 +1,7 @@
package com.github.retrooper.packetevents.protocol.entity.data;
import java.util.List;
public interface EntityMetadataProvider {
List<EntityData> entityData();
}
@@ -1,343 +0,0 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 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.data.provider;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import com.github.retrooper.packetevents.protocol.entity.pose.EntityPose;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class EntityDataProvider implements DataProvider {
@Nullable
private Component customName;
private boolean customNameVisible;
private EntityPose pose = EntityPose.STANDING;
private int airTicks;
private int ticksFrozenInPowderedSnow = 0;
private boolean onFire;
private boolean crouching;
//Now unused
private boolean riding;
private boolean sprinting;
private boolean swimming;
private boolean invisible;
private boolean glowing;
private boolean flyingWithElytra;
private boolean silent;
private boolean hasGravity = true;
@Nullable
public Component getCustomName() {
return customName;
}
public void setCustomName(@Nullable Component customName) {
this.customName = customName;
}
public boolean isCustomNameVisible() {
return customNameVisible;
}
public void setCustomNameVisible(boolean customNameVisible) {
this.customNameVisible = customNameVisible;
}
public EntityPose getPose() {
return pose;
}
public void setPose(EntityPose pose) {
this.pose = pose;
}
public int getAirTicks() {
return airTicks;
}
public void setAirTicks(int airTicks) {
this.airTicks = airTicks;
}
public int getTicksFrozenInPowderedSnow() {
return ticksFrozenInPowderedSnow;
}
public void setTicksFrozenInPowderedSnow(int ticksFrozenInPowderedSnow) {
this.ticksFrozenInPowderedSnow = ticksFrozenInPowderedSnow;
}
public boolean isOnFire() {
return onFire;
}
public void setOnFire(boolean onFire) {
this.onFire = onFire;
}
public boolean isCrouching() {
return crouching;
}
public void setCrouching(boolean crouching) {
this.crouching = crouching;
}
public boolean isRiding() {
return riding;
}
public void setRiding(boolean riding) {
this.riding = riding;
}
public boolean isSprinting() {
return sprinting;
}
public void setSprinting(boolean sprinting) {
this.sprinting = sprinting;
}
public boolean isSwimming() {
return swimming;
}
public void setSwimming(boolean swimming) {
this.swimming = swimming;
}
public boolean isInvisible() {
return invisible;
}
public void setInvisible(boolean invisible) {
this.invisible = invisible;
}
public boolean isGlowing() {
return glowing;
}
public void setGlowing(boolean glowing) {
this.glowing = glowing;
}
public boolean isFlyingWithElytra() {
return flyingWithElytra;
}
public void setFlyingWithElytra(boolean flyingWithElytra) {
this.flyingWithElytra = flyingWithElytra;
}
public boolean isSilent() {
return silent;
}
public void setSilent(boolean silent) {
this.silent = silent;
}
public boolean isHasGravity() {
return hasGravity;
}
public void setHasGravity(boolean hasGravity) {
this.hasGravity = hasGravity;
}
@Override
public List<EntityData> encode() {
byte mask = 0x00;
if (onFire) {
mask |= 0x01;
}
if (crouching) {
mask |= 0x02;
}
//TODO Rethink, should we add this?
if (riding) {
mask |= 0x04;
}
if (sprinting) {
mask |= 0x08;
}
if (swimming) {
mask |= 0x10;
}
if (invisible) {
mask |= 0x20;
}
if (glowing) {
mask |= 0x40;
}
if (flyingWithElytra) {
mask |= 0x80;
}
List<EntityData> metadata = new ArrayList<>(8);
metadata.add(new EntityData(0, EntityDataTypes.BYTE, mask));
metadata.add(new EntityData(1, EntityDataTypes.INT, airTicks));
metadata.add(new EntityData(2, EntityDataTypes.OPTIONAL_COMPONENT, Optional.ofNullable(customName)));
metadata.add(new EntityData(3, EntityDataTypes.BOOLEAN, customNameVisible));
metadata.add(new EntityData(4, EntityDataTypes.BOOLEAN, silent));
metadata.add(new EntityData(5, EntityDataTypes.BOOLEAN, !hasGravity));
metadata.add(new EntityData(6, EntityDataTypes.ENTITY_POSE, pose));
metadata.add(new EntityData(7, EntityDataTypes.INT, ticksFrozenInPowderedSnow));
return metadata;
}
@Override
public void decode(List<EntityData> data) {
for (EntityData entityData : data) {
switch (entityData.getIndex()) {
case 0:
byte mask = (byte) entityData.getValue();
onFire = (mask & 0x01) != 0;
crouching = (mask & 0x02) != 0;
riding = (mask & 0x04) != 0;
sprinting = (mask & 0x08) != 0;
swimming = (mask & 0x10) != 0;
invisible = (mask & 0x20) != 0;
glowing = (mask & 0x40) != 0;
flyingWithElytra = (mask & 0x80) != 0;
break;
case 1:
airTicks = (int) entityData.getValue();
break;
case 2:
customName = ((Optional<Component>) entityData.getValue()).orElse(null);
break;
case 3:
customNameVisible = (boolean) entityData.getValue();
break;
case 4:
silent = (boolean) entityData.getValue();
break;
case 5:
hasGravity = !(boolean) entityData.getValue();
break;
case 6:
pose = (EntityPose) entityData.getValue();
break;
case 7:
ticksFrozenInPowderedSnow = (int) entityData.getValue();
break;
}
}
}
public static EntityBuilder<EntityBuilder> builderEntity() {
return new EntityBuilder<>(new EntityDataProvider());
}
public static class EntityBuilder<T extends EntityBuilder> {
protected EntityDataProvider provider;
public EntityBuilder(EntityDataProvider provider) {
this.provider = provider;
}
public T customName(@Nullable Component customName) {
((EntityDataProvider) provider).setCustomName(customName);
return (T) this;
}
public T customNameVisible(boolean customNameVisible) {
((EntityDataProvider) provider).setCustomNameVisible(customNameVisible);
return (T) this;
}
public T pose(EntityPose pose) {
((EntityDataProvider) provider).setPose(pose);
return (T) this;
}
public T onFire(boolean onFire) {
((EntityDataProvider) provider).setOnFire(onFire);
return (T) this;
}
public T crouching(boolean crouching) {
((EntityDataProvider) provider).setCrouching(crouching);
return (T) this;
}
public T riding(boolean riding) {
((EntityDataProvider) provider).setRiding(riding);
return (T) this;
}
public T sprinting(boolean sprinting) {
((EntityDataProvider) provider).setSprinting(sprinting);
return (T) this;
}
public T swimming(boolean swimming) {
((EntityDataProvider) provider).setSwimming(swimming);
return (T) this;
}
public T invisible(boolean invisible) {
((EntityDataProvider) provider).setInvisible(invisible);
return (T) this;
}
public T glowing(boolean glowing) {
((EntityDataProvider) provider).setGlowing(glowing);
return (T) this;
}
public T flyingWithElytra(boolean flyingWithElytra) {
((EntityDataProvider) provider).setFlyingWithElytra(flyingWithElytra);
return (T) this;
}
public T silent(boolean silent) {
((EntityDataProvider) provider).setSilent(silent);
return (T) this;
}
public T hasGravity(boolean hasGravity) {
((EntityDataProvider) provider).setHasGravity(hasGravity);
return (T) this;
}
public T airTicks(int airTicks) {
((EntityDataProvider) provider).setAirTicks(airTicks);
return (T) this;
}
public T ticksFrozenInPowderedSnow(int ticksFrozenInPowderedSnow) {
((EntityDataProvider) provider).setTicksFrozenInPowderedSnow(ticksFrozenInPowderedSnow);
return (T) this;
}
public <K extends EntityDataProvider> K build() {
return (K) provider;
}
}
}
@@ -1,232 +0,0 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 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.data.provider;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import com.github.retrooper.packetevents.protocol.player.InteractionHand;
import com.github.retrooper.packetevents.util.Vector3i;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Optional;
public class LivingEntityDataProvider extends EntityDataProvider {
private boolean handActive;
private InteractionHand hand = InteractionHand.MAIN_HAND;
private boolean isInRiptideSpinAttack;
private float health = 1.0f;
private int potionEffectColor;
private boolean potionEffectAmbient;
private int arrowInBodyCount;
private int beeStingsInBodyCount;
@Nullable
private Vector3i sleepingPosition;
public boolean isHandActive() {
return handActive;
}
public void setHandActive(boolean handActive) {
this.handActive = handActive;
}
public InteractionHand getHand() {
return hand;
}
public void setHand(InteractionHand hand) {
this.hand = hand;
}
public boolean isInRiptideSpinAttack() {
return isInRiptideSpinAttack;
}
public void setInRiptideSpinAttack(boolean inRiptideSpinAttack) {
isInRiptideSpinAttack = inRiptideSpinAttack;
}
public float getHealth() {
return health;
}
public void setHealth(float health) {
this.health = health;
}
public int getPotionEffectColor() {
return potionEffectColor;
}
public void setPotionEffectColor(int potionEffectColor) {
this.potionEffectColor = potionEffectColor;
}
public boolean isPotionEffectAmbient() {
return potionEffectAmbient;
}
public void setPotionEffectAmbient(boolean potionEffectAmbient) {
this.potionEffectAmbient = potionEffectAmbient;
}
public int getArrowInBodyCount() {
return arrowInBodyCount;
}
public void setArrowInBodyCount(int arrowInBodyCount) {
this.arrowInBodyCount = arrowInBodyCount;
}
public int getBeeStingsInBodyCount() {
return beeStingsInBodyCount;
}
public void setBeeStingsInBodyCount(int beeStingsInBodyCount) {
this.beeStingsInBodyCount = beeStingsInBodyCount;
}
@Nullable
public Vector3i getSleepingPosition() {
return sleepingPosition;
}
public void setSleepingPosition(@Nullable Vector3i sleepingPosition) {
this.sleepingPosition = sleepingPosition;
}
public static LivingEntityBuilder<LivingEntityBuilder> builderLivingEntity() {
return new LivingEntityBuilder<>(new LivingEntityDataProvider());
}
@Override
public List<EntityData> encode() {
List<EntityData> metadata = super.encode();
byte mask = 0x00;
if (handActive) {
mask |= 0x01;
}
//TODO Confirm
if (hand == InteractionHand.OFF_HAND) {
mask |= 0x02;
}
if (isInRiptideSpinAttack) {
mask |= 0x04;
}
metadata.add(new EntityData(8, EntityDataTypes.BYTE, mask));
metadata.add(new EntityData(9, EntityDataTypes.FLOAT, health));
metadata.add(new EntityData(10, EntityDataTypes.INT, potionEffectColor));
metadata.add(new EntityData(11, EntityDataTypes.BOOLEAN, potionEffectAmbient));
metadata.add(new EntityData(12, EntityDataTypes.INT, arrowInBodyCount));
metadata.add(new EntityData(13, EntityDataTypes.INT, beeStingsInBodyCount));
metadata.add(new EntityData(14, EntityDataTypes.OPTIONAL_BLOCK_POSITION, Optional.ofNullable(sleepingPosition)));
return metadata;
}
@Override
public void decode(List<EntityData> data) {
super.decode(data);
for (EntityData entityData : data) {
switch (entityData.getIndex()) {
case 8:
byte mask = (byte) entityData.getValue();
handActive = (mask & 0x01) != 0;
//TODO Test, look into
hand = (mask & 0x02) != 0 ? InteractionHand.OFF_HAND : InteractionHand.MAIN_HAND;
isInRiptideSpinAttack = (mask & 0x04) != 0;
break;
case 9:
health = (float) entityData.getValue();
break;
case 10:
potionEffectColor = (int) entityData.getValue();
break;
case 11:
potionEffectAmbient = (boolean) entityData.getValue();
break;
case 12:
arrowInBodyCount = (int) entityData.getValue();
break;
case 13:
beeStingsInBodyCount = (int) entityData.getValue();
break;
case 14:
sleepingPosition = ((Optional<Vector3i>) entityData.getValue()).orElse(null);
break;
}
}
}
public static class LivingEntityBuilder<T extends LivingEntityBuilder> extends EntityDataProvider.EntityBuilder<T> {
public LivingEntityBuilder(LivingEntityDataProvider livingEntityDataProvider) {
super(livingEntityDataProvider);
}
public T handActive(boolean handActive) {
((LivingEntityDataProvider) provider).setHandActive(handActive);
return (T) this;
}
public T hand(InteractionHand hand) {
((LivingEntityDataProvider) provider).setHand(hand);
return (T) this;
}
public T isInRiptideSpinAttack(boolean isInRiptideSpinAttack) {
((LivingEntityDataProvider) provider).setInRiptideSpinAttack(isInRiptideSpinAttack);
return (T) this;
}
public T health(float health) {
((LivingEntityDataProvider) provider).setHealth(health);
return (T) this;
}
public T potionEffectColor(int potionEffectColor) {
((LivingEntityDataProvider) provider).setPotionEffectColor(potionEffectColor);
return (T) this;
}
public T potionEffectAmbient(boolean potionEffectAmbient) {
((LivingEntityDataProvider) provider).setPotionEffectAmbient(potionEffectAmbient);
return (T) this;
}
public T arrowInBodyCount(int arrowInBodyCount) {
((LivingEntityDataProvider) provider).setArrowInBodyCount(arrowInBodyCount);
return (T) this;
}
public T beeStingsInBodyCount(int beeStingsInBodyCount) {
((LivingEntityDataProvider) provider).setBeeStingsInBodyCount(beeStingsInBodyCount);
return (T) this;
}
public T sleepingPosition(@Nullable Vector3i sleepingPosition) {
((LivingEntityDataProvider) provider).setSleepingPosition(sleepingPosition);
return (T) this;
}
}
}
@@ -1,168 +0,0 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 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.data.provider;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
import com.github.retrooper.packetevents.protocol.player.HumanoidArm;
import com.github.retrooper.packetevents.protocol.player.SkinSection;
import java.util.List;
public class PlayerDataProvider extends LivingEntityDataProvider {
private float additionalHealth;
private int score;
private byte skinPartsMask = SkinSection.ALL.getMask();
private HumanoidArm mainArm = HumanoidArm.RIGHT;
private NBTCompound leftShoulderNBT = new NBTCompound();
private NBTCompound rightShoulderNBT = new NBTCompound();
public float getAdditionalHealth() {
return additionalHealth;
}
public void setAdditionalHealth(float additionalHealth) {
this.additionalHealth = additionalHealth;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public byte getSkinPartsMask() {
return skinPartsMask;
}
public void setSkinPartsMask(byte skinPartsMask) {
this.skinPartsMask = skinPartsMask;
}
public HumanoidArm getMainArm() {
return mainArm;
}
public void setMainArm(HumanoidArm mainArm) {
this.mainArm = mainArm;
}
public NBTCompound getLeftShoulderNBT() {
return leftShoulderNBT;
}
public void setLeftShoulderNBT(NBTCompound leftShoulderNBT) {
this.leftShoulderNBT = leftShoulderNBT;
}
public NBTCompound getRightShoulderNBT() {
return rightShoulderNBT;
}
public void setRightShoulderNBT(NBTCompound rightShoulderNBT) {
this.rightShoulderNBT = rightShoulderNBT;
}
public static PlayerBuilder<PlayerBuilder> builderPlayer() {
return new PlayerBuilder<>(new PlayerDataProvider());
}
@Override
public List<EntityData> encode() {
List<EntityData> metadata = super.encode();
metadata.add(new EntityData(15, EntityDataTypes.FLOAT, additionalHealth));
metadata.add(new EntityData(16, EntityDataTypes.INT, score));
metadata.add(new EntityData(17, EntityDataTypes.BYTE, skinPartsMask));
metadata.add(new EntityData(18, EntityDataTypes.BYTE, (byte) mainArm.ordinal()));
metadata.add(new EntityData(19, EntityDataTypes.NBT, leftShoulderNBT));
metadata.add(new EntityData(20, EntityDataTypes.NBT, rightShoulderNBT));
return metadata;
}
@Override
public void decode(List<EntityData> data) {
super.decode(data);
for (EntityData entityData : data) {
switch (entityData.getIndex()) {
case 15:
additionalHealth = (float) entityData.getValue();
break;
case 16:
score = (int) entityData.getValue();
break;
case 17:
skinPartsMask = (byte) entityData.getValue();
break;
case 18:
mainArm = HumanoidArm.VALUES[(byte) entityData.getValue()];
break;
case 19:
leftShoulderNBT = (NBTCompound) entityData.getValue();
break;
case 20:
rightShoulderNBT = (NBTCompound) entityData.getValue();
break;
}
}
}
public static class PlayerBuilder<T extends PlayerBuilder> extends LivingEntityDataProvider.LivingEntityBuilder<T> {
public PlayerBuilder(PlayerDataProvider entityDataProvider) {
super(entityDataProvider);
}
public T additionalHealth(float additionalHealth) {
((PlayerDataProvider)provider).setAdditionalHealth(additionalHealth);
return (T) this;
}
public T score(int score) {
((PlayerDataProvider)provider).setScore(score);
return (T) this;
}
public T skinPartsMask(byte skinPartsMask) {
((PlayerDataProvider)provider).setSkinPartsMask(skinPartsMask);
return (T)this;
}
public T skinParts(SkinSection skinSections) {
((PlayerDataProvider)provider).setSkinPartsMask(skinSections.getMask());
return (T)this;
}
public T mainArm(HumanoidArm mainArm) {
((PlayerDataProvider)provider).setMainArm(mainArm);
return (T)this;
}
public T leftShoulderNBT(NBTCompound leftShoulderNBT) {
((PlayerDataProvider)provider).setLeftShoulderNBT(leftShoulderNBT);
return (T)this;
}
public T rightShoulderNBT(NBTCompound rightShoulderNBT) {
((PlayerDataProvider)provider).setRightShoulderNBT(rightShoulderNBT);
return (T)this;
}
}
}
@@ -31,6 +31,7 @@ public enum EntityPose {
DYING,
CROAKING,
USING_TONGUE,
SITTING,
ROARING,
SNIFFING,
EMERGING,
@@ -40,6 +41,9 @@ public enum EntityPose {
if (this == DYING && version.isOlderThan(ClientVersion.V_1_17)) {
return 6;
}
if (this.ordinal() >= 11 && version.isOlderThan(ClientVersion.V_1_19_3)) {
return this.ordinal() - 1;
}
return ordinal();
}
@@ -48,6 +52,10 @@ public enum EntityPose {
if (id == 6 && version.isOlderThan(ClientVersion.V_1_17)) {
return DYING;
}
// The SITTING pose was added in 1.19.3, shifting Warden's poses by 1
if (id >= 10 && version.isOlderThan(ClientVersion.V_1_19_3)) {
id++;
}
return values()[id];
}
}
@@ -16,13 +16,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.protocol.entity.data.provider;
package com.github.retrooper.packetevents.protocol.entity.sniffer;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import java.util.List;
public interface DataProvider {
List<EntityData> encode();
void decode(List<EntityData> data);
public enum SnifferState {
IDLING,
FEELING_HAPPY,
SCENTING,
SNIFFING,
SEARCHING,
DIGGING,
RISING
}
@@ -0,0 +1,91 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 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.transform;
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
import com.github.retrooper.packetevents.protocol.player.UserProfile;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
public class EntityTransformType {
public static final EntityTransformType IDENTITY = new EntityTransformType(null, 1.0F, null);
private @Nullable TypeModifier typeModifier;
private float scale;
private @Nullable UserProfile playerSkin;
//Scale must be between 0.1F and 16.0F
public EntityTransformType(@Nullable TypeModifier typeModifier, float scale, @Nullable UserProfile playerSkin) {
this.typeModifier = typeModifier;
this.scale = scale;
this.playerSkin = playerSkin;
}
public Optional<TypeModifier> getTypeModifier() {
return Optional.ofNullable(typeModifier);
}
public void setTypeModifier(@Nullable TypeModifier typeModifier) {
this.typeModifier = typeModifier;
}
public float getScale() {
return scale;
}
public void setScale(float scale) {
this.scale = scale;
}
public Optional<UserProfile> getPlayerSkin() {
return Optional.ofNullable(playerSkin);
}
public void setPlayerSkin(@Nullable UserProfile playerSkin) {
this.playerSkin = playerSkin;
}
public static class TypeModifier {
private EntityType entityType;
private @Nullable NBTCompound tag;
public TypeModifier(EntityType entityType, @Nullable NBTCompound tag) {
this.entityType = entityType;
this.tag = tag;
}
public EntityType getEntityType() {
return entityType;
}
public void setEntityType(EntityType entityType) {
this.entityType = entityType;
}
public Optional<NBTCompound> getTag() {
return Optional.ofNullable(tag);
}
public void setTag(@Nullable NBTCompound tag) {
this.tag = tag;
}
}
}
@@ -43,7 +43,9 @@ public class EntityTypes {
ClientVersion.V_1_16,
ClientVersion.V_1_16_2,
ClientVersion.V_1_17,
ClientVersion.V_1_19);
ClientVersion.V_1_19,
ClientVersion.V_1_19_3,
ClientVersion.V_1_19_4);
private static final TypesBuilder LEGACY_TYPES_BUILDER = new TypesBuilder("entity/legacy_entity_type_mappings",
ClientVersion.V_1_8,
ClientVersion.V_1_9,
@@ -178,6 +180,7 @@ public class EntityTypes {
public static final EntityType BOAT = define("boat", ENTITY);
public static final EntityType CHEST_BOAT = define("chest_boat", BOAT);
public static final EntityType CAT = define("cat", ABSTRACT_TAMEABLE_ANIMAL);
public static final EntityType CAMEL = define("camel", ABSTRACT_HORSE);
public static final EntityType SPIDER = define("spider", ABSTRACT_MONSTER);
public static final EntityType CAVE_SPIDER = define("cave_spider", SPIDER);
public static final EntityType CHICKEN = define("chicken", ABSTRACT_ANIMAL);
@@ -298,4 +301,11 @@ public class EntityTypes {
public static final EntityType MINECART_TNT = define("minecart_tnt", MINECART_ABSTRACT);
public static final EntityType MINECART_HOPPER = define("minecart_hopper", MINECART_ABSTRACT);
public static final EntityType MINECART_MOB_SPAWNER = define("minecart_mob_spawner", MINECART_ABSTRACT);
// Display type entities added in 1.19.4
public static final EntityType DISPLAY = define("display", ENTITY);
public static final EntityType BLOCK_DISPLAY = define("block_display", DISPLAY);
public static final EntityType ITEM_DISPLAY = define("item_display", DISPLAY);
public static final EntityType TEXT_DISPLAY = define("text_display", DISPLAY);
public static final EntityType INTERACTION = define("interaction", DISPLAY);
public static final EntityType SNIFFER = define("sniffer", ABSTRACT_ANIMAL);
}
@@ -125,7 +125,7 @@ public class ItemStack {
}
public ItemStack copy() {
return cachedIsEmpty ? EMPTY : new ItemStack(type, amount, nbt == null ? new NBTCompound() : nbt.copy(), legacyData);
return cachedIsEmpty ? EMPTY : new ItemStack(type, amount, nbt == null ? null : nbt.copy(), legacyData);
}
@Nullable
@@ -258,7 +258,16 @@ public class ItemStack {
}
public static boolean tagMatches(ItemStack left, ItemStack right) {
return left.isEmpty() && right.isEmpty() || (!left.isEmpty() && !right.isEmpty() && ((left.nbt != null || right.nbt == null) && (left.nbt == null || left.nbt.equals(right.nbt))));
if (left == right) {
return true;
}
if (left == null) {
return right.isEmpty();
}
if (right == null) {
return left.isEmpty();
}
return Objects.equals(left.nbt, right.nbt);
}
@Override
@@ -44,7 +44,10 @@ public class ItemTypes {
ClientVersion.V_1_16_2,
ClientVersion.V_1_17,
ClientVersion.V_1_18,
ClientVersion.V_1_19);
ClientVersion.V_1_19,
ClientVersion.V_1_19_3,
ClientVersion.V_1_19_4,
ClientVersion.V_1_20);
public static final ItemType GILDED_BLACKSTONE = builder("gilded_blackstone").setMaxAmount(64).setPlacedType(StateTypes.GILDED_BLACKSTONE).build();
public static final ItemType NETHER_BRICK_SLAB = builder("nether_brick_slab").setMaxAmount(64).setPlacedType(StateTypes.NETHER_BRICK_SLAB).build();
@@ -1198,6 +1201,115 @@ public class ItemTypes {
public static final ItemType DARK_OAK_CHEST_BOAT = builder("dark_oak_chest_boat").setMaxAmount(1).build();
public static final ItemType MANGROVE_BOAT = builder("mangrove_boat").setMaxAmount(1).build();
public static final ItemType MANGROVE_CHEST_BOAT = builder("mangrove_chest_boat").setMaxAmount(1).build();
public static ItemType CHERRY_PLANKS = builder("CHERRY_PLANKS").setMaxAmount(64).setPlacedType(StateTypes.CHERRY_PLANKS).build();
public static ItemType BAMBOO_PLANKS = builder("BAMBOO_PLANKS").setMaxAmount(64).setPlacedType(StateTypes.BAMBOO_PLANKS).build();
public static ItemType BAMBOO_MOSAIC = builder("BAMBOO_MOSAIC").setMaxAmount(64).setPlacedType(StateTypes.BAMBOO_MOSAIC).build();
public static ItemType CHERRY_SAPLING = builder("CHERRY_SAPLING").setMaxAmount(64).setPlacedType(StateTypes.CHERRY_SAPLING).build();
public static ItemType SUSPICIOUS_SAND = builder("SUSPICIOUS_SAND").setMaxAmount(64).setPlacedType(StateTypes.SUSPICIOUS_SAND).build();
public static ItemType CHERRY_LOG = builder("CHERRY_LOG").setMaxAmount(64).setPlacedType(StateTypes.CHERRY_LOG).build();
public static ItemType BAMBOO_BLOCK = builder("BAMBOO_BLOCK").setMaxAmount(64).setPlacedType(StateTypes.BAMBOO_BLOCK).build();
public static ItemType STRIPPED_CHERRY_LOG = builder("STRIPPED_CHERRY_LOG").setMaxAmount(64).setPlacedType(StateTypes.STRIPPED_CHERRY_LOG).build();
public static ItemType STRIPPED_CHERRY_WOOD = builder("STRIPPED_CHERRY_WOOD").setMaxAmount(64).setPlacedType(StateTypes.STRIPPED_CHERRY_WOOD).build();
public static ItemType STRIPPED_BAMBOO_BLOCK = builder("STRIPPED_BAMBOO_BLOCK").setMaxAmount(64).setPlacedType(StateTypes.STRIPPED_BAMBOO_BLOCK).build();
public static ItemType CHERRY_WOOD = builder("CHERRY_WOOD").setMaxAmount(64).setPlacedType(StateTypes.CHERRY_WOOD).build();
public static ItemType CHERRY_LEAVES = builder("CHERRY_LEAVES").setMaxAmount(64).setPlacedType(StateTypes.CHERRY_LEAVES).build();
public static ItemType TORCHFLOWER = builder("TORCHFLOWER").setMaxAmount(64).setPlacedType(StateTypes.TORCHFLOWER).build();
public static ItemType PINK_PETALS = builder("PINK_PETALS").setMaxAmount(64).setPlacedType(StateTypes.PINK_PETALS).build();
public static ItemType CHERRY_SLAB = builder("CHERRY_SLAB").setMaxAmount(64).setPlacedType(StateTypes.CHERRY_SLAB).build();
public static ItemType BAMBOO_SLAB = builder("BAMBOO_SLAB").setMaxAmount(64).setPlacedType(StateTypes.BAMBOO_SLAB).build();
public static ItemType BAMBOO_MOSAIC_SLAB = builder("BAMBOO_MOSAIC_SLAB").setMaxAmount(64).setPlacedType(StateTypes.BAMBOO_MOSAIC_SLAB).build();
public static ItemType CHISELED_BOOKSHELF = builder("CHISELED_BOOKSHELF").setMaxAmount(64).setPlacedType(StateTypes.CHISELED_BOOKSHELF).build();
public static ItemType DECORATED_POT = builder("DECORATED_POT").setMaxAmount(1).setPlacedType(StateTypes.DECORATED_POT).build();
public static ItemType CHERRY_FENCE = builder("CHERRY_FENCE").setMaxAmount(64).setPlacedType(StateTypes.CHERRY_FENCE).build();
public static ItemType BAMBOO_FENCE = builder("BAMBOO_FENCE").setMaxAmount(64).setPlacedType(StateTypes.BAMBOO_FENCE).build();
public static ItemType CHERRY_STAIRS = builder("CHERRY_STAIRS").setMaxAmount(64).setPlacedType(StateTypes.CHERRY_STAIRS).build();
public static ItemType MANGROVE_STAIRS = builder("MANGROVE_STAIRS").setMaxAmount(64).setPlacedType(StateTypes.MANGROVE_STAIRS).build();
public static ItemType BAMBOO_STAIRS = builder("BAMBOO_STAIRS").setMaxAmount(64).setPlacedType(StateTypes.BAMBOO_STAIRS).build();
public static ItemType BAMBOO_MOSAIC_STAIRS = builder("BAMBOO_MOSAIC_STAIRS").setMaxAmount(64).setPlacedType(StateTypes.BAMBOO_MOSAIC_STAIRS).build();
public static ItemType CHERRY_BUTTON = builder("CHERRY_BUTTON").setMaxAmount(64).setPlacedType(StateTypes.CHERRY_BUTTON).build();
public static ItemType BAMBOO_BUTTON = builder("BAMBOO_BUTTON").setMaxAmount(64).setPlacedType(StateTypes.BAMBOO_BUTTON).build();
public static ItemType CHERRY_PRESSURE_PLATE = builder("CHERRY_PRESSURE_PLATE").setMaxAmount(64).setPlacedType(StateTypes.CHERRY_PRESSURE_PLATE).build();
public static ItemType BAMBOO_PRESSURE_PLATE = builder("BAMBOO_PRESSURE_PLATE").setMaxAmount(64).setPlacedType(StateTypes.BAMBOO_PRESSURE_PLATE).build();
public static ItemType CHERRY_DOOR = builder("CHERRY_DOOR").setMaxAmount(64).setPlacedType(StateTypes.CHERRY_DOOR).build();
public static ItemType BAMBOO_DOOR = builder("BAMBOO_DOOR").setMaxAmount(64).setPlacedType(StateTypes.BAMBOO_DOOR).build();
public static ItemType CHERRY_TRAPDOOR = builder("CHERRY_TRAPDOOR").setMaxAmount(64).setPlacedType(StateTypes.CHERRY_TRAPDOOR).build();
public static ItemType BAMBOO_TRAPDOOR = builder("BAMBOO_TRAPDOOR").setMaxAmount(64).setPlacedType(StateTypes.BAMBOO_TRAPDOOR).build();
public static ItemType CHERRY_FENCE_GATE = builder("CHERRY_FENCE_GATE").setMaxAmount(64).setPlacedType(StateTypes.CHERRY_FENCE_GATE).build();
public static ItemType BAMBOO_FENCE_GATE = builder("BAMBOO_FENCE_GATE").setMaxAmount(64).setPlacedType(StateTypes.BAMBOO_FENCE_GATE).build();
public static ItemType CHERRY_BOAT = builder("CHERRY_BOAT").setMaxAmount(1).build();
public static ItemType CHERRY_CHEST_BOAT = builder("CHERRY_CHEST_BOAT").setMaxAmount(1).build();
public static ItemType BAMBOO_RAFT = builder("BAMBOO_RAFT").setMaxAmount(1).build();
public static ItemType BAMBOO_CHEST_RAFT = builder("BAMBOO_CHEST_RAFT").setMaxAmount(1).build();
public static ItemType CHERRY_SIGN = builder("CHERRY_SIGN").setMaxAmount(16).setPlacedType(StateTypes.CHERRY_SIGN).build();
public static ItemType BAMBOO_SIGN = builder("BAMBOO_SIGN").setMaxAmount(16).setPlacedType(StateTypes.BAMBOO_SIGN).build();
public static ItemType OAK_HANGING_SIGN = builder("OAK_HANGING_SIGN").setMaxAmount(16).setPlacedType(StateTypes.OAK_HANGING_SIGN).build();
public static ItemType SPRUCE_HANGING_SIGN = builder("SPRUCE_HANGING_SIGN").setMaxAmount(16).setPlacedType(StateTypes.SPRUCE_HANGING_SIGN).build();
public static ItemType BIRCH_HANGING_SIGN = builder("BIRCH_HANGING_SIGN").setMaxAmount(16).setPlacedType(StateTypes.BIRCH_HANGING_SIGN).build();
public static ItemType JUNGLE_HANGING_SIGN = builder("JUNGLE_HANGING_SIGN").setMaxAmount(16).setPlacedType(StateTypes.JUNGLE_HANGING_SIGN).build();
public static ItemType ACACIA_HANGING_SIGN = builder("ACACIA_HANGING_SIGN").setMaxAmount(16).setPlacedType(StateTypes.ACACIA_HANGING_SIGN).build();
public static ItemType CHERRY_HANGING_SIGN = builder("CHERRY_HANGING_SIGN").setMaxAmount(16).setPlacedType(StateTypes.CHERRY_HANGING_SIGN).build();
public static ItemType DARK_OAK_HANGING_SIGN = builder("DARK_OAK_HANGING_SIGN").setMaxAmount(16).setPlacedType(StateTypes.DARK_OAK_HANGING_SIGN).build();
public static ItemType MANGROVE_HANGING_SIGN = builder("MANGROVE_HANGING_SIGN").setMaxAmount(16).setPlacedType(StateTypes.MANGROVE_HANGING_SIGN).build();
public static ItemType BAMBOO_HANGING_SIGN = builder("BAMBOO_HANGING_SIGN").setMaxAmount(16).setPlacedType(StateTypes.BAMBOO_HANGING_SIGN).build();
public static ItemType CRIMSON_HANGING_SIGN = builder("CRIMSON_HANGING_SIGN").setMaxAmount(16).setPlacedType(StateTypes.CRIMSON_HANGING_SIGN).build();
public static ItemType WARPED_HANGING_SIGN = builder("WARPED_HANGING_SIGN").setMaxAmount(16).setPlacedType(StateTypes.WARPED_HANGING_SIGN).build();
public static ItemType CAMEL_SPAWN_EGG = builder("CAMEL_SPAWN_EGG").setMaxAmount(64).build();
public static ItemType ENDER_DRAGON_SPAWN_EGG = builder("ENDER_DRAGON_SPAWN_EGG").setMaxAmount(64).build();
public static ItemType IRON_GOLEM_SPAWN_EGG = builder("IRON_GOLEM_SPAWN_EGG").setMaxAmount(64).build();
public static ItemType SNIFFER_SPAWN_EGG = builder("SNIFFER_SPAWN_EGG").setMaxAmount(64).build();
public static ItemType SNOW_GOLEM_SPAWN_EGG = builder("SNOW_GOLEM_SPAWN_EGG").setMaxAmount(64).build();
public static ItemType WITHER_SPAWN_EGG = builder("WITHER_SPAWN_EGG").setMaxAmount(64).build();
public static ItemType PIGLIN_HEAD = builder("PIGLIN_HEAD").setMaxAmount(64).setPlacedType(StateTypes.PIGLIN_HEAD).build();
public static ItemType TORCHFLOWER_SEEDS = builder("TORCHFLOWER_SEEDS").setMaxAmount(64).build();
public static ItemType BRUSH = builder("BRUSH").setMaxAmount(1).build();
public static ItemType NETHERITE_UPGRADE_SMITHING_TEMPLATE = builder("NETHERITE_UPGRADE_SMITHING_TEMPLATE").setMaxAmount(64).build();
public static ItemType SENTRY_ARMOR_TRIM_SMITHING_TEMPLATE = builder("SENTRY_ARMOR_TRIM_SMITHING_TEMPLATE").setMaxAmount(64).build();
public static ItemType DUNE_ARMOR_TRIM_SMITHING_TEMPLATE = builder("DUNE_ARMOR_TRIM_SMITHING_TEMPLATE").setMaxAmount(64).build();
public static ItemType COAST_ARMOR_TRIM_SMITHING_TEMPLATE = builder("COAST_ARMOR_TRIM_SMITHING_TEMPLATE").setMaxAmount(64).build();
public static ItemType WILD_ARMOR_TRIM_SMITHING_TEMPLATE = builder("WILD_ARMOR_TRIM_SMITHING_TEMPLATE").setMaxAmount(64).build();
public static ItemType WARD_ARMOR_TRIM_SMITHING_TEMPLATE = builder("WARD_ARMOR_TRIM_SMITHING_TEMPLATE").setMaxAmount(64).build();
public static ItemType EYE_ARMOR_TRIM_SMITHING_TEMPLATE = builder("EYE_ARMOR_TRIM_SMITHING_TEMPLATE").setMaxAmount(64).build();
public static ItemType VEX_ARMOR_TRIM_SMITHING_TEMPLATE = builder("VEX_ARMOR_TRIM_SMITHING_TEMPLATE").setMaxAmount(64).build();
public static ItemType TIDE_ARMOR_TRIM_SMITHING_TEMPLATE = builder("TIDE_ARMOR_TRIM_SMITHING_TEMPLATE").setMaxAmount(64).build();
public static ItemType SNOUT_ARMOR_TRIM_SMITHING_TEMPLATE = builder("SNOUT_ARMOR_TRIM_SMITHING_TEMPLATE").setMaxAmount(64).build();
public static ItemType RIB_ARMOR_TRIM_SMITHING_TEMPLATE = builder("RIB_ARMOR_TRIM_SMITHING_TEMPLATE").setMaxAmount(64).build();
public static ItemType SPIRE_ARMOR_TRIM_SMITHING_TEMPLATE = builder("SPIRE_ARMOR_TRIM_SMITHING_TEMPLATE").setMaxAmount(64).build();
public static ItemType POTTERY_SHARD_ARCHER = builder("POTTERY_SHARD_ARCHER").setMaxAmount(64).build();
public static ItemType POTTERY_SHARD_PRIZE = builder("POTTERY_SHARD_PRIZE").setMaxAmount(64).build();
public static ItemType POTTERY_SHARD_ARMS_UP = builder("POTTERY_SHARD_ARMS_UP").setMaxAmount(64).build();
public static ItemType POTTERY_SHARD_SKULL = builder("POTTERY_SHARD_SKULL").setMaxAmount(64).build();
//1.20 items
public static ItemType SUSPICIOUS_GRAVEL = builder("SUSPICIOUS_GRAVEL").setMaxAmount(64).build();
public static ItemType PITCHER_PLANT = builder("PITCHER_PLANT").setMaxAmount(64).build();
public static ItemType SNIFFER_EGG = builder("SNIFFER_EGG").setMaxAmount(64).build();
public static ItemType CALIBRATED_SCULK_SENSOR = builder("CALIBRATED_SCULK_SENSOR").setMaxAmount(64).build();
public static ItemType PITCHER_POD = builder("PITCHER_POD").setMaxAmount(64).build();
public static ItemType MUSIC_DISC_RELIC = builder("MUSIC_DISC_RELIC").setMaxAmount(1).setAttributes(ItemAttribute.MUSIC_DISC).build();
public static ItemType WAYFINDER_ARMOR_TRIM_SMITHING_TEMPLATE = builder("WAYFINDER_ARMOR_TRIM_SMITHING_TEMPLATE").setMaxAmount(64).build();
public static ItemType SHAPER_ARMOR_TRIM_SMITHING_TEMPLATE = builder("SHAPER_ARMOR_TRIM_SMITHING_TEMPLATE").setMaxAmount(64).build();
public static ItemType SILENCE_ARMOR_TRIM_SMITHING_TEMPLATE = builder("SILENCE_ARMOR_TRIM_SMITHING_TEMPLATE").setMaxAmount(64).build();
public static ItemType RAISER_ARMOR_TRIM_SMITHING_TEMPLATE = builder("RAISER_ARMOR_TRIM_SMITHING_TEMPLATE").setMaxAmount(64).build();
public static ItemType HOST_ARMOR_TRIM_SMITHING_TEMPLATE = builder("HOST_ARMOR_TRIM_SMITHING_TEMPLATE").setMaxAmount(64).build();
public static ItemType ANGLER_POTTERY_SHERD = builder("ANGLER_POTTERY_SHERD").setMaxAmount(64).build();
public static ItemType ARCHER_POTTERY_SHERD = builder("ARCHER_POTTERY_SHERD").setMaxAmount(64).build();
public static ItemType ARMS_UP_POTTERY_SHERD = builder("ARMS_UP_POTTERY_SHERD").setMaxAmount(64).build();
public static ItemType BLADE_POTTERY_SHERD = builder("BLADE_POTTERY_SHERD").setMaxAmount(64).build();
public static ItemType BREWER_POTTERY_SHERD = builder("BREWER_POTTERY_SHERD").setMaxAmount(64).build();
public static ItemType BURN_POTTERY_SHERD = builder("BURN_POTTERY_SHERD").setMaxAmount(64).build();
public static ItemType DANGER_POTTERY_SHERD = builder("DANGER_POTTERY_SHERD").setMaxAmount(64).build();
public static ItemType EXPLORER_POTTERY_SHERD = builder("EXPLORER_POTTERY_SHERD").setMaxAmount(64).build();
public static ItemType FRIEND_POTTERY_SHERD = builder("FRIEND_POTTERY_SHERD").setMaxAmount(64).build();
public static ItemType HEART_POTTERY_SHERD = builder("HEART_POTTERY_SHERD").setMaxAmount(64).build();
public static ItemType HEARTBREAK_POTTERY_SHERD = builder("HEARTBREAK_POTTERY_SHERD").setMaxAmount(64).build();
public static ItemType HOWL_POTTERY_SHERD = builder("HOWL_POTTERY_SHERD").setMaxAmount(64).build();
public static ItemType MINER_POTTERY_SHERD = builder("MINER_POTTERY_SHERD").setMaxAmount(64).build();
public static ItemType MOURNER_POTTERY_SHERD = builder("MOURNER_POTTERY_SHERD").setMaxAmount(64).build();
public static ItemType PLENTY_POTTERY_SHERD = builder("PLENTY_POTTERY_SHERD").setMaxAmount(64).build();
public static ItemType PRIZE_POTTERY_SHERD = builder("PRIZE_POTTERY_SHERD").setMaxAmount(64).build();
public static ItemType SHEAF_POTTERY_SHERD = builder("SHEAF_POTTERY_SHERD").setMaxAmount(64).build();
public static ItemType SHELTER_POTTERY_SHERD = builder("SHELTER_POTTERY_SHERD").setMaxAmount(64).build();
public static ItemType SKULL_POTTERY_SHERD = builder("SKULL_POTTERY_SHERD").setMaxAmount(64).build();
public static ItemType SNORT_POTTERY_SHERD = builder("SNORT_POTTERY_SHERD").setMaxAmount(64).build();
/**
* @deprecated Burning furnace shows up as a missing texture, removed in 1.9
*/
@@ -1221,7 +1333,7 @@ public class ItemTypes {
}
public static Builder builder(String key) {
return new Builder(key);
return new Builder(key.toLowerCase());
}
public static ItemType define(int maxAmount, String key, ItemType craftRemainder, StateType placedType, int maxDurability, List<ItemAttribute> attributesArr) {
@@ -33,6 +33,7 @@ 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;
@@ -130,6 +131,16 @@ public class NBTCodec {
else if (nbt instanceof NBTEnd) {
throw new IllegalStateException("Encountered the NBTEnd tag during the NBT to JSON conversion: " + nbt.toString());
}
else if (nbt instanceof NBTCompound) {
JsonObject jsonObject = new JsonObject();
Map<String, NBT> compoundTags = ((NBTCompound)nbt).getTags();
for (String tagName : compoundTags.keySet()) {
NBT tag = compoundTags.get(tagName);
JsonElement jsonValue = nbtToJson(tag, parseByteAsBool);
jsonObject.add(tagName, jsonValue);
}
return jsonObject;
}
else {
throw new IllegalStateException("Failed to convert NBT to JSON.");
}
@@ -139,8 +150,9 @@ public class NBTCodec {
public static NBTCompound readNBTFromBuffer(Object byteBuf, ServerVersion serverVersion) {
if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_8)) {
try {
boolean named = serverVersion.isOlderThan(ServerVersion.V_1_20_2);
return (NBTCompound) DefaultNBTSerializer.INSTANCE.deserializeTag(
new ByteBufInputStream(byteBuf));
new ByteBufInputStream(byteBuf), named);
} catch (IOException e) {
e.printStackTrace();
}
@@ -168,7 +180,8 @@ public class NBTCodec {
if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_8)) {
try (ByteBufOutputStream outputStream = new ByteBufOutputStream(byteBuf)) {
if (tag != null) {
DefaultNBTSerializer.INSTANCE.serializeTag(outputStream, tag);
boolean named = serverVersion.isOlderThan(ServerVersion.V_1_20_2);
DefaultNBTSerializer.INSTANCE.serializeTag(outputStream, tag, named);
} else {
DefaultNBTSerializer.INSTANCE.serializeTag(outputStream, NBTEnd.INSTANCE);
}
@@ -47,21 +47,33 @@ public class NBTSerializer<IN, OUT> {
}
public NBT deserializeTag(IN from) throws IOException {
return deserializeTag(from, true);
}
public NBT deserializeTag(IN from, boolean named) throws IOException {
NBTType<?> type = readTagType(from);
if (type == NBTType.END) {
return null;
}
readTagName(from);
if (named) {
readTagName(from);
}
return readTag(from, type);
}
public void serializeTag(OUT to, NBT tag) throws IOException {
serializeTag(to, tag, true);
}
public void serializeTag(OUT to, NBT tag, boolean named) throws IOException {
NBTType<?> type = tag.getType();
writeTagType(to, type);
if (tag.getType() == NBTType.END) {
return;
}
writeTagName(to, "");
if (named) {
writeTagName(to, "");
}
writeTag(to, tag);
}
@@ -23,6 +23,7 @@ import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.item.ItemStack;
import com.github.retrooper.packetevents.protocol.player.*;
import com.github.retrooper.packetevents.protocol.world.Location;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import com.github.retrooper.packetevents.wrapper.play.server.*;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
@@ -33,6 +34,7 @@ import java.util.*;
public class NPC {
private final int id;
private final UserProfile profile;
private GameMode gamemode;
private Component tabName;
private NamedTextColor nameColor;
private Component prefixName;
@@ -47,10 +49,11 @@ public class NPC {
private ItemStack boots = null;
private final Set<Object> channels = new HashSet<>();
public NPC(UserProfile profile, int entityId, @Nullable Component tabName, @Nullable NamedTextColor nameColor,
public NPC(UserProfile profile, int entityId, GameMode gamemode, @Nullable Component tabName, @Nullable NamedTextColor nameColor,
@Nullable Component prefixName, @Nullable Component suffixName) {
this.profile = profile;
this.id = entityId;
this.gamemode = gamemode;
this.tabName = tabName;
this.nameColor = nameColor;
@@ -59,7 +62,7 @@ public class NPC {
}
public NPC(UserProfile profile, int entityId, @Nullable Component tabName) {
this(profile, entityId, tabName, null, null, null);
this(profile, entityId, GameMode.SURVIVAL, tabName, null, null, null);
}
public NPC(UserProfile profile, int entityId) {
@@ -72,9 +75,15 @@ public class NPC {
public void spawn(Object channel) {
if (hasSpawned(channel)) return;
WrapperPlayServerPlayerInfo playerInfoPacket =
new WrapperPlayServerPlayerInfo(WrapperPlayServerPlayerInfo.Action.ADD_PLAYER, getPlayerInfoData());
PacketEvents.getAPI().getProtocolManager().sendPacket(channel, playerInfoPacket);
PacketWrapper<?> playerInfo;
if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_19_3)) {
playerInfo = new WrapperPlayServerPlayerInfoUpdate(WrapperPlayServerPlayerInfoUpdate.Action.ADD_PLAYER,
getModernPlayerInfoData());
}
else {
playerInfo = new WrapperPlayServerPlayerInfo(WrapperPlayServerPlayerInfo.Action.ADD_PLAYER, getLegacyPlayerInfoData());
}
PacketEvents.getAPI().getProtocolManager().sendPacket(channel, playerInfo);
//TODO Later if we want entity metadata, its not supported on newer server versions though(confirm if its mandatory on older versions)
WrapperPlayServerSpawnPlayer spawnPlayer = new WrapperPlayServerSpawnPlayer(getId(),
@@ -181,16 +190,44 @@ public class NPC {
public void updateTabPing(int ping) {
setDisplayPing(ping);
for (Object channel : channels) {
WrapperPlayServerPlayerInfo playerInfo =
new WrapperPlayServerPlayerInfo(WrapperPlayServerPlayerInfo.Action.UPDATE_LATENCY, getPlayerInfoData());
PacketWrapper<?> playerInfo;
if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_19_3)) {
playerInfo = new WrapperPlayServerPlayerInfoUpdate(WrapperPlayServerPlayerInfoUpdate.Action.UPDATE_LATENCY, getModernPlayerInfoData());
}
else {
playerInfo =
new WrapperPlayServerPlayerInfo(WrapperPlayServerPlayerInfo.Action.UPDATE_LATENCY, getLegacyPlayerInfoData());
}
PacketEvents.getAPI().getProtocolManager().sendPacket(channel, playerInfo);
}
}
public void updateGameMode(GameMode gamemode) {
setGameMode(gamemode);
for (Object channel : channels) {
PacketWrapper<?> playerInfo;
if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_19_3)) {
playerInfo = new WrapperPlayServerPlayerInfoUpdate(WrapperPlayServerPlayerInfoUpdate.Action.UPDATE_GAME_MODE,
getModernPlayerInfoData());
}
else {
playerInfo =
new WrapperPlayServerPlayerInfo(WrapperPlayServerPlayerInfo.Action.UPDATE_GAME_MODE, getLegacyPlayerInfoData());
}
PacketEvents.getAPI().getProtocolManager().sendPacket(channel, playerInfo);
}
}
public void changeSkin(UUID skinUUID, List<TextureProperty> skinTextureProperties) {
for (Object channel : channels) {
WrapperPlayServerPlayerInfo playerInfoRemove =
new WrapperPlayServerPlayerInfo(WrapperPlayServerPlayerInfo.Action.REMOVE_PLAYER, getPlayerInfoData());
PacketWrapper<?> playerInfoRemove;
if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_19_3)) {
playerInfoRemove = new WrapperPlayServerPlayerInfoRemove(getProfile().getUUID());
}
else {
playerInfoRemove =
new WrapperPlayServerPlayerInfo(WrapperPlayServerPlayerInfo.Action.REMOVE_PLAYER, getLegacyPlayerInfoData());
}
PacketEvents.getAPI().getProtocolManager().sendPacket(channel, playerInfoRemove);
WrapperPlayServerDestroyEntities destroyEntities =
@@ -199,8 +236,15 @@ public class NPC {
getProfile().setTextureProperties(skinTextureProperties);
getProfile().setUUID(skinUUID);
WrapperPlayServerPlayerInfo playerInfoAdd =
new WrapperPlayServerPlayerInfo(WrapperPlayServerPlayerInfo.Action.ADD_PLAYER, getPlayerInfoData());
PacketWrapper<?> playerInfoAdd;
if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_19_3)) {
playerInfoAdd = new WrapperPlayServerPlayerInfoUpdate(WrapperPlayServerPlayerInfoUpdate.Action.ADD_PLAYER,
getModernPlayerInfoData());
}
else {
playerInfoAdd =
new WrapperPlayServerPlayerInfo(WrapperPlayServerPlayerInfo.Action.ADD_PLAYER, getLegacyPlayerInfoData());
}
PacketEvents.getAPI().getProtocolManager().sendPacket(channel, playerInfoAdd);
WrapperPlayServerSpawnPlayer spawnPlayer =
@@ -209,7 +253,7 @@ public class NPC {
}
}
public void updateNameTag(NPC npc) {
public void updateNameTag() {
for (Object channel : channels) {
//Destroy team
WrapperPlayServerTeams removeTeam =
@@ -218,8 +262,8 @@ public class NPC {
Optional.empty());
PacketEvents.getAPI().getProtocolManager().sendPacket(channel, removeTeam);
if (npc.getNameColor() != null || npc.getPrefixName() != null
|| npc.getSuffixName() != null) {
if (this.getNameColor() != null || this.getPrefixName() != null
|| this.getSuffixName() != null) {
PacketEvents.getAPI().getProtocolManager().sendPacket(channel, generateTeamsData());
}
}
@@ -367,6 +411,14 @@ public class NPC {
return profile;
}
public GameMode getGameMode() {
return gamemode;
}
public void setGameMode(GameMode gamemode) {
this.gamemode = gamemode;
}
private WrapperPlayServerTeams generateTeamsData() {
return new WrapperPlayServerTeams("custom_name_team",
WrapperPlayServerTeams.TeamMode.CREATE,
@@ -383,12 +435,17 @@ public class NPC {
getProfile().getName());
}
public WrapperPlayServerPlayerInfo.PlayerData getPlayerInfoData() {
public WrapperPlayServerPlayerInfo.PlayerData getLegacyPlayerInfoData() {
return new WrapperPlayServerPlayerInfo.PlayerData(getTabName(),
getProfile(), GameMode.SURVIVAL,
getProfile(), getGameMode(),
getDisplayPing());
}
public WrapperPlayServerPlayerInfoUpdate.PlayerInfo getModernPlayerInfoData() {
return new WrapperPlayServerPlayerInfoUpdate.PlayerInfo(getProfile(), true,
getDisplayPing(), getGameMode(), getTabName(), null);
}
public int getDisplayPing() {
return displayPing;
}
@@ -404,4 +461,8 @@ public class NPC {
public void setLocation(Location location) {
this.location = location;
}
public Set<Object> getChannels() {
return channels;
}
}
@@ -0,0 +1,9 @@
package com.github.retrooper.packetevents.protocol.packettype;
/**
* A Marker interface used to indicate that this packet is originating on
* the server, and is bound for the client.
*/
public interface ClientBoundPacket {
}
@@ -50,7 +50,10 @@ public final class PacketType {
ClientVersion.V_1_17,
ClientVersion.V_1_18,
ClientVersion.V_1_19,
ClientVersion.V_1_19_1);
ClientVersion.V_1_19_1,
ClientVersion.V_1_19_3,
ClientVersion.V_1_19_4,
ClientVersion.V_1_20_2);
//TODO UPDATE Update packet type mappings (serverbound pt. 1)
private static final VersionMapper SERVERBOUND_PLAY_VERSION_MAPPER = new VersionMapper(
@@ -66,7 +69,10 @@ public final class PacketType {
ClientVersion.V_1_16_2,
ClientVersion.V_1_17,
ClientVersion.V_1_19,
ClientVersion.V_1_19_1);
ClientVersion.V_1_19_1,
ClientVersion.V_1_19_3,
ClientVersion.V_1_19_4,
ClientVersion.V_1_20_2);
public static void prepare() {
PacketType.Play.Client.load();
@@ -104,13 +110,19 @@ public final class PacketType {
} else {
return Play.Server.getById(version, packetID);
}
case CONFIGURATION:
if (side == PacketSide.CLIENT) {
return Configuration.Client.getById(packetID);
} else {
return Configuration.Server.getById(packetID);
}
default:
return null;
}
}
public static class Handshaking {
public enum Client implements PacketTypeConstant {
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.
@@ -138,9 +150,14 @@ public final class PacketType {
public int getId() {
return id;
}
@Override
public PacketSide getSide() {
return PacketSide.CLIENT;
}
}
public enum Server implements PacketTypeConstant {
public enum Server implements PacketTypeConstant, ClientBoundPacket {
LEGACY_SERVER_LIST_RESPONSE(254); //0xFE in hex
private final int id;
@@ -157,11 +174,16 @@ public final class PacketType {
public int getId() {
return id;
}
@Override
public PacketSide getSide() {
return PacketSide.SERVER;
}
}
}
public static class Status {
public enum Client implements PacketTypeConstant {
public enum Client implements PacketTypeConstant, ServerBoundPacket {
REQUEST(0),
PING(1);
@@ -185,9 +207,15 @@ public final class PacketType {
public int getId() {
return id;
}
@Override
public PacketSide getSide() {
return PacketSide.CLIENT;
}
}
public enum Server implements PacketTypeConstant {
public enum Server implements PacketTypeConstant, ClientBoundPacket {
RESPONSE(0),
PONG(1);
@@ -211,15 +239,22 @@ public final class PacketType {
public int getId() {
return id;
}
@Override
public PacketSide getSide() {
return PacketSide.SERVER;
}
}
}
public static class Login {
public enum Client implements PacketTypeConstant {
public enum Client implements PacketTypeConstant, ServerBoundPacket {
LOGIN_START(0),
ENCRYPTION_RESPONSE(1),
///Added in 1.13
LOGIN_PLUGIN_RESPONSE(2);
LOGIN_PLUGIN_RESPONSE(2),
//Added in 1.20.2
LOGIN_SUCCESS_ACK(3);
private final int id;
@@ -235,6 +270,8 @@ public final class PacketType {
return ENCRYPTION_RESPONSE;
} else if (packetID == 2) {
return LOGIN_PLUGIN_RESPONSE;
} else if (packetID == 3) {
return LOGIN_SUCCESS_ACK;
} else {
return null;
}
@@ -243,9 +280,14 @@ public final class PacketType {
public int getId() {
return id;
}
@Override
public PacketSide getSide() {
return PacketSide.CLIENT;
}
}
public enum Server implements PacketTypeConstant {
public enum Server implements PacketTypeConstant, ClientBoundPacket {
DISCONNECT(0),
ENCRYPTION_REQUEST(1),
LOGIN_SUCCESS(2),
@@ -281,11 +323,122 @@ public final class PacketType {
public int getId() {
return id;
}
@Override
public PacketSide getSide() {
return PacketSide.SERVER;
}
}
}
// Added in 1.20.2
public static class Configuration {
public enum Client implements PacketTypeConstant, ServerBoundPacket {
CLIENT_SETTINGS(0x00),
PLUGIN_MESSAGE(0x01),
CONFIGURATION_END_ACK(0x02),
KEEP_ALIVE(0x03),
PONG(0x04),
RESOURCE_PACK_STATUS(0x05);
private final int id;
Client(int id) {
this.id = id;
}
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;
}
}
@Override
public int getId() {
return this.id;
}
@Override
public PacketSide getSide() {
return PacketSide.CLIENT;
}
}
public enum Server implements PacketTypeConstant, ClientBoundPacket {
PLUGIN_MESSAGE(0x00),
DISCONNECT(0x01),
CONFIGURATION_END(0x02),
KEEP_ALIVE(0x03),
PING(0x04),
REGISTRY_DATA(0x05),
RESOURCE_PACK_SEND(0x06),
UPDATE_ENABLED_FEATURES(0x07),
UPDATE_TAGS(0x08);
private final int id;
Server(int id) {
this.id = id;
}
public static @Nullable PacketTypeCommon getById(int packetId) {
switch (packetId) {
case 0x00:
return PLUGIN_MESSAGE;
case 0x01:
return DISCONNECT;
case 0x02:
return CONFIGURATION_END;
case 0x03:
return KEEP_ALIVE;
case 0x04:
return PING;
case 0x05:
return REGISTRY_DATA;
case 0x06:
return RESOURCE_PACK_SEND;
case 0x07:
return UPDATE_ENABLED_FEATURES;
case 0x08:
return UPDATE_TAGS;
default:
return null;
}
}
@Override
public int getId() {
return this.id;
}
@Override
public PacketSide getSide() {
return PacketSide.CLIENT;
}
}
}
public static class Play {
public enum Client implements PacketTypeCommon {
public enum Client implements PacketTypeCommon, ServerBoundPacket {
//Packets that no longer exist on the latest version
CHAT_PREVIEW,
TELEPORT_CONFIRM,
QUERY_BLOCK_NBT,
SET_DIFFICULTY,
@@ -338,9 +491,14 @@ public final class PacketType {
USE_ITEM,
//Added in 1.19
CHAT_COMMAND,
CHAT_PREVIEW,
//Added in 1.19.1
CHAT_ACK;
CHAT_ACK,
//Added in 1.19.3
CHAT_SESSION_UPDATE,
//Added in 1.20.2
CHUNK_BATCH_ACK,
CONFIGURATION_ACK,
DEBUG_PING;
private static int INDEX = 0;
private static final Map<Byte, Map<Integer, PacketTypeCommon>> PACKET_TYPE_ID_MAP = new HashMap<>();
@@ -389,6 +547,9 @@ public final class PacketType {
loadPacketIds(ServerboundPacketType_1_17.values());
loadPacketIds(ServerboundPacketType_1_19.values());
loadPacketIds(ServerboundPacketType_1_19_1.values());
loadPacketIds(ServerboundPacketType_1_19_3.values());
loadPacketIds(ServerboundPacketType_1_19_4.values());
loadPacketIds(ServerboundPacketType_1_20_2.values());
//TODO UPDATE Update packet type mappings (serverbound pt. 2)
}
@@ -399,9 +560,14 @@ public final class PacketType {
int index = SERVERBOUND_PLAY_VERSION_MAPPER.getIndex(version);
return ids[index];
}
@Override
public PacketSide getSide() {
return PacketSide.CLIENT;
}
}
public enum Server implements PacketTypeCommon {
public enum Server implements PacketTypeCommon, ClientBoundPacket {
//Packets that are no longer present on latest version
SET_COMPRESSION,
MAP_CHUNK_BULK,
@@ -417,12 +583,18 @@ public final class PacketType {
SPAWN_PAINTING,
SCULK_VIBRATION_SIGNAL,
ACKNOWLEDGE_PLAYER_DIGGING,
CHAT_PREVIEW_PACKET,
NAMED_SOUND_EFFECT,
PLAYER_CHAT_HEADER,
PLAYER_INFO,
DISPLAY_CHAT_PREVIEW,
UPDATE_ENABLED_FEATURES,
SPAWN_PLAYER,
//Okay these are normal ones
WINDOW_CONFIRMATION,
SPAWN_ENTITY,
SPAWN_EXPERIENCE_ORB,
SPAWN_PLAYER,
ENTITY_ANIMATION,
STATISTICS,
BLOCK_BREAK_ANIMATION,
@@ -441,7 +613,6 @@ public final class PacketType {
SET_SLOT,
SET_COOLDOWN,
PLUGIN_MESSAGE,
NAMED_SOUND_EFFECT,
DISCONNECT,
ENTITY_STATUS,
EXPLOSION,
@@ -470,7 +641,6 @@ public final class PacketType {
END_COMBAT_EVENT,
ENTER_COMBAT_EVENT,
DEATH_COMBAT_EVENT,
PLAYER_INFO,
FACE_PLAYER,
PLAYER_POSITION_AND_LOOK,
UNLOCK_RECIPES,
@@ -523,15 +693,27 @@ public final class PacketType {
//Added in 1.19
ACKNOWLEDGE_BLOCK_CHANGES,
CHAT_PREVIEW_PACKET,
SERVER_DATA,
DISPLAY_CHAT_PREVIEW,
SYSTEM_CHAT_MESSAGE,
//Added in 1.19.1
DELETE_CHAT,
PLAYER_CHAT_HEADER,
CUSTOM_CHAT_COMPLETIONS;
CUSTOM_CHAT_COMPLETIONS,
//Added in 1.19.3
DISGUISED_CHAT,
PLAYER_INFO_REMOVE,
PLAYER_INFO_UPDATE,
//Added in 1.19.4
DAMAGE_EVENT,
HURT_ANIMATION,
BUNDLE,
CHUNK_BIOMES,
//Added in 1.20.2
CHUNK_BATCH_END,
CHUNK_BATCH_BEGIN,
DEBUG_PONG,
CONFIGURATION_START;
private static int INDEX = 0;
private static final Map<Byte, Map<Integer, PacketTypeCommon>> PACKET_TYPE_ID_MAP = new HashMap<>();
@@ -560,6 +742,11 @@ public final class PacketType {
return map.get(packetId);
}
@Override
public PacketSide getSide() {
return PacketSide.SERVER;
}
private static void loadPacketIds(Enum<?>[] enumConstants) {
int index = INDEX;
for (Enum<?> constant : enumConstants) {
@@ -591,6 +778,9 @@ public final class PacketType {
loadPacketIds(ClientboundPacketType_1_18.values());
loadPacketIds(ClientboundPacketType_1_19.values());
loadPacketIds(ClientboundPacketType_1_19_1.values());
loadPacketIds(ClientboundPacketType_1_19_3.values());
loadPacketIds(ClientboundPacketType_1_19_4.values());
loadPacketIds(ClientboundPacketType_1_20_2.values());
//TODO UPDATE Update packet type mappings (clientbound pt. 2)
}
}
@@ -18,6 +18,7 @@
package com.github.retrooper.packetevents.protocol.packettype;
import com.github.retrooper.packetevents.protocol.PacketSide;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
public interface PacketTypeCommon {
@@ -27,4 +28,6 @@ public interface PacketTypeCommon {
}
int getId(ClientVersion version);
PacketSide getSide();
}
@@ -20,7 +20,7 @@ package com.github.retrooper.packetevents.protocol.packettype;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
public interface PacketTypeConstant extends PacketTypeCommon{
public interface PacketTypeConstant extends PacketTypeCommon {
default int getId(ClientVersion version) {
return getId();
}
@@ -0,0 +1,8 @@
package com.github.retrooper.packetevents.protocol.packettype;
/**
* A Marker interface used to indicate that this packet is originating on
* the client, and is bound for the server.
*/
public interface ServerBoundPacket {
}
@@ -0,0 +1,187 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 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_19_3 {
SPAWN_ENTITY,
SPAWN_EXPERIENCE_ORB,
//Removed in 1.19
//SPAWN_LIVING_ENTITY,
//SPAWN_PAINTING,
SPAWN_PLAYER,
//Removed in 1.19
//SCULK_VIBRATION_SIGNAL,
ENTITY_ANIMATION,
STATISTICS,
//Removed in 1.19 and replaced with ACKNOWLEDGE_BLOCK_CHANGES
//ACKNOWLEDGE_PLAYER_DIGGING,
//Added in 1.19
ACKNOWLEDGE_BLOCK_CHANGES,
BLOCK_BREAK_ANIMATION,
BLOCK_ENTITY_DATA,
BLOCK_ACTION,
BLOCK_CHANGE,
BOSS_BAR,
SERVER_DIFFICULTY,
//Removed in 1.19.3
//CHAT_PREVIEW_PACKET,
CLEAR_TITLES,
TAB_COMPLETE,
DECLARE_COMMANDS,
CLOSE_WINDOW,
WINDOW_ITEMS,
WINDOW_PROPERTY,
SET_SLOT,
SET_COOLDOWN,
//Added in 1.19.1
CUSTOM_CHAT_COMPLETIONS,
PLUGIN_MESSAGE,
//Removed in 1.19.3
//NAMED_SOUND_EFFECT,
//Added in 1.19.1
DELETE_CHAT,
DISCONNECT,
//Added in 1.19.3
DISGUISED_CHAT,
ENTITY_STATUS,
EXPLOSION,
UNLOAD_CHUNK,
CHANGE_GAME_STATE,
OPEN_HORSE_WINDOW,
INITIALIZE_WORLD_BORDER,
KEEP_ALIVE,
//This is also used for lighting
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,
CRAFT_RECIPE_RESPONSE,
PLAYER_ABILITIES,
//Removed in 1.19.3
//PLAYER_CHAT_HEADER,
//Interesting changes in 1.19. This is used by vanilla to broadcast messages sent by clients to all connected clients.
CHAT_MESSAGE,
END_COMBAT_EVENT,
ENTER_COMBAT_EVENT,
DEATH_COMBAT_EVENT,
//Removed in 1.19.3 and replaced with PLAYER_INFO_REMOVE and PLAYER_INFO_UPDATE
//PLAYER_INFO,
//Added in 1.19.3 (read comment above)
PLAYER_INFO_REMOVE,
PLAYER_INFO_UPDATE,
FACE_PLAYER,
PLAYER_POSITION_AND_LOOK,
UNLOCK_RECIPES,
DESTROY_ENTITIES,
REMOVE_ENTITY_EFFECT,
RESOURCE_PACK_SEND,
RESPAWN,
ENTITY_HEAD_LOOK,
MULTI_BLOCK_CHANGE,
SELECT_ADVANCEMENTS_TAB,
//Added in 1.19. Seems like cancelling it surpresses the warning of messages not being verified on the client.
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,
//Deleted in 1.19.3
//DISPLAY_CHAT_PREVIEW,
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,
STOP_SOUND,
//Added in 1.19. This is now used only for system messages by vanilla.
SYSTEM_CHAT_MESSAGE,
PLAYER_LIST_HEADER_AND_FOOTER,
NBT_QUERY_RESPONSE,
COLLECT_ITEM,
ENTITY_TELEPORT,
UPDATE_ADVANCEMENTS,
UPDATE_ATTRIBUTES,
//Added in 1.19.3
UPDATE_ENABLED_FEATURES,
ENTITY_EFFECT,
DECLARE_RECIPES,
TAGS
}
@@ -0,0 +1,133 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 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_19_4 {
BUNDLE, // New packet
SPAWN_ENTITY,
SPAWN_EXPERIENCE_ORB,
SPAWN_PLAYER,
ENTITY_ANIMATION,
STATISTICS,
ACKNOWLEDGE_BLOCK_CHANGES,
BLOCK_BREAK_ANIMATION,
BLOCK_ENTITY_DATA,
BLOCK_ACTION,
BLOCK_CHANGE,
BOSS_BAR,
SERVER_DIFFICULTY,
CHUNK_BIOMES,
CLEAR_TITLES,
TAB_COMPLETE,
DECLARE_COMMANDS,
CLOSE_WINDOW,
WINDOW_ITEMS,
WINDOW_PROPERTY,
SET_SLOT,
SET_COOLDOWN,
CUSTOM_CHAT_COMPLETIONS,
PLUGIN_MESSAGE,
DAMAGE_EVENT, // New packet
DELETE_CHAT,
DISCONNECT,
DISGUISED_CHAT,
ENTITY_STATUS,
EXPLOSION,
UNLOAD_CHUNK,
CHANGE_GAME_STATE,
OPEN_HORSE_WINDOW,
HURT_ANIMATION, // New packet (?)
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,
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,
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,
STOP_SOUND,
SYSTEM_CHAT_MESSAGE,
PLAYER_LIST_HEADER_AND_FOOTER,
NBT_QUERY_RESPONSE,
COLLECT_ITEM,
ENTITY_TELEPORT,
UPDATE_ADVANCEMENTS,
UPDATE_ATTRIBUTES,
UPDATE_ENABLED_FEATURES,
ENTITY_EFFECT,
DECLARE_RECIPES,
TAGS
}
@@ -0,0 +1,137 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 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_2 {
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, // New packet
CHUNK_BATCH_BEGIN, // New packet
CHUNK_BIOMES,
CLEAR_TITLES,
TAB_COMPLETE,
DECLARE_COMMANDS,
CLOSE_WINDOW,
WINDOW_ITEMS,
WINDOW_PROPERTY,
SET_SLOT,
SET_COOLDOWN,
CUSTOM_CHAT_COMPLETIONS,
PLUGIN_MESSAGE,
DAMAGE_EVENT,
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, // New packet
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,
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, // New packet
STOP_SOUND,
SYSTEM_CHAT_MESSAGE,
PLAYER_LIST_HEADER_AND_FOOTER,
NBT_QUERY_RESPONSE,
COLLECT_ITEM,
ENTITY_TELEPORT,
UPDATE_ADVANCEMENTS,
UPDATE_ATTRIBUTES,
// UPDATE_ENABLED_FEATURES, removed
ENTITY_EFFECT,
DECLARE_RECIPES,
TAGS,
}
@@ -0,0 +1,86 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 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_19_3 {
TELEPORT_CONFIRM,
QUERY_BLOCK_NBT,
SET_DIFFICULTY,
//Added in 1.19.1
CHAT_ACK,
//Added in 1.19
CHAT_COMMAND,
//Interesting changes in 1.19
CHAT_MESSAGE,
//Removed in 1.19.3
//CHAT_PREVIEW,
CLIENT_STATUS,
CLIENT_SETTINGS,
TAB_COMPLETE,
CLICK_WINDOW_BUTTON,
CLICK_WINDOW,
CLOSE_WINDOW,
PLUGIN_MESSAGE,
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,
CRAFT_RECIPE_REQUEST,
PLAYER_ABILITIES,
PLAYER_DIGGING,
ENTITY_ACTION,
STEER_VEHICLE,
PONG,
//Added in 1.19.3
CHAT_SESSION_UPDATE,
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
}
@@ -0,0 +1,84 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 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_19_4 {
TELEPORT_CONFIRM,
QUERY_BLOCK_NBT,
SET_DIFFICULTY,
//Added in 1.19.1
CHAT_ACK,
//Added in 1.19
CHAT_COMMAND,
//Interesting changes in 1.19
CHAT_MESSAGE,
CHAT_SESSION_UPDATE, // Moved around in 1.19.4
//Removed in 1.19.3
//CHAT_PREVIEW,
CLIENT_STATUS,
CLIENT_SETTINGS,
TAB_COMPLETE,
CLICK_WINDOW_BUTTON,
CLICK_WINDOW,
CLOSE_WINDOW,
PLUGIN_MESSAGE,
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,
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
}
@@ -0,0 +1,77 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 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_2 {
TELEPORT_CONFIRM,
QUERY_BLOCK_NBT,
SET_DIFFICULTY,
CHAT_ACK,
CHAT_COMMAND,
CHAT_MESSAGE,
CHAT_SESSION_UPDATE,
CHUNK_BATCH_ACK, // New packet
CLIENT_STATUS,
CLIENT_SETTINGS,
TAB_COMPLETE,
CONFIGURATION_ACK, // New packet
CLICK_WINDOW_BUTTON,
CLICK_WINDOW,
CLOSE_WINDOW,
PLUGIN_MESSAGE,
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, // New packet
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,6 +20,7 @@ package com.github.retrooper.packetevents.protocol.particle.data;
import com.github.retrooper.packetevents.util.Vector3i;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
@@ -49,23 +50,23 @@ public class ParticleVibrationData extends ParticleData {
private Vector3i startingPosition;
private PositionType type;
private final Optional<Vector3i> blockPosition;
private final Optional<Integer> entityId;
private @Nullable Vector3i blockPosition;
private @Nullable Integer entityId;
private int ticks;
public ParticleVibrationData(Vector3i startingPosition, Vector3i blockPosition, int ticks) {
public ParticleVibrationData(Vector3i startingPosition, @Nullable Vector3i blockPosition, int ticks) {
this.startingPosition = startingPosition;
this.type = PositionType.BLOCK;
this.blockPosition = Optional.of(blockPosition);
this.entityId = Optional.empty();
this.blockPosition = blockPosition;
this.entityId = null;
this.ticks = ticks;
}
public ParticleVibrationData(Vector3i startingPosition, int entityId, int ticks) {
this.startingPosition = startingPosition;
this.type = PositionType.ENTITY;
this.blockPosition = Optional.empty();
this.entityId = Optional.of(entityId);
this.blockPosition = null;
this.entityId = entityId;
this.ticks = ticks;
}
@@ -82,11 +83,19 @@ public class ParticleVibrationData extends ParticleData {
}
public Optional<Vector3i> getBlockPosition() {
return blockPosition;
return Optional.ofNullable(blockPosition);
}
public void setBlockPosition(@Nullable Vector3i blockPosition) {
this.blockPosition = blockPosition;
}
public Optional<Integer> getEntityId() {
return entityId;
return Optional.ofNullable(entityId);
}
public void setEntityId(int entityId) {
this.entityId = entityId;
}
public int getTicks() {
@@ -43,7 +43,9 @@ public class ParticleTypes {
ClientVersion.V_1_16_2,
ClientVersion.V_1_17,
ClientVersion.V_1_18,
ClientVersion.V_1_19);
ClientVersion.V_1_19,
ClientVersion.V_1_19_4,
ClientVersion.V_1_20);
public static ParticleType define(String key, Function<PacketWrapper<?>, ParticleData> readDataFunction, BiConsumer<PacketWrapper<?>, ParticleData> writeDataFunction) {
TypesBuilderData data = TYPES_BUILDER.defineFromArray(key);
@@ -202,7 +204,13 @@ public class ParticleTypes {
public static final ParticleType ELECTRIC_SPARK = define("electric_spark");
public static final ParticleType SCRAPE = define("scrape");
public static final ParticleType SHRIEK = define("shriek", ParticleShriekData::read, (wrapper, data) -> ParticleShriekData.write(wrapper, (ParticleShriekData) data));
//Added in 1.19.3, BUT REMOVED in 1.20, replaced with CHERRY_LEAVES
public static final ParticleType DRIPPING_CHERRY_LEAVES = define("dripping_cherry_leaves");
public static final ParticleType FALLING_CHERRY_LEAVES = define("falling_cherry_leaves");
public static final ParticleType LANDING_CHERRY_LEAVES = define("landing_cherry_leaves");
//Added in 1.20
public static final ParticleType CHERRY_LEAVES = define("cherry_leaves");
public static final ParticleType EGG_CRACK = define("egg_crack");
static {
TYPES_BUILDER.unloadFileMappings();
}
@@ -22,6 +22,10 @@ import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.manager.server.VersionComparison;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* Client Version.
* This is a nice tool for minecraft's client protocol versions.
@@ -76,11 +80,15 @@ public enum ClientVersion {
V_1_19(759),
V_1_19_1(760),
V_1_19_3(761),
V_1_19_4(762),
V_1_20(763),
V_1_20_2(764),
//TODO UPDATE Add new protocol version field
LOWER_THAN_SUPPORTED_VERSIONS(V_1_7_10.protocolVersion - 1, true),
//TODO UPDATE Update HIGHER_THAN_SUPPORTED_VERSIONS field
HIGHER_THAN_SUPPORTED_VERSIONS(V_1_19_1.protocolVersion + 1, true),
HIGHER_THAN_SUPPORTED_VERSIONS(V_1_20_2.protocolVersion + 1, true),
UNKNOWN(-1, true);
@@ -88,15 +96,9 @@ public enum ClientVersion {
private static final ClientVersion[] REVERSED_VALUES;
static {
REVERSED_VALUES = values();
int i = 0;
int j = REVERSED_VALUES.length - 1;
ClientVersion tmp;
while (j > i) {
tmp = REVERSED_VALUES[j];
REVERSED_VALUES[j--] = REVERSED_VALUES[i];
REVERSED_VALUES[i++] = tmp;
}
List<ClientVersion> valuesAsList = Arrays.asList(values());
Collections.reverse(valuesAsList);
REVERSED_VALUES = valuesAsList.toArray(new ClientVersion[0]);
}
private static final int LOWEST_SUPPORTED_PROTOCOL_VERSION = LOWER_THAN_SUPPORTED_VERSIONS.protocolVersion + 1;
@@ -275,4 +277,4 @@ public enum ClientVersion {
return false;
}
}
}
}
@@ -18,8 +18,6 @@
package com.github.retrooper.packetevents.protocol.player;
import org.jetbrains.annotations.Nullable;
/**
* Representation of a player's game mode.
*
@@ -38,11 +36,15 @@ public enum GameMode {
return ordinal();
}
@Nullable
public static GameMode getById(int id) {
if (id == -1) {
return null;
// Minecraft defaults to a survival gamemode if invalid
if (id < 0 || id >= VALUES.length) {
return GameMode.SURVIVAL;
}
return VALUES[id];
}
public static GameMode defaultGameMode() {
return SURVIVAL;
}
}
@@ -0,0 +1,50 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 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.player;
import java.security.PublicKey;
import java.time.Instant;
public class PublicProfileKey {
private final Instant expiresAt;
private final PublicKey key;
private final byte[] keySignature;
public PublicProfileKey(Instant expiresAt, PublicKey key, byte[] keySignature) {
this.expiresAt = expiresAt;
this.key = key;
this.keySignature = keySignature;
}
public Instant getExpiresAt() {
return expiresAt;
}
public PublicKey getKey() {
return key;
}
public byte[] getKeySignature() {
return keySignature;
}
public boolean hasExpired() {
return expiresAt.isBefore(Instant.now());
}
}
@@ -29,7 +29,8 @@ import com.github.retrooper.packetevents.protocol.chat.message.ChatMessageLegacy
import com.github.retrooper.packetevents.protocol.chat.message.ChatMessage_v1_16;
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
import com.github.retrooper.packetevents.protocol.nbt.NBTList;
import com.github.retrooper.packetevents.util.AdventureSerializer;
import com.github.retrooper.packetevents.protocol.world.Dimension;
import com.github.retrooper.packetevents.util.adventure.AdventureSerializer;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import com.github.retrooper.packetevents.wrapper.play.server.*;
import net.kyori.adventure.text.Component;
@@ -41,19 +42,22 @@ import java.util.UUID;
public class User {
private final Object channel;
private ConnectionState connectionState;
private ConnectionState decoderState;
private ConnectionState encoderState;
private ClientVersion clientVersion;
private final UserProfile profile;
private int entityId = -1;
private int minWorldHeight = 0;
private int totalWorldHeight = 256;
private List<NBTCompound> worldNBT;
private Dimension dimension = new Dimension(0);
public User(Object channel,
ConnectionState connectionState, ClientVersion clientVersion,
UserProfile profile) {
this.channel = channel;
this.connectionState = connectionState;
this.decoderState = connectionState;
this.encoderState = connectionState;
this.clientVersion = clientVersion;
this.profile = profile;
}
@@ -67,11 +71,37 @@ public class User {
}
public ConnectionState getConnectionState() {
return connectionState;
ConnectionState decoderState = this.decoderState;
ConnectionState encoderState = this.encoderState;
if (decoderState != encoderState) {
throw new IllegalArgumentException("Can't get common connection state: " + decoderState + " != " + encoderState);
}
return decoderState;
}
public void setConnectionState(ConnectionState connectionState) {
this.connectionState = connectionState;
this.setDecoderState(connectionState);
this.setEncoderState(connectionState);
}
public ConnectionState getDecoderState() {
return this.decoderState;
}
public void setDecoderState(ConnectionState decoderState) {
this.decoderState = decoderState;
PacketEvents.getAPI().getLogManager().debug(
"Transitioned " + this.getName() + "'s decoder into " + decoderState + " state!");
}
public ConnectionState getEncoderState() {
return this.encoderState;
}
public void setEncoderState(ConnectionState encoderState) {
this.encoderState = encoderState;
PacketEvents.getAPI().getLogManager().debug(
"Transitioned " + this.getName() + "'s encoder into " + encoderState + " state!");
}
public ClientVersion getClientVersion() {
@@ -148,7 +178,8 @@ public class User {
}
public void sendMessage(Component component, ChatType type) {
ServerVersion version = PacketEvents.getAPI().getServerManager().getVersion();
ServerVersion version = PacketEvents.getAPI().getInjector().isProxy() ? getClientVersion().toServerVersion() :
PacketEvents.getAPI().getServerManager().getVersion();
PacketWrapper<?> chatPacket;
if (version.isNewerThanOrEquals(ServerVersion.V_1_19)) {
chatPacket = new WrapperPlayServerSystemChatMessage(false, component);
@@ -172,7 +203,9 @@ public class User {
}
public void sendTitle(Component title, Component subtitle, int fadeInTicks, int stayTicks, int fadeOutTicks) {
boolean modern = PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_17);
ServerVersion version = PacketEvents.getAPI().getInjector().isProxy() ? getClientVersion().toServerVersion() :
PacketEvents.getAPI().getServerManager().getVersion();
boolean modern = version.isNewerThanOrEquals(ServerVersion.V_1_17);
PacketWrapper<?> animation;
PacketWrapper<?> setTitle = null;
PacketWrapper<?> setSubtitle = null;
@@ -230,8 +263,19 @@ public class User {
this.worldNBT = worldNBT.getTags();
}
public Dimension getDimension() {
return dimension;
}
public void setDimension(Dimension dimension) {
this.dimension = dimension;
}
@Nullable
public NBTCompound getWorldNBT(String worldName) {
if (worldNBT == null) {
return null;
}
for (NBTCompound compound : worldNBT) {
if (compound.getStringTagOrNull("name").getValue().equals(worldName)) {
return compound;
@@ -18,8 +18,8 @@
package com.github.retrooper.packetevents.protocol.potion;
import com.github.retrooper.packetevents.protocol.mapper.StaticMappedEntity;
import com.github.retrooper.packetevents.protocol.mapper.MappedEntity;
public interface PotionType extends StaticMappedEntity {
public interface PotionType extends MappedEntity {
}
@@ -18,6 +18,8 @@
package com.github.retrooper.packetevents.protocol.potion;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.resources.ResourceLocation;
import org.jetbrains.annotations.Nullable;
@@ -37,14 +39,17 @@ public class PotionTypes {
}
@Override
public int getId() {
public int getId(ClientVersion version) {
if (version.isOlderThan(ClientVersion.V_1_20_2)) {
return id + 1;
}
return id;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof PotionType) {
return getId() == ((PotionType)obj).getId();
return getName().equals(((PotionType)obj).getName());
}
return false;
}
@@ -52,7 +57,8 @@ public class PotionTypes {
//minecraft:speed would be a string for example
POTION_TYPE_MAP.put(potionType.getName().toString(), potionType);
POTION_TYPE_ID_MAP.put((byte) potionType.getId(), potionType);
//We map the 1.20.2 IDs
POTION_TYPE_ID_MAP.put((byte) potionType.getId(ClientVersion.V_1_20_2), potionType);
return potionType;
}
@@ -61,42 +67,55 @@ public class PotionTypes {
return POTION_TYPE_MAP.get(name);
}
@Nullable
public static PotionType getById(int id) {
@Deprecated
public static @Nullable PotionType getById(int id) {
return getById(id, PacketEvents.getAPI().getServerManager().getVersion().toClientVersion());
}
public static @Nullable PotionType getById(int id, com.github.retrooper.packetevents.manager.server.ServerVersion version) {
return getById(id, version.toClientVersion());
}
public static @Nullable PotionType getById(int id, ClientVersion version) {
if (version.isOlderThan(ClientVersion.V_1_20_2)) {
//We map the 1.20.2 values (starting from 0)
//If the version is older than that, we must subtract one from the input ID (cause it starts from 1)
id--; // potion effects ids where shifted by -1 in 1.20.2
}
return POTION_TYPE_ID_MAP.get((byte)id);
}
public static final PotionType SPEED = define("speed", 1);
public static final PotionType SLOWNESS = define("slowness", 2);
public static final PotionType HASTE = define("haste", 3);
public static final PotionType MINING_FATIGUE = define("mining_fatigue", 4);
public static final PotionType STRENGTH = define("strength", 5);
public static final PotionType INSTANT_HEALTH = define("instant_health", 6);
public static final PotionType INSTANT_DAMAGE = define("instant_damage", 7);
public static final PotionType JUMP_BOOST = define("jump_boost", 8);
public static final PotionType NAUSEA = define("nausea", 9);
public static final PotionType REGENERATION = define("regeneration", 10);
public static final PotionType RESISTANCE = define("resistance", 11);
public static final PotionType FIRE_RESISTANCE = define("fire_resistance", 12);
public static final PotionType WATER_BREATHING = define("water_breathing", 13);
public static final PotionType INVISIBILITY = define("invisibility", 14);
public static final PotionType BLINDNESS = define("blindness", 15);
public static final PotionType NIGHT_VISION = define("night_vision", 16);
public static final PotionType HUNGER = define("hunger", 17);
public static final PotionType WEAKNESS = define("weakness", 18);
public static final PotionType POISON = define("poison", 19);
public static final PotionType WITHER = define("wither", 20);
public static final PotionType HEALTH_BOOST = define("health_boost", 21);
public static final PotionType ABSORPTION = define("absorption", 22);
public static final PotionType SATURATION = define("saturation", 23);
public static final PotionType GLOWING = define("glowing", 24);
public static final PotionType LEVITATION = define("levitation", 25);
public static final PotionType LUCK = define("luck", 26);
public static final PotionType UNLUCK = define("unluck", 27);
public static final PotionType SLOW_FALLING = define("slow_falling", 28);
public static final PotionType CONDUIT_POWER = define("conduit_power", 29);
public static final PotionType DOLPHINS_GRACE = define("dolphins_grace", 30);
public static final PotionType BAD_OMEN = define("bad_omen", 31);
public static final PotionType HERO_OF_THE_VILLAGE = define("hero_of_the_village", 32);
public static final PotionType DARKNESS = define("darkness", 33);
public static final PotionType SPEED = define("speed", 0);
public static final PotionType SLOWNESS = define("slowness", 1);
public static final PotionType HASTE = define("haste", 2);
public static final PotionType MINING_FATIGUE = define("mining_fatigue", 3);
public static final PotionType STRENGTH = define("strength", 4);
public static final PotionType INSTANT_HEALTH = define("instant_health", 5);
public static final PotionType INSTANT_DAMAGE = define("instant_damage", 6);
public static final PotionType JUMP_BOOST = define("jump_boost", 7);
public static final PotionType NAUSEA = define("nausea", 8);
public static final PotionType REGENERATION = define("regeneration", 9);
public static final PotionType RESISTANCE = define("resistance", 10);
public static final PotionType FIRE_RESISTANCE = define("fire_resistance", 11);
public static final PotionType WATER_BREATHING = define("water_breathing", 12);
public static final PotionType INVISIBILITY = define("invisibility", 13);
public static final PotionType BLINDNESS = define("blindness", 14);
public static final PotionType NIGHT_VISION = define("night_vision", 15);
public static final PotionType HUNGER = define("hunger", 16);
public static final PotionType WEAKNESS = define("weakness", 17);
public static final PotionType POISON = define("poison", 18);
public static final PotionType WITHER = define("wither", 19);
public static final PotionType HEALTH_BOOST = define("health_boost", 20);
public static final PotionType ABSORPTION = define("absorption", 21);
public static final PotionType SATURATION = define("saturation", 22);
public static final PotionType GLOWING = define("glowing", 23);
public static final PotionType LEVITATION = define("levitation", 24);
public static final PotionType LUCK = define("luck", 25);
public static final PotionType UNLUCK = define("unluck", 26);
public static final PotionType SLOW_FALLING = define("slow_falling", 27);
public static final PotionType CONDUIT_POWER = define("conduit_power", 28);
public static final PotionType DOLPHINS_GRACE = define("dolphins_grace", 29);
public static final PotionType BAD_OMEN = define("bad_omen", 30);
public static final PotionType HERO_OF_THE_VILLAGE = define("hero_of_the_village", 31);
public static final PotionType DARKNESS = define("darkness", 32);
}
@@ -20,8 +20,8 @@ package com.github.retrooper.packetevents.protocol.stats;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.util.AdventureSerializer;
import com.github.retrooper.packetevents.util.MappingHelper;
import com.github.retrooper.packetevents.util.adventure.AdventureSerializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import net.kyori.adventure.text.Component;
@@ -67,5 +67,6 @@ public enum MaterialType {
AMETHYST,
POWDER_SNOW,
FROGSPAWN,
FROGLIGHT
FROGLIGHT,
DECORATED_POT
}
@@ -32,9 +32,26 @@ import com.github.retrooper.packetevents.protocol.world.chunk.storage.LegacyFlex
import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
public interface BaseChunk {
WrappedBlockState get(ClientVersion version, int x, int y, int z);
int getBlockId(int x, int y, int z);
void set(ClientVersion version, int x, int y, int z, int combinedID);
default WrappedBlockState get(ClientVersion version, int x, int y, int z) {
return WrappedBlockState.getByGlobalId(version, getBlockId(x, y, z));
}
default WrappedBlockState get(int x, int y, int z) {
return get(PacketEvents.getAPI().getServerManager().getVersion().toClientVersion(), x, y, z);
}
default void set(int x, int y, int z, WrappedBlockState state) {
set(x, y, z, state.getGlobalId());
}
void set(int x, int y, int z, int combinedID);
// We don't use ClientVersion, but it's here to maintain backwards compatibility.
default void set(ClientVersion version, int x, int y, int z, int combinedID) {
set(x, y, z, combinedID);
}
boolean isEmpty();
@@ -84,11 +84,11 @@ public class Chunk_v1_9 implements BaseChunk {
}
@Override
public WrappedBlockState get(ClientVersion version, int x, int y, int z) {
return WrappedBlockState.getByGlobalId(version, this.dataPalette.get(x, y, z));
public int getBlockId(int x, int y, int z) {
return this.dataPalette.get(x, y, z);
}
public void set(ClientVersion version, int x, int y, int z, int state) {
public void set(int x, int y, int z, int state) {
int curr = this.dataPalette.set(x, y, z, state);
// Pre-1.14 we don't get block counts
if (blockCount == Integer.MAX_VALUE) return;
@@ -44,13 +44,12 @@ public class Chunk_v1_7 implements BaseChunk {
}
@Override
public WrappedBlockState get(ClientVersion version, int x, int y, int z) {
int combinedID = blocks.get(x, y, z) | (extendedBlocks.get(x, y, z) << 12);
return WrappedBlockState.getByGlobalId(version, combinedID);
public int getBlockId(int x, int y, int z) {
return blocks.get(x, y, z) | (extendedBlocks.get(x, y, z) << 12);
}
@Override
public void set(ClientVersion version, int x, int y, int z, int combinedID) {
public void set(int x, int y, int z, int combinedID) {
blocks.set(x, y, z, combinedID & 0xFF);
extendedBlocks.set(x, y, z, combinedID >> 12);
}
@@ -52,13 +52,12 @@ public class Chunk_v1_8 implements BaseChunk {
}
@Override
public WrappedBlockState get(ClientVersion version, int x, int y, int z) {
int combinedID = this.blocks.get(x, y, z);
return WrappedBlockState.getByGlobalId(version, combinedID);
public int getBlockId(int x, int y, int z) {
return this.blocks.get(x, y, z);
}
@Override
public void set(ClientVersion version, int x, int y, int z, int combinedID) {
public void set(int x, int y, int z, int combinedID) {
this.blocks.set(x, y, z, combinedID);
}
@@ -61,12 +61,12 @@ public class Chunk_v1_18 implements BaseChunk {
}
@Override
public WrappedBlockState get(ClientVersion version, int x, int y, int z) {
return WrappedBlockState.getByGlobalId(version, this.chunkData.get(x, y, z));
public int getBlockId(int x, int y, int z) {
return this.chunkData.get(x, y, z);
}
@Override
public void set(ClientVersion version, int x, int y, int z, int state) {
public void set(int x, int y, int z, int state) {
int curr = this.chunkData.set(x, y, z, state);
if (state != AIR && curr == AIR) {
this.blockCount++;
@@ -19,10 +19,11 @@
package com.github.retrooper.packetevents.protocol.world.chunk.reader;
import com.github.retrooper.packetevents.protocol.stream.NetStreamInput;
import com.github.retrooper.packetevents.protocol.world.Dimension;
import com.github.retrooper.packetevents.protocol.world.chunk.BaseChunk;
import java.util.BitSet;
public interface ChunkReader {
BaseChunk[] read(BitSet set, BitSet sevenExtendedMask, boolean fullChunk, boolean hasSkyLight, boolean checkForSky, int chunkSize, byte[] data, NetStreamInput dataIn);
BaseChunk[] read(Dimension dimension, BitSet set, BitSet sevenExtendedMask, boolean fullChunk, boolean hasSkyLight, boolean checkForSky, int chunkSize, byte[] data, NetStreamInput dataIn);
}
@@ -19,6 +19,7 @@
package com.github.retrooper.packetevents.protocol.world.chunk.reader.impl;
import com.github.retrooper.packetevents.protocol.stream.NetStreamInput;
import com.github.retrooper.packetevents.protocol.world.Dimension;
import com.github.retrooper.packetevents.protocol.world.chunk.BaseChunk;
import com.github.retrooper.packetevents.protocol.world.chunk.impl.v1_16.Chunk_v1_9;
import com.github.retrooper.packetevents.protocol.world.chunk.reader.ChunkReader;
@@ -27,7 +28,7 @@ import java.util.BitSet;
public class ChunkReader_v1_16 implements ChunkReader {
@Override
public BaseChunk[] read(BitSet set, BitSet sevenExtendedMask, boolean fullChunk, boolean hasSkyLight, boolean checkForSky, int chunkSize, byte[] data, NetStreamInput dataIn) {
public BaseChunk[] read(Dimension dimension, BitSet set, BitSet sevenExtendedMask, boolean fullChunk, boolean hasSkyLight, boolean checkForSky, int chunkSize, byte[] data, NetStreamInput dataIn) {
BaseChunk[] chunks = new BaseChunk[chunkSize];
for (int index = 0; index < chunks.length; ++index) {
@@ -19,6 +19,7 @@
package com.github.retrooper.packetevents.protocol.world.chunk.reader.impl;
import com.github.retrooper.packetevents.protocol.stream.NetStreamInput;
import com.github.retrooper.packetevents.protocol.world.Dimension;
import com.github.retrooper.packetevents.protocol.world.chunk.BaseChunk;
import com.github.retrooper.packetevents.protocol.world.chunk.impl.v_1_18.Chunk_v1_18;
import com.github.retrooper.packetevents.protocol.world.chunk.reader.ChunkReader;
@@ -27,7 +28,7 @@ import java.util.BitSet;
public class ChunkReader_v1_18 implements ChunkReader {
@Override
public BaseChunk[] read(BitSet set, BitSet sevenExtendedMask, boolean fullChunk, boolean hasSkyLight, boolean checkForSky, int chunkSize, byte[] data, NetStreamInput dataIn) {
public BaseChunk[] read(Dimension dimension, BitSet set, BitSet sevenExtendedMask, boolean fullChunk, boolean hasSkyLight, boolean checkForSky, int chunkSize, byte[] data, NetStreamInput dataIn) {
BaseChunk[] chunks = new BaseChunk[chunkSize];
for (int index = 0; index < chunkSize; ++index) {
@@ -19,6 +19,7 @@
package com.github.retrooper.packetevents.protocol.world.chunk.reader.impl;
import com.github.retrooper.packetevents.protocol.stream.NetStreamInput;
import com.github.retrooper.packetevents.protocol.world.Dimension;
import com.github.retrooper.packetevents.protocol.world.chunk.BaseChunk;
import com.github.retrooper.packetevents.protocol.world.chunk.ByteArray3d;
import com.github.retrooper.packetevents.protocol.world.chunk.NetworkChunkData;
@@ -30,7 +31,7 @@ import java.util.BitSet;
public class ChunkReader_v1_7 implements ChunkReader {
@Override
public BaseChunk[] read(BitSet primarySet, BitSet sevenExtendedMask, boolean fullChunk, boolean hasSkyLight, boolean checkForSky, int chunkSize, byte[] data, NetStreamInput dataIn) {
public BaseChunk[] read(Dimension dimension, BitSet primarySet, BitSet sevenExtendedMask, boolean fullChunk, boolean hasSkyLight, boolean checkForSky, int chunkSize, byte[] data, NetStreamInput dataIn) {
Chunk_v1_7[] chunks = new Chunk_v1_7[16];
int pos = 0;
int expected = 0;
@@ -19,6 +19,7 @@
package com.github.retrooper.packetevents.protocol.world.chunk.reader.impl;
import com.github.retrooper.packetevents.protocol.stream.NetStreamInput;
import com.github.retrooper.packetevents.protocol.world.Dimension;
import com.github.retrooper.packetevents.protocol.world.chunk.BaseChunk;
import com.github.retrooper.packetevents.protocol.world.chunk.NetworkChunkData;
import com.github.retrooper.packetevents.protocol.world.chunk.NibbleArray3d;
@@ -34,7 +35,7 @@ import java.util.BitSet;
public class ChunkReader_v1_8 implements ChunkReader {
@Override
public BaseChunk[] read(BitSet set, BitSet sevenExtendedMask, boolean fullChunk, boolean hasSkyLight, boolean checkForSky, int chunkSize, byte[] data, NetStreamInput dataIn) {
public BaseChunk[] read(Dimension dimension, BitSet set, BitSet sevenExtendedMask, boolean fullChunk, boolean hasSkyLight, boolean checkForSky, int chunkSize, byte[] data, NetStreamInput dataIn) {
Chunk_v1_8[] chunks = new Chunk_v1_8[16];
int pos = 0;
int expected = fullChunk ? 256 : 0; // 256 if full chunk for the biome data, always sent if full chunk
@@ -18,49 +18,24 @@
package com.github.retrooper.packetevents.protocol.world.chunk.reader.impl;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.stream.NetStreamInput;
import com.github.retrooper.packetevents.protocol.world.Dimension;
import com.github.retrooper.packetevents.protocol.world.chunk.BaseChunk;
import com.github.retrooper.packetevents.protocol.world.chunk.impl.v1_16.Chunk_v1_9;
import com.github.retrooper.packetevents.protocol.world.chunk.reader.ChunkReader;
import java.io.IOException;
import java.util.BitSet;
public class ChunkReader_v1_9 implements ChunkReader {
@Override
public BaseChunk[] read(BitSet set, BitSet sevenExtendedMask, boolean fullChunk, boolean hasBlockLight, boolean hasSkyLight, int chunkSize, byte[] data, NetStreamInput dataIn) {
public BaseChunk[] read(Dimension dimension, BitSet set, BitSet sevenExtendedMask, boolean fullChunk, boolean hasBlockLight, boolean hasSkyLight, int chunkSize, byte[] data, NetStreamInput dataIn) {
BaseChunk[] chunks = new BaseChunk[chunkSize];
Throwable throwable = null;
try {
for (int index = 0; index < chunks.length; ++index) {
if (set.get(index)) {
chunks[index] = new Chunk_v1_9(dataIn, hasBlockLight, hasSkyLight);
}
for (int index = 0; index < chunks.length; ++index) {
if (set.get(index)) {
chunks[index] = new Chunk_v1_9(dataIn, hasBlockLight, hasSkyLight);
}
} catch (Throwable e) {
throwable = e;
}
if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_14)) return chunks;
try {
// Unfortunately, this is needed to detect whether the chunks contain skylight or not.
// Yes, this hack is required all the way from 1.9 through 1.13!
//
// Minimum is more than 256 bytes when it is a full chunks for biome data
// if not a full chunk, any leftover data means it has skylight
int minimum = fullChunk ? 256 : 0;
if ((dataIn.available() > minimum || throwable != null ) && !hasSkyLight) {
dataIn.reset();
return read(set, sevenExtendedMask, fullChunk, hasBlockLight, true, chunkSize, data, dataIn);
}
} catch (IOException e) {
e.printStackTrace();
}
return chunks;
@@ -80,7 +80,8 @@ public class LegacyFlexibleStorage extends BaseStorage {
this.data[startIndex] = this.data[startIndex] & ~(this.maxEntryValue << startBitSubIndex) | ((long) value & this.maxEntryValue) << startBitSubIndex;
if (startIndex != endIndex) {
int endBitSubIndex = 64 - startBitSubIndex;
this.data[endIndex] = this.data[endIndex] >>> endBitSubIndex << endBitSubIndex | ((long) value & this.maxEntryValue) >> endBitSubIndex;
int j1 = this.bitsPerEntry - endBitSubIndex;
this.data[endIndex] = this.data[endIndex] >>> j1 << j1 | ((long) value & this.maxEntryValue) >> endBitSubIndex;
}
}
@@ -73,9 +73,14 @@ public class WrappedBlockState {
if (data != null) {
for (String s : data) {
String[] split = s.split("=");
StateValue value = StateValue.byName(split[0]);
this.data.put(value, value.getParser().apply(split[1].toUpperCase(Locale.ROOT)));
try {
String[] split = s.split("=");
StateValue value = StateValue.byName(split[0]);
this.data.put(value, value.getParser().apply(split[1].toUpperCase(Locale.ROOT)));
} catch (Exception e) {
e.printStackTrace();
System.out.println("Failed to parse block state: " + s);
}
}
}
@@ -91,6 +96,11 @@ public class WrappedBlockState {
this.mappingsIndex = mappingsIndex;
}
@NotNull
public static WrappedBlockState getByGlobalId(int globalID) {
return getByGlobalId(PacketEvents.getAPI().getServerManager().getVersion().toClientVersion(), globalID);
}
@NotNull
public static WrappedBlockState getByGlobalId(ClientVersion version, int globalID) {
if (globalID == 0) return AIR; // Hardcode for performance
@@ -98,19 +108,29 @@ public class WrappedBlockState {
return BY_ID.get(mappingsIndex).getOrDefault(globalID, AIR).clone();
}
@NotNull
public static WrappedBlockState getByString(String string) {
return getByString(PacketEvents.getAPI().getServerManager().getVersion().toClientVersion(), string);
}
@NotNull
public static WrappedBlockState getByString(ClientVersion version, String string) {
byte mappingsIndex = getMappingsIndex(version);
return BY_STRING.get(mappingsIndex).getOrDefault(string.replace("minecraft:", ""), AIR).clone();
}
@NotNull
public static WrappedBlockState getDefaultState(StateType type) {
return getDefaultState(PacketEvents.getAPI().getServerManager().getVersion().toClientVersion(), type);
}
@NotNull
public static WrappedBlockState getDefaultState(ClientVersion version, StateType type) {
if (type == StateTypes.AIR) return AIR;
byte mappingsIndex = getMappingsIndex(version);
WrappedBlockState state = DEFAULT_STATES.get(mappingsIndex).get(type);
if (state == null) {
PacketEvents.getAPI().getLogger().warning("Default state for " + type.getName() + " is null. Returning AIR");
PacketEvents.getAPI().getLogger().config("Default state for " + type.getName() + " is null. Returning AIR");
return AIR;
}
return state.clone();
@@ -133,9 +153,16 @@ public class WrappedBlockState {
return 6;
} else if (version.isOlderThanOrEquals(ClientVersion.V_1_18_2)) {
return 7;
} else {
} else if (version.isOlderThanOrEquals(ClientVersion.V_1_19_1)) {
return 8;
} else if (version.isOlderThanOrEquals(ClientVersion.V_1_19_3)) {
return 9;
} else if (version.isOlderThanOrEquals(ClientVersion.V_1_19_4)) {
return 10;
} else if (version.isOlderThanOrEquals(ClientVersion.V_1_20)) {
return 11;
}
return 12;
}
private static void loadLegacy() {
@@ -885,6 +912,66 @@ public class WrappedBlockState {
checkIsStillValid();
}
public boolean isSlotZeroOccupied() {
return (boolean) data.get(StateValue.SLOT_0_OCCUPIED);
}
public void setSlotZeroOccupied(boolean slotZeroOccupied) {
checkIfCloneNeeded();
data.put(StateValue.SLOT_0_OCCUPIED, slotZeroOccupied);
checkIsStillValid();
}
public boolean isSlotOneOccupied() {
return (boolean) data.get(StateValue.SLOT_1_OCCUPIED);
}
public void setSlotOneOccupied(boolean slotOneOccupied) {
checkIfCloneNeeded();
data.put(StateValue.SLOT_1_OCCUPIED, slotOneOccupied);
checkIsStillValid();
}
public boolean isSlotTwoOccupied() {
return (boolean) data.get(StateValue.SLOT_2_OCCUPIED);
}
public void setSlotTwoOccupied(boolean slotTwoOccupied) {
checkIfCloneNeeded();
data.put(StateValue.SLOT_2_OCCUPIED, slotTwoOccupied);
checkIsStillValid();
}
public boolean isSlotThreeOccupied() {
return (boolean) data.get(StateValue.SLOT_3_OCCUPIED);
}
public void setSlotThreeOccupied(boolean slotThreeOccupied) {
checkIfCloneNeeded();
data.put(StateValue.SLOT_3_OCCUPIED, slotThreeOccupied);
checkIsStillValid();
}
public boolean isSlotFourOccupied() {
return (boolean) data.get(StateValue.SLOT_4_OCCUPIED);
}
public void setSlotFourOccupied(boolean slotFourOccupied) {
checkIfCloneNeeded();
data.put(StateValue.SLOT_4_OCCUPIED, slotFourOccupied);
checkIsStillValid();
}
public boolean isSlotFiveOccupied() {
return (boolean) data.get(StateValue.SLOT_5_OCCUPIED);
}
public void setSlotFiveOccupied(boolean slotFiveOccupied) {
checkIfCloneNeeded();
data.put(StateValue.SLOT_5_OCCUPIED, slotFiveOccupied);
checkIsStillValid();
}
public boolean isSnowy() {
return (boolean) data.get(StateValue.SNOWY);
}
@@ -1099,4 +1186,4 @@ public class WrappedBlockState {
public String toString() {
return INTO_STRING.get(mappingsIndex).get(this);
}
}
}
@@ -29,6 +29,9 @@ import java.util.Set;
/**
* This class allows you to use block tags on outdated versions.
* If you are on a version that sends tags to the player, you are suggested to listen to {@link com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerTags}
*
* Might as well just fucking shade the entire vanilla jar if we are going to copy SO MANY HUNDREDS OF LINES
* @author DefineOutside
*/
public class BlockTags {
private static final HashMap<String, BlockTags> byName = new HashMap<>();
@@ -37,8 +40,9 @@ public class BlockTags {
public static final BlockTags PLANKS = bind("planks");
public static final BlockTags STONE_BRICKS = bind("stone_bricks");
public static final BlockTags WOODEN_BUTTONS = bind("wooden_buttons");
public static final BlockTags STONE_BUTTONS = bind("stone_buttons");
public static final BlockTags BUTTONS = bind("buttons");
public static final BlockTags CARPETS = bind("carpets");
public static final BlockTags WOOL_CARPETS = bind("wool_carpets");
public static final BlockTags WOODEN_DOORS = bind("wooden_doors");
public static final BlockTags WOODEN_STAIRS = bind("wooden_stairs");
public static final BlockTags WOODEN_SLABS = bind("wooden_slabs");
@@ -50,17 +54,23 @@ public class BlockTags {
public static final BlockTags DOORS = bind("doors");
public static final BlockTags SAPLINGS = bind("saplings");
public static final BlockTags LOGS_THAT_BURN = bind("logs_that_burn");
public static final BlockTags OVERWORLD_NATURAL_LOGS = bind("overworld_natural_logs");
public static final BlockTags LOGS = bind("logs");
public static final BlockTags DARK_OAK_LOGS = bind("dark_oak_logs");
public static final BlockTags OAK_LOGS = bind("oak_logs");
public static final BlockTags BIRCH_LOGS = bind("birch_logs");
public static final BlockTags ACACIA_LOGS = bind("acacia_logs");
public static final BlockTags CHERRY_LOGS = bind("cherry_logs");
public static final BlockTags JUNGLE_LOGS = bind("jungle_logs");
public static final BlockTags SPRUCE_LOGS = bind("spruce_logs");
public static final BlockTags MANGROVE_LOGS = bind("mangrove_logs");
public static final BlockTags CRIMSON_STEMS = bind("crimson_stems");
public static final BlockTags WARPED_STEMS = bind("warped_stems");
public static final BlockTags BAMBOO_BLOCKS = bind("bamboo_blocks");
public static final BlockTags WART_BLOCKS = bind("wart_blocks");
public static final BlockTags BANNERS = bind("banners");
public static final BlockTags SAND = bind("sand");
public static final BlockTags SMELTS_TO_GLASS = bind("smelts_to_glass");
public static final BlockTags STAIRS = bind("stairs");
public static final BlockTags SLABS = bind("slabs");
public static final BlockTags WALLS = bind("walls");
@@ -82,10 +92,10 @@ public class BlockTags {
public static final BlockTags COAL_ORES = bind("coal_ores");
public static final BlockTags EMERALD_ORES = bind("emerald_ores");
public static final BlockTags COPPER_ORES = bind("copper_ores");
public static final BlockTags NON_FLAMMABLE_WOOD = bind("non_flammable_wood");
public static final BlockTags CANDLES = bind("candles");
public static final BlockTags DIRT = bind("dirt");
public static final BlockTags TERRACOTTA = bind("terracotta");
public static final BlockTags COMPLETES_FIND_TREE_TUTORIAL = bind("completes_find_tree_tutorial");
public static final BlockTags FLOWER_POTS = bind("flower_pots");
public static final BlockTags ENDERMAN_HOLDABLE = bind("enderman_holdable");
public static final BlockTags ICE = bind("ice");
@@ -100,7 +110,12 @@ public class BlockTags {
public static final BlockTags STANDING_SIGNS = bind("standing_signs");
public static final BlockTags WALL_SIGNS = bind("wall_signs");
public static final BlockTags SIGNS = bind("signs");
public static final BlockTags CEILING_HANGING_SIGNS = bind("ceiling_hanging_signs");
public static final BlockTags WALL_HANGING_SIGNS = bind("wall_hanging_signs");
public static final BlockTags ALL_HANGING_SIGNS = bind("all_hanging_signs");
public static final BlockTags ALL_SIGNS = bind("all_signs");
public static final BlockTags DRAGON_IMMUNE = bind("dragon_immune");
public static final BlockTags DRAGON_TRANSPARENT = bind("dragon_transparent");
public static final BlockTags WITHER_IMMUNE = bind("wither_immune");
public static final BlockTags WITHER_SUMMON_BASE_BLOCKS = bind("wither_summon_base_blocks");
public static final BlockTags BEEHIVES = bind("beehives");
@@ -109,11 +124,11 @@ public class BlockTags {
public static final BlockTags PORTALS = bind("portals");
public static final BlockTags FIRE = bind("fire");
public static final BlockTags NYLIUM = bind("nylium");
public static final BlockTags WART_BLOCKS = bind("wart_blocks");
public static final BlockTags BEACON_BASE_BLOCKS = bind("beacon_base_blocks");
public static final BlockTags SOUL_SPEED_BLOCKS = bind("soul_speed_blocks");
public static final BlockTags WALL_POST_OVERRIDE = bind("wall_post_override");
public static final BlockTags CLIMBABLE = bind("climbable");
public static final BlockTags FALL_DAMAGE_RESETTING = bind("fall_damage_resetting");
public static final BlockTags SHULKER_BOXES = bind("shulker_boxes");
public static final BlockTags HOGLIN_REPELLENTS = bind("hoglin_repellents");
public static final BlockTags SOUL_FIRE_BASE_BLOCKS = bind("soul_fire_base_blocks");
@@ -131,11 +146,15 @@ public class BlockTags {
public static final BlockTags STONE_ORE_REPLACEABLES = bind("stone_ore_replaceables");
public static final BlockTags DEEPSLATE_ORE_REPLACEABLES = bind("deepslate_ore_replaceables");
public static final BlockTags BASE_STONE_NETHER = bind("base_stone_nether");
public static final BlockTags OVERWORLD_CARVER_REPLACEABLES = bind("overworld_carver_replaceables");
public static final BlockTags NETHER_CARVER_REPLACEABLES = bind("nether_carver_replaceables");
public static final BlockTags CANDLE_CAKES = bind("candle_cakes");
public static final BlockTags CAULDRONS = bind("cauldrons");
public static final BlockTags CRYSTAL_SOUND_BLOCKS = bind("crystal_sound_blocks");
public static final BlockTags INSIDE_STEP_SOUND_BLOCKS = bind("inside_step_sound_blocks");
public static final BlockTags COMBINATION_STEP_SOUND_BLOCKS = bind("combination_step_sound_blocks");
public static final BlockTags OCCLUDES_VIBRATION_SIGNALS = bind("occludes_vibration_signals");
public static final BlockTags DAMPENS_VIBRATIONS = bind("dampens_vibrations");
public static final BlockTags DRIPSTONE_REPLACEABLE = bind("dripstone_replaceable_blocks");
public static final BlockTags CAVE_VINES = bind("cave_vines");
public static final BlockTags MOSS_REPLACEABLE = bind("moss_replaceable");
@@ -148,23 +167,45 @@ public class BlockTags {
public static final BlockTags MINEABLE_WITH_HOE = bind("mineable/hoe");
public static final BlockTags MINEABLE_WITH_PICKAXE = bind("mineable/pickaxe");
public static final BlockTags MINEABLE_WITH_SHOVEL = bind("mineable/shovel");
public static final BlockTags SWORD_EFFICIENT = bind("sword_efficient");
public static final BlockTags NEEDS_DIAMOND_TOOL = bind("needs_diamond_tool");
public static final BlockTags NEEDS_IRON_TOOL = bind("needs_iron_tool");
public static final BlockTags NEEDS_STONE_TOOL = bind("needs_stone_tool");
public static final BlockTags FEATURES_CANNOT_REPLACE = bind("features_cannot_replace");
public static final BlockTags LAVA_POOL_STONE_CANNOT_REPLACE = bind("lava_pool_stone_cannot_replace");
public static final BlockTags GEODE_INVALID_BLOCKS = bind("geode_invalid_blocks");
public static final BlockTags FROG_PREFER_JUMP_TO = bind("frog_prefer_jump_to");
public static final BlockTags SCULK_REPLACEABLE = bind("sculk_replaceable");
public static final BlockTags SCULK_REPLACEABLE_WORLD_GEN = bind("sculk_replaceable_world_gen");
public static final BlockTags ANCIENT_CITY_REPLACEABLE = bind("ancient_city_replaceable");
public static final BlockTags VIBRATION_RESONATORS = bind("vibration_resonators");
public static final BlockTags ANIMALS_SPAWNABLE_ON = bind("animals_spawnable_on");
public static final BlockTags AXOLOTLS_SPAWNABLE_ON = bind("axolotls_spawnable_on");
public static final BlockTags GOATS_SPAWNABLE_ON = bind("goats_spawnable_on");
public static final BlockTags MOOSHROOMS_SPAWNABLE_ON = bind("mooshrooms_spawnable_on");
public static final BlockTags PARROTS_SPAWNABLE_ON = bind("parrots_spawnable_on");
public static final BlockTags POLAR_BEARS_SPAWNABLE_ON_IN_FROZEN_OCEAN = bind("polar_bears_spawnable_on_in_frozen_ocean");
public static final BlockTags POLAR_BEARS_SPAWNABLE_ON_ALTERNATE = bind("polar_bears_spawnable_on_alternate");
public static final BlockTags RABBITS_SPAWNABLE_ON = bind("rabbits_spawnable_on");
public static final BlockTags FOXES_SPAWNABLE_ON = bind("foxes_spawnable_on");
public static final BlockTags WOLVES_SPAWNABLE_ON = bind("wolves_spawnable_on");
public static final BlockTags FROGS_SPAWNABLE_ON = bind("frogs_spawnable_on");
public static final BlockTags AZALEA_GROWS_ON = bind("azalea_grows_on");
public static final BlockTags REPLACEABLE_PLANTS = bind("replaceable_plants");
public static final BlockTags CONVERTABLE_TO_MUD = bind("convertable_to_mud");
public static final BlockTags MANGROVE_LOGS_CAN_GROW_THROUGH = bind("mangrove_logs_can_grow_through");
public static final BlockTags MANGROVE_ROOTS_CAN_GROW_THROUGH = bind("mangrove_roots_can_grow_through");
public static final BlockTags DEAD_BUSH_MAY_PLACE_ON = bind("dead_bush_may_place_on");
public static final BlockTags SNAPS_GOAT_HORN = bind("snaps_goat_horn");
public static final BlockTags SNOW_LAYER_CANNOT_SURVIVE_ON = bind("snow_layer_cannot_survive_on");
public static final BlockTags SNOW_LAYER_CAN_SURVIVE_ON = bind("snow_layer_can_survive_on");
public static final BlockTags INVALID_SPAWN_INSIDE = bind("invalid_spawn_inside");
public static final BlockTags SNIFFER_DIGGABLE_BLOCK = bind("sniffer_diggable_block");
public static final BlockTags SNIFFER_EGG_HATCH_BOOST = bind("sniffer_egg_hatch_boost");
public static final BlockTags TRAIL_RUINS_REPLACEABLE = bind("trail_ruins_replaceable");
public static final BlockTags REPLACEABLE = bind("replaceable");
public static final BlockTags ENCHANTMENT_POWER_PROVIDER = bind("enchantment_power_provider");
public static final BlockTags ENCHANTMENT_POWER_TRANSMITTER = bind("enchantment_power_transmitter");
public static final BlockTags MAINTAINS_FARMLAND = bind("maintains_farmland");
/**
* Unofficial tag for all glass blocks
*/
@@ -176,69 +217,76 @@ public class BlockTags {
static {
BlockTags.WOOL.add(StateTypes.WHITE_WOOL, StateTypes.ORANGE_WOOL, StateTypes.MAGENTA_WOOL, StateTypes.LIGHT_BLUE_WOOL, StateTypes.YELLOW_WOOL, StateTypes.LIME_WOOL, StateTypes.PINK_WOOL, StateTypes.GRAY_WOOL, StateTypes.LIGHT_GRAY_WOOL, StateTypes.CYAN_WOOL, StateTypes.PURPLE_WOOL, StateTypes.BLUE_WOOL, StateTypes.BROWN_WOOL, StateTypes.GREEN_WOOL, StateTypes.RED_WOOL, StateTypes.BLACK_WOOL);
BlockTags.PLANKS.add(StateTypes.OAK_PLANKS, StateTypes.SPRUCE_PLANKS, StateTypes.BIRCH_PLANKS, StateTypes.JUNGLE_PLANKS, StateTypes.ACACIA_PLANKS, StateTypes.DARK_OAK_PLANKS, StateTypes.CRIMSON_PLANKS, StateTypes.WARPED_PLANKS, StateTypes.MANGROVE_PLANKS);
BlockTags.PLANKS.add(StateTypes.OAK_PLANKS, StateTypes.SPRUCE_PLANKS, StateTypes.BIRCH_PLANKS, StateTypes.JUNGLE_PLANKS, StateTypes.ACACIA_PLANKS, StateTypes.DARK_OAK_PLANKS, StateTypes.CRIMSON_PLANKS, StateTypes.WARPED_PLANKS, StateTypes.MANGROVE_PLANKS, StateTypes.BAMBOO_PLANKS, StateTypes.CHERRY_PLANKS);
BlockTags.STONE_BRICKS.add(StateTypes.STONE_BRICKS, StateTypes.MOSSY_STONE_BRICKS, StateTypes.CRACKED_STONE_BRICKS, StateTypes.CHISELED_STONE_BRICKS);
BlockTags.WOODEN_BUTTONS.add(StateTypes.OAK_BUTTON, StateTypes.SPRUCE_BUTTON, StateTypes.BIRCH_BUTTON, StateTypes.JUNGLE_BUTTON, StateTypes.ACACIA_BUTTON, StateTypes.DARK_OAK_BUTTON, StateTypes.CRIMSON_BUTTON, StateTypes.WARPED_BUTTON, StateTypes.MANGROVE_BUTTON);
BlockTags.BUTTONS.addTag(BlockTags.WOODEN_BUTTONS).add(StateTypes.STONE_BUTTON).add(StateTypes.POLISHED_BLACKSTONE_BUTTON);
// TODO: This was renamed to WOOL_CARPETS in 1.19
BlockTags.CARPETS.add(StateTypes.WHITE_CARPET, StateTypes.ORANGE_CARPET, StateTypes.MAGENTA_CARPET, StateTypes.LIGHT_BLUE_CARPET, StateTypes.YELLOW_CARPET, StateTypes.LIME_CARPET, StateTypes.PINK_CARPET, StateTypes.GRAY_CARPET, StateTypes.LIGHT_GRAY_CARPET, StateTypes.CYAN_CARPET, StateTypes.PURPLE_CARPET, StateTypes.BLUE_CARPET, StateTypes.BROWN_CARPET, StateTypes.GREEN_CARPET, StateTypes.RED_CARPET, StateTypes.BLACK_CARPET);
BlockTags.WOODEN_DOORS.add(StateTypes.OAK_DOOR, StateTypes.SPRUCE_DOOR, StateTypes.BIRCH_DOOR, StateTypes.JUNGLE_DOOR, StateTypes.ACACIA_DOOR, StateTypes.DARK_OAK_DOOR, StateTypes.CRIMSON_DOOR, StateTypes.WARPED_DOOR, StateTypes.MANGROVE_DOOR);
BlockTags.WOODEN_STAIRS.add(StateTypes.OAK_STAIRS, StateTypes.SPRUCE_STAIRS, StateTypes.BIRCH_STAIRS, StateTypes.JUNGLE_STAIRS, StateTypes.ACACIA_STAIRS, StateTypes.DARK_OAK_STAIRS, StateTypes.CRIMSON_STAIRS, StateTypes.WARPED_STAIRS, StateTypes.MANGROVE_STAIRS);
BlockTags.WOODEN_SLABS.add(StateTypes.OAK_SLAB, StateTypes.SPRUCE_SLAB, StateTypes.BIRCH_SLAB, StateTypes.JUNGLE_SLAB, StateTypes.ACACIA_SLAB, StateTypes.DARK_OAK_SLAB, StateTypes.CRIMSON_SLAB, StateTypes.WARPED_SLAB, StateTypes.MANGROVE_SLAB);
BlockTags.WOODEN_FENCES.add(StateTypes.OAK_FENCE, StateTypes.ACACIA_FENCE, StateTypes.DARK_OAK_FENCE, StateTypes.SPRUCE_FENCE, StateTypes.BIRCH_FENCE, StateTypes.JUNGLE_FENCE, StateTypes.CRIMSON_FENCE, StateTypes.WARPED_FENCE, StateTypes.MANGROVE_FENCE);
BlockTags.WOODEN_BUTTONS.add(StateTypes.OAK_BUTTON, StateTypes.SPRUCE_BUTTON, StateTypes.BIRCH_BUTTON, StateTypes.JUNGLE_BUTTON, StateTypes.ACACIA_BUTTON, StateTypes.DARK_OAK_BUTTON, StateTypes.CRIMSON_BUTTON, StateTypes.WARPED_BUTTON, StateTypes.MANGROVE_BUTTON, StateTypes.BAMBOO_BUTTON, StateTypes.CHERRY_BUTTON);
BlockTags.STONE_BUTTONS.add(StateTypes.STONE_BUTTON, StateTypes.POLISHED_BLACKSTONE_BUTTON);
BlockTags.BUTTONS.addTag(BlockTags.WOODEN_BUTTONS).addTag(BlockTags.STONE_BUTTONS);
BlockTags.WOOL_CARPETS.add(StateTypes.WHITE_CARPET, StateTypes.ORANGE_CARPET, StateTypes.MAGENTA_CARPET, StateTypes.LIGHT_BLUE_CARPET, StateTypes.YELLOW_CARPET, StateTypes.LIME_CARPET, StateTypes.PINK_CARPET, StateTypes.GRAY_CARPET, StateTypes.LIGHT_GRAY_CARPET, StateTypes.CYAN_CARPET, StateTypes.PURPLE_CARPET, StateTypes.BLUE_CARPET, StateTypes.BROWN_CARPET, StateTypes.GREEN_CARPET, StateTypes.RED_CARPET, StateTypes.BLACK_CARPET);
BlockTags.WOODEN_DOORS.add(StateTypes.OAK_DOOR, StateTypes.SPRUCE_DOOR, StateTypes.BIRCH_DOOR, StateTypes.JUNGLE_DOOR, StateTypes.ACACIA_DOOR, StateTypes.DARK_OAK_DOOR, StateTypes.CRIMSON_DOOR, StateTypes.WARPED_DOOR, StateTypes.MANGROVE_DOOR, StateTypes.BAMBOO_DOOR, StateTypes.CHERRY_DOOR);
BlockTags.WOODEN_STAIRS.add(StateTypes.OAK_STAIRS, StateTypes.SPRUCE_STAIRS, StateTypes.BIRCH_STAIRS, StateTypes.JUNGLE_STAIRS, StateTypes.ACACIA_STAIRS, StateTypes.DARK_OAK_STAIRS, StateTypes.CRIMSON_STAIRS, StateTypes.WARPED_STAIRS, StateTypes.MANGROVE_STAIRS, StateTypes.BAMBOO_STAIRS, StateTypes.CHERRY_STAIRS);
BlockTags.WOODEN_SLABS.add(StateTypes.OAK_SLAB, StateTypes.SPRUCE_SLAB, StateTypes.BIRCH_SLAB, StateTypes.JUNGLE_SLAB, StateTypes.ACACIA_SLAB, StateTypes.DARK_OAK_SLAB, StateTypes.CRIMSON_SLAB, StateTypes.WARPED_SLAB, StateTypes.MANGROVE_SLAB, StateTypes.BAMBOO_SLAB, StateTypes.CHERRY_SLAB);
BlockTags.WOODEN_FENCES.add(StateTypes.OAK_FENCE, StateTypes.ACACIA_FENCE, StateTypes.DARK_OAK_FENCE, StateTypes.SPRUCE_FENCE, StateTypes.BIRCH_FENCE, StateTypes.JUNGLE_FENCE, StateTypes.CRIMSON_FENCE, StateTypes.WARPED_FENCE, StateTypes.MANGROVE_FENCE, StateTypes.BAMBOO_FENCE, StateTypes.CHERRY_FENCE);
BlockTags.DOORS.addTag(BlockTags.WOODEN_DOORS).add(StateTypes.IRON_DOOR);
BlockTags.SAPLINGS.add(StateTypes.OAK_SAPLING, StateTypes.SPRUCE_SAPLING, StateTypes.BIRCH_SAPLING, StateTypes.JUNGLE_SAPLING, StateTypes.ACACIA_SAPLING, StateTypes.DARK_OAK_SAPLING, StateTypes.AZALEA, StateTypes.FLOWERING_AZALEA, StateTypes.MANGROVE_PROPAGULE);
BlockTags.SAPLINGS.add(StateTypes.OAK_SAPLING, StateTypes.SPRUCE_SAPLING, StateTypes.BIRCH_SAPLING, StateTypes.JUNGLE_SAPLING, StateTypes.ACACIA_SAPLING, StateTypes.DARK_OAK_SAPLING, StateTypes.AZALEA, StateTypes.FLOWERING_AZALEA, StateTypes.MANGROVE_PROPAGULE, StateTypes.CHERRY_SAPLING);
BlockTags.BAMBOO_BLOCKS.add(StateTypes.BAMBOO_BLOCK, StateTypes.STRIPPED_BAMBOO_BLOCK);
BlockTags.DARK_OAK_LOGS.add(StateTypes.DARK_OAK_LOG, StateTypes.DARK_OAK_WOOD, StateTypes.STRIPPED_DARK_OAK_LOG, StateTypes.STRIPPED_DARK_OAK_WOOD);
BlockTags.OAK_LOGS.add(StateTypes.OAK_LOG, StateTypes.OAK_WOOD, StateTypes.STRIPPED_OAK_LOG, StateTypes.STRIPPED_OAK_WOOD);
BlockTags.ACACIA_LOGS.add(StateTypes.ACACIA_LOG, StateTypes.ACACIA_WOOD, StateTypes.STRIPPED_ACACIA_LOG, StateTypes.STRIPPED_ACACIA_WOOD);
BlockTags.CHERRY_LOGS.add(StateTypes.CHERRY_LOG, StateTypes.CHERRY_WOOD, StateTypes.STRIPPED_CHERRY_LOG, StateTypes.STRIPPED_CHERRY_WOOD);
BlockTags.BIRCH_LOGS.add(StateTypes.BIRCH_LOG, StateTypes.BIRCH_WOOD, StateTypes.STRIPPED_BIRCH_LOG, StateTypes.STRIPPED_BIRCH_WOOD);
BlockTags.JUNGLE_LOGS.add(StateTypes.JUNGLE_LOG, StateTypes.JUNGLE_WOOD, StateTypes.STRIPPED_JUNGLE_LOG, StateTypes.STRIPPED_JUNGLE_WOOD);
BlockTags.SPRUCE_LOGS.add(StateTypes.SPRUCE_LOG, StateTypes.SPRUCE_WOOD, StateTypes.STRIPPED_SPRUCE_LOG, StateTypes.STRIPPED_SPRUCE_WOOD);
BlockTags.CRIMSON_STEMS.add(StateTypes.CRIMSON_STEM, StateTypes.STRIPPED_CRIMSON_STEM, StateTypes.CRIMSON_HYPHAE, StateTypes.STRIPPED_CRIMSON_HYPHAE);
BlockTags.WARPED_STEMS.add(StateTypes.WARPED_STEM, StateTypes.STRIPPED_WARPED_STEM, StateTypes.WARPED_HYPHAE, StateTypes.STRIPPED_WARPED_HYPHAE);
// TODO: this.tag(BlockTags.MANGROVE_LOGS).add(Blocks.MANGROVE_LOG, Blocks.MANGROVE_WOOD, Blocks.STRIPPED_MANGROVE_LOG, Blocks.STRIPPED_MANGROVE_WOOD);
BlockTags.LOGS_THAT_BURN.addTag(BlockTags.DARK_OAK_LOGS).addTag(BlockTags.OAK_LOGS).addTag(BlockTags.ACACIA_LOGS).addTag(BlockTags.BIRCH_LOGS).addTag(BlockTags.JUNGLE_LOGS).addTag(BlockTags.SPRUCE_LOGS); // TODO: Add MANGROVE_LOGS tag to this
// TODO: this.tag(BlockTags.OVERWORLD_NATURAL_LOGS).add(Blocks.ACACIA_LOG).add(Blocks.BIRCH_LOG).add(Blocks.OAK_LOG).add(Blocks.JUNGLE_LOG).add(Blocks.SPRUCE_LOG).add(Blocks.DARK_OAK_LOG).add(Blocks.MANGROVE_LOG);
BlockTags.LOGS.addTag(BlockTags.LOGS_THAT_BURN).addTag(BlockTags.CRIMSON_STEMS).addTag(BlockTags.WARPED_STEMS).add(StateTypes.MANGROVE_LOG, StateTypes.MANGROVE_WOOD, StateTypes.STRIPPED_MANGROVE_LOG, StateTypes.STRIPPED_MANGROVE_WOOD); // TODO: Add mangrove logs not manually
BlockTags.MANGROVE_LOGS.add(StateTypes.MANGROVE_LOG, StateTypes.MANGROVE_WOOD, StateTypes.STRIPPED_MANGROVE_LOG, StateTypes.STRIPPED_MANGROVE_WOOD);
BlockTags.LOGS_THAT_BURN.addTag(BlockTags.DARK_OAK_LOGS).addTag(BlockTags.OAK_LOGS).addTag(BlockTags.ACACIA_LOGS).addTag(BlockTags.BIRCH_LOGS).addTag(BlockTags.JUNGLE_LOGS).addTag(BlockTags.SPRUCE_LOGS).addTag(BlockTags.MANGROVE_LOGS).addTag(BlockTags.CHERRY_LOGS);
BlockTags.OVERWORLD_NATURAL_LOGS.add(StateTypes.ACACIA_LOG).add(StateTypes.BIRCH_LOG).add(StateTypes.OAK_LOG).add(StateTypes.JUNGLE_LOG).add(StateTypes.SPRUCE_LOG).add(StateTypes.DARK_OAK_LOG).add(StateTypes.MANGROVE_LOG).add(StateTypes.CHERRY_LOG);
BlockTags.LOGS.addTag(BlockTags.LOGS_THAT_BURN).addTag(BlockTags.CRIMSON_STEMS).addTag(BlockTags.WARPED_STEMS);
BlockTags.ANVIL.add(StateTypes.ANVIL, StateTypes.CHIPPED_ANVIL, StateTypes.DAMAGED_ANVIL);
BlockTags.SMALL_FLOWERS.add(StateTypes.DANDELION, StateTypes.POPPY, StateTypes.BLUE_ORCHID, StateTypes.ALLIUM, StateTypes.AZURE_BLUET, StateTypes.RED_TULIP, StateTypes.ORANGE_TULIP, StateTypes.WHITE_TULIP, StateTypes.PINK_TULIP, StateTypes.OXEYE_DAISY, StateTypes.CORNFLOWER, StateTypes.LILY_OF_THE_VALLEY, StateTypes.WITHER_ROSE);
BlockTags.SMALL_FLOWERS.add(StateTypes.DANDELION, StateTypes.POPPY, StateTypes.BLUE_ORCHID, StateTypes.ALLIUM, StateTypes.AZURE_BLUET, StateTypes.RED_TULIP, StateTypes.ORANGE_TULIP, StateTypes.WHITE_TULIP, StateTypes.PINK_TULIP, StateTypes.OXEYE_DAISY, StateTypes.CORNFLOWER, StateTypes.LILY_OF_THE_VALLEY, StateTypes.WITHER_ROSE, StateTypes.TORCHFLOWER);
BlockTags.DIRT.add(StateTypes.DIRT, StateTypes.GRASS_BLOCK, StateTypes.PODZOL, StateTypes.COARSE_DIRT, StateTypes.MYCELIUM, StateTypes.ROOTED_DIRT, StateTypes.MOSS_BLOCK, StateTypes.MUD, StateTypes.MUDDY_MANGROVE_ROOTS);
BlockTags.ENDERMAN_HOLDABLE.addTag(BlockTags.SMALL_FLOWERS).addTag(BlockTags.DIRT).add(StateTypes.SAND, StateTypes.RED_SAND, StateTypes.GRAVEL, StateTypes.BROWN_MUSHROOM, StateTypes.RED_MUSHROOM, StateTypes.TNT, StateTypes.CACTUS, StateTypes.CLAY, StateTypes.PUMPKIN, StateTypes.CARVED_PUMPKIN, StateTypes.MELON, StateTypes.CRIMSON_FUNGUS, StateTypes.CRIMSON_NYLIUM, StateTypes.CRIMSON_ROOTS, StateTypes.WARPED_FUNGUS, StateTypes.WARPED_NYLIUM, StateTypes.WARPED_ROOTS);
BlockTags.FLOWER_POTS.add(StateTypes.FLOWER_POT, StateTypes.POTTED_POPPY, StateTypes.POTTED_BLUE_ORCHID, StateTypes.POTTED_ALLIUM, StateTypes.POTTED_AZURE_BLUET, StateTypes.POTTED_RED_TULIP, StateTypes.POTTED_ORANGE_TULIP, StateTypes.POTTED_WHITE_TULIP, StateTypes.POTTED_PINK_TULIP, StateTypes.POTTED_OXEYE_DAISY, StateTypes.POTTED_DANDELION, StateTypes.POTTED_OAK_SAPLING, StateTypes.POTTED_SPRUCE_SAPLING, StateTypes.POTTED_BIRCH_SAPLING, StateTypes.POTTED_JUNGLE_SAPLING, StateTypes.POTTED_ACACIA_SAPLING, StateTypes.POTTED_DARK_OAK_SAPLING, StateTypes.POTTED_RED_MUSHROOM, StateTypes.POTTED_BROWN_MUSHROOM, StateTypes.POTTED_DEAD_BUSH, StateTypes.POTTED_FERN, StateTypes.POTTED_CACTUS, StateTypes.POTTED_CORNFLOWER, StateTypes.POTTED_LILY_OF_THE_VALLEY, StateTypes.POTTED_WITHER_ROSE, StateTypes.POTTED_BAMBOO, StateTypes.POTTED_CRIMSON_FUNGUS, StateTypes.POTTED_WARPED_FUNGUS, StateTypes.POTTED_CRIMSON_ROOTS, StateTypes.POTTED_WARPED_ROOTS, StateTypes.POTTED_AZALEA_BUSH, StateTypes.POTTED_FLOWERING_AZALEA_BUSH, StateTypes.POTTED_MANGROVE_PROPAGULE);
BlockTags.FLOWER_POTS.add(StateTypes.FLOWER_POT, StateTypes.POTTED_POPPY, StateTypes.POTTED_BLUE_ORCHID, StateTypes.POTTED_ALLIUM, StateTypes.POTTED_AZURE_BLUET, StateTypes.POTTED_RED_TULIP, StateTypes.POTTED_ORANGE_TULIP, StateTypes.POTTED_WHITE_TULIP, StateTypes.POTTED_PINK_TULIP, StateTypes.POTTED_OXEYE_DAISY, StateTypes.POTTED_DANDELION, StateTypes.POTTED_OAK_SAPLING, StateTypes.POTTED_SPRUCE_SAPLING, StateTypes.POTTED_BIRCH_SAPLING, StateTypes.POTTED_JUNGLE_SAPLING, StateTypes.POTTED_ACACIA_SAPLING, StateTypes.POTTED_DARK_OAK_SAPLING, StateTypes.POTTED_RED_MUSHROOM, StateTypes.POTTED_BROWN_MUSHROOM, StateTypes.POTTED_DEAD_BUSH, StateTypes.POTTED_FERN, StateTypes.POTTED_CACTUS, StateTypes.POTTED_CORNFLOWER, StateTypes.POTTED_LILY_OF_THE_VALLEY, StateTypes.POTTED_WITHER_ROSE, StateTypes.POTTED_BAMBOO, StateTypes.POTTED_CRIMSON_FUNGUS, StateTypes.POTTED_WARPED_FUNGUS, StateTypes.POTTED_CRIMSON_ROOTS, StateTypes.POTTED_WARPED_ROOTS, StateTypes.POTTED_AZALEA_BUSH, StateTypes.POTTED_FLOWERING_AZALEA_BUSH, StateTypes.POTTED_MANGROVE_PROPAGULE, StateTypes.POTTED_CHERRY_SAPLING, StateTypes.POTTED_TORCHFLOWER);
BlockTags.BANNERS.add(StateTypes.WHITE_BANNER, StateTypes.ORANGE_BANNER, StateTypes.MAGENTA_BANNER, StateTypes.LIGHT_BLUE_BANNER, StateTypes.YELLOW_BANNER, StateTypes.LIME_BANNER, StateTypes.PINK_BANNER, StateTypes.GRAY_BANNER, StateTypes.LIGHT_GRAY_BANNER, StateTypes.CYAN_BANNER, StateTypes.PURPLE_BANNER, StateTypes.BLUE_BANNER, StateTypes.BROWN_BANNER, StateTypes.GREEN_BANNER, StateTypes.RED_BANNER, StateTypes.BLACK_BANNER, StateTypes.WHITE_WALL_BANNER, StateTypes.ORANGE_WALL_BANNER, StateTypes.MAGENTA_WALL_BANNER, StateTypes.LIGHT_BLUE_WALL_BANNER, StateTypes.YELLOW_WALL_BANNER, StateTypes.LIME_WALL_BANNER, StateTypes.PINK_WALL_BANNER, StateTypes.GRAY_WALL_BANNER, StateTypes.LIGHT_GRAY_WALL_BANNER, StateTypes.CYAN_WALL_BANNER, StateTypes.PURPLE_WALL_BANNER, StateTypes.BLUE_WALL_BANNER, StateTypes.BROWN_WALL_BANNER, StateTypes.GREEN_WALL_BANNER, StateTypes.RED_WALL_BANNER, StateTypes.BLACK_WALL_BANNER);
BlockTags.WOODEN_PRESSURE_PLATES.add(StateTypes.OAK_PRESSURE_PLATE, StateTypes.SPRUCE_PRESSURE_PLATE, StateTypes.BIRCH_PRESSURE_PLATE, StateTypes.JUNGLE_PRESSURE_PLATE, StateTypes.ACACIA_PRESSURE_PLATE, StateTypes.DARK_OAK_PRESSURE_PLATE, StateTypes.CRIMSON_PRESSURE_PLATE, StateTypes.WARPED_PRESSURE_PLATE, StateTypes.MANGROVE_PRESSURE_PLATE);
BlockTags.WOODEN_PRESSURE_PLATES.add(StateTypes.OAK_PRESSURE_PLATE, StateTypes.SPRUCE_PRESSURE_PLATE, StateTypes.BIRCH_PRESSURE_PLATE, StateTypes.JUNGLE_PRESSURE_PLATE, StateTypes.ACACIA_PRESSURE_PLATE, StateTypes.DARK_OAK_PRESSURE_PLATE, StateTypes.CRIMSON_PRESSURE_PLATE, StateTypes.WARPED_PRESSURE_PLATE, StateTypes.MANGROVE_PRESSURE_PLATE, StateTypes.BAMBOO_PRESSURE_PLATE, StateTypes.CHERRY_PRESSURE_PLATE);
BlockTags.STONE_PRESSURE_PLATES.add(StateTypes.STONE_PRESSURE_PLATE, StateTypes.POLISHED_BLACKSTONE_PRESSURE_PLATE);
BlockTags.PRESSURE_PLATES.add(StateTypes.LIGHT_WEIGHTED_PRESSURE_PLATE, StateTypes.HEAVY_WEIGHTED_PRESSURE_PLATE).addTag(BlockTags.WOODEN_PRESSURE_PLATES).addTag(BlockTags.STONE_PRESSURE_PLATES);
BlockTags.STAIRS.addTag(BlockTags.WOODEN_STAIRS).add(StateTypes.COBBLESTONE_STAIRS, StateTypes.SANDSTONE_STAIRS, StateTypes.NETHER_BRICK_STAIRS, StateTypes.STONE_BRICK_STAIRS, StateTypes.BRICK_STAIRS, StateTypes.PURPUR_STAIRS, StateTypes.QUARTZ_STAIRS, StateTypes.RED_SANDSTONE_STAIRS, StateTypes.PRISMARINE_BRICK_STAIRS, StateTypes.PRISMARINE_STAIRS, StateTypes.DARK_PRISMARINE_STAIRS, StateTypes.POLISHED_GRANITE_STAIRS, StateTypes.SMOOTH_RED_SANDSTONE_STAIRS, StateTypes.MOSSY_STONE_BRICK_STAIRS, StateTypes.POLISHED_DIORITE_STAIRS, StateTypes.MOSSY_COBBLESTONE_STAIRS, StateTypes.END_STONE_BRICK_STAIRS, StateTypes.STONE_STAIRS, StateTypes.SMOOTH_SANDSTONE_STAIRS, StateTypes.SMOOTH_QUARTZ_STAIRS, StateTypes.GRANITE_STAIRS, StateTypes.ANDESITE_STAIRS, StateTypes.RED_NETHER_BRICK_STAIRS, StateTypes.POLISHED_ANDESITE_STAIRS, StateTypes.DIORITE_STAIRS, StateTypes.BLACKSTONE_STAIRS, StateTypes.POLISHED_BLACKSTONE_BRICK_STAIRS, StateTypes.POLISHED_BLACKSTONE_STAIRS, StateTypes.COBBLED_DEEPSLATE_STAIRS, StateTypes.POLISHED_DEEPSLATE_STAIRS, StateTypes.DEEPSLATE_TILE_STAIRS, StateTypes.DEEPSLATE_BRICK_STAIRS, StateTypes.OXIDIZED_CUT_COPPER_STAIRS, StateTypes.WEATHERED_CUT_COPPER_STAIRS, StateTypes.EXPOSED_CUT_COPPER_STAIRS, StateTypes.CUT_COPPER_STAIRS, StateTypes.WAXED_WEATHERED_CUT_COPPER_STAIRS, StateTypes.WAXED_EXPOSED_CUT_COPPER_STAIRS, StateTypes.WAXED_CUT_COPPER_STAIRS, StateTypes.WAXED_OXIDIZED_CUT_COPPER_STAIRS, StateTypes.MUD_BRICK_STAIRS);
BlockTags.SLABS.addTag(BlockTags.WOODEN_SLABS).add(StateTypes.STONE_SLAB, StateTypes.SMOOTH_STONE_SLAB, StateTypes.STONE_BRICK_SLAB, StateTypes.SANDSTONE_SLAB, StateTypes.PURPUR_SLAB, StateTypes.QUARTZ_SLAB, StateTypes.RED_SANDSTONE_SLAB, StateTypes.BRICK_SLAB, StateTypes.COBBLESTONE_SLAB, StateTypes.NETHER_BRICK_SLAB, StateTypes.PETRIFIED_OAK_SLAB, StateTypes.PRISMARINE_SLAB, StateTypes.PRISMARINE_BRICK_SLAB, StateTypes.DARK_PRISMARINE_SLAB, StateTypes.POLISHED_GRANITE_SLAB, StateTypes.SMOOTH_RED_SANDSTONE_SLAB, StateTypes.MOSSY_STONE_BRICK_SLAB, StateTypes.POLISHED_DIORITE_SLAB, StateTypes.MOSSY_COBBLESTONE_SLAB, StateTypes.END_STONE_BRICK_SLAB, StateTypes.SMOOTH_SANDSTONE_SLAB, StateTypes.SMOOTH_QUARTZ_SLAB, StateTypes.GRANITE_SLAB, StateTypes.ANDESITE_SLAB, StateTypes.RED_NETHER_BRICK_SLAB, StateTypes.POLISHED_ANDESITE_SLAB, StateTypes.DIORITE_SLAB, StateTypes.CUT_SANDSTONE_SLAB, StateTypes.CUT_RED_SANDSTONE_SLAB, StateTypes.BLACKSTONE_SLAB, StateTypes.POLISHED_BLACKSTONE_BRICK_SLAB, StateTypes.POLISHED_BLACKSTONE_SLAB, StateTypes.COBBLED_DEEPSLATE_SLAB, StateTypes.POLISHED_DEEPSLATE_SLAB, StateTypes.DEEPSLATE_TILE_SLAB, StateTypes.DEEPSLATE_BRICK_SLAB, StateTypes.WAXED_WEATHERED_CUT_COPPER_SLAB, StateTypes.WAXED_EXPOSED_CUT_COPPER_SLAB, StateTypes.WAXED_CUT_COPPER_SLAB, StateTypes.OXIDIZED_CUT_COPPER_SLAB, StateTypes.WEATHERED_CUT_COPPER_SLAB, StateTypes.EXPOSED_CUT_COPPER_SLAB, StateTypes.CUT_COPPER_SLAB, StateTypes.WAXED_OXIDIZED_CUT_COPPER_SLAB, StateTypes.MUD_BRICK_SLAB);
BlockTags.STAIRS.addTag(BlockTags.WOODEN_STAIRS).add(StateTypes.BAMBOO_MOSAIC_STAIRS, StateTypes.COBBLESTONE_STAIRS, StateTypes.SANDSTONE_STAIRS, StateTypes.NETHER_BRICK_STAIRS, StateTypes.STONE_BRICK_STAIRS, StateTypes.BRICK_STAIRS, StateTypes.PURPUR_STAIRS, StateTypes.QUARTZ_STAIRS, StateTypes.RED_SANDSTONE_STAIRS, StateTypes.PRISMARINE_BRICK_STAIRS, StateTypes.PRISMARINE_STAIRS, StateTypes.DARK_PRISMARINE_STAIRS, StateTypes.POLISHED_GRANITE_STAIRS, StateTypes.SMOOTH_RED_SANDSTONE_STAIRS, StateTypes.MOSSY_STONE_BRICK_STAIRS, StateTypes.POLISHED_DIORITE_STAIRS, StateTypes.MOSSY_COBBLESTONE_STAIRS, StateTypes.END_STONE_BRICK_STAIRS, StateTypes.STONE_STAIRS, StateTypes.SMOOTH_SANDSTONE_STAIRS, StateTypes.SMOOTH_QUARTZ_STAIRS, StateTypes.GRANITE_STAIRS, StateTypes.ANDESITE_STAIRS, StateTypes.RED_NETHER_BRICK_STAIRS, StateTypes.POLISHED_ANDESITE_STAIRS, StateTypes.DIORITE_STAIRS, StateTypes.BLACKSTONE_STAIRS, StateTypes.POLISHED_BLACKSTONE_BRICK_STAIRS, StateTypes.POLISHED_BLACKSTONE_STAIRS, StateTypes.COBBLED_DEEPSLATE_STAIRS, StateTypes.POLISHED_DEEPSLATE_STAIRS, StateTypes.DEEPSLATE_TILE_STAIRS, StateTypes.DEEPSLATE_BRICK_STAIRS, StateTypes.OXIDIZED_CUT_COPPER_STAIRS, StateTypes.WEATHERED_CUT_COPPER_STAIRS, StateTypes.EXPOSED_CUT_COPPER_STAIRS, StateTypes.CUT_COPPER_STAIRS, StateTypes.WAXED_WEATHERED_CUT_COPPER_STAIRS, StateTypes.WAXED_EXPOSED_CUT_COPPER_STAIRS, StateTypes.WAXED_CUT_COPPER_STAIRS, StateTypes.WAXED_OXIDIZED_CUT_COPPER_STAIRS, StateTypes.MUD_BRICK_STAIRS);
BlockTags.SLABS.addTag(BlockTags.WOODEN_SLABS).add(StateTypes.BAMBOO_MOSAIC_SLAB, StateTypes.STONE_SLAB, StateTypes.SMOOTH_STONE_SLAB, StateTypes.STONE_BRICK_SLAB, StateTypes.SANDSTONE_SLAB, StateTypes.PURPUR_SLAB, StateTypes.QUARTZ_SLAB, StateTypes.RED_SANDSTONE_SLAB, StateTypes.BRICK_SLAB, StateTypes.COBBLESTONE_SLAB, StateTypes.NETHER_BRICK_SLAB, StateTypes.PETRIFIED_OAK_SLAB, StateTypes.PRISMARINE_SLAB, StateTypes.PRISMARINE_BRICK_SLAB, StateTypes.DARK_PRISMARINE_SLAB, StateTypes.POLISHED_GRANITE_SLAB, StateTypes.SMOOTH_RED_SANDSTONE_SLAB, StateTypes.MOSSY_STONE_BRICK_SLAB, StateTypes.POLISHED_DIORITE_SLAB, StateTypes.MOSSY_COBBLESTONE_SLAB, StateTypes.END_STONE_BRICK_SLAB, StateTypes.SMOOTH_SANDSTONE_SLAB, StateTypes.SMOOTH_QUARTZ_SLAB, StateTypes.GRANITE_SLAB, StateTypes.ANDESITE_SLAB, StateTypes.RED_NETHER_BRICK_SLAB, StateTypes.POLISHED_ANDESITE_SLAB, StateTypes.DIORITE_SLAB, StateTypes.CUT_SANDSTONE_SLAB, StateTypes.CUT_RED_SANDSTONE_SLAB, StateTypes.BLACKSTONE_SLAB, StateTypes.POLISHED_BLACKSTONE_BRICK_SLAB, StateTypes.POLISHED_BLACKSTONE_SLAB, StateTypes.COBBLED_DEEPSLATE_SLAB, StateTypes.POLISHED_DEEPSLATE_SLAB, StateTypes.DEEPSLATE_TILE_SLAB, StateTypes.DEEPSLATE_BRICK_SLAB, StateTypes.WAXED_WEATHERED_CUT_COPPER_SLAB, StateTypes.WAXED_EXPOSED_CUT_COPPER_SLAB, StateTypes.WAXED_CUT_COPPER_SLAB, StateTypes.OXIDIZED_CUT_COPPER_SLAB, StateTypes.WEATHERED_CUT_COPPER_SLAB, StateTypes.EXPOSED_CUT_COPPER_SLAB, StateTypes.CUT_COPPER_SLAB, StateTypes.WAXED_OXIDIZED_CUT_COPPER_SLAB, StateTypes.MUD_BRICK_SLAB);
BlockTags.WALLS.add(StateTypes.COBBLESTONE_WALL, StateTypes.MOSSY_COBBLESTONE_WALL, StateTypes.BRICK_WALL, StateTypes.PRISMARINE_WALL, StateTypes.RED_SANDSTONE_WALL, StateTypes.MOSSY_STONE_BRICK_WALL, StateTypes.GRANITE_WALL, StateTypes.STONE_BRICK_WALL, StateTypes.NETHER_BRICK_WALL, StateTypes.ANDESITE_WALL, StateTypes.RED_NETHER_BRICK_WALL, StateTypes.SANDSTONE_WALL, StateTypes.END_STONE_BRICK_WALL, StateTypes.DIORITE_WALL, StateTypes.BLACKSTONE_WALL, StateTypes.POLISHED_BLACKSTONE_BRICK_WALL, StateTypes.POLISHED_BLACKSTONE_WALL, StateTypes.COBBLED_DEEPSLATE_WALL, StateTypes.POLISHED_DEEPSLATE_WALL, StateTypes.DEEPSLATE_TILE_WALL, StateTypes.DEEPSLATE_BRICK_WALL, StateTypes.MUD_BRICK_WALL);
BlockTags.CORAL_PLANTS.add(StateTypes.TUBE_CORAL, StateTypes.BRAIN_CORAL, StateTypes.BUBBLE_CORAL, StateTypes.FIRE_CORAL, StateTypes.HORN_CORAL);
BlockTags.CORALS.addTag(BlockTags.CORAL_PLANTS).add(StateTypes.TUBE_CORAL_FAN, StateTypes.BRAIN_CORAL_FAN, StateTypes.BUBBLE_CORAL_FAN, StateTypes.FIRE_CORAL_FAN, StateTypes.HORN_CORAL_FAN);
BlockTags.WALL_CORALS.add(StateTypes.TUBE_CORAL_WALL_FAN, StateTypes.BRAIN_CORAL_WALL_FAN, StateTypes.BUBBLE_CORAL_WALL_FAN, StateTypes.FIRE_CORAL_WALL_FAN, StateTypes.HORN_CORAL_WALL_FAN);
BlockTags.SAND.add(StateTypes.SAND, StateTypes.RED_SAND);
BlockTags.SAND.add(StateTypes.SAND, StateTypes.RED_SAND, StateTypes.SUSPICIOUS_SAND);
BlockTags.SMELTS_TO_GLASS.add(StateTypes.SAND, StateTypes.RED_SAND);
BlockTags.RAILS.add(StateTypes.RAIL, StateTypes.POWERED_RAIL, StateTypes.DETECTOR_RAIL, StateTypes.ACTIVATOR_RAIL);
BlockTags.CORAL_BLOCKS.add(StateTypes.TUBE_CORAL_BLOCK, StateTypes.BRAIN_CORAL_BLOCK, StateTypes.BUBBLE_CORAL_BLOCK, StateTypes.FIRE_CORAL_BLOCK, StateTypes.HORN_CORAL_BLOCK);
BlockTags.ICE.add(StateTypes.ICE, StateTypes.PACKED_ICE, StateTypes.BLUE_ICE, StateTypes.FROSTED_ICE);
BlockTags.VALID_SPAWN.add(StateTypes.GRASS_BLOCK, StateTypes.PODZOL);
BlockTags.LEAVES.add(StateTypes.JUNGLE_LEAVES, StateTypes.OAK_LEAVES, StateTypes.SPRUCE_LEAVES, StateTypes.DARK_OAK_LEAVES, StateTypes.ACACIA_LEAVES, StateTypes.BIRCH_LEAVES, StateTypes.AZALEA_LEAVES, StateTypes.FLOWERING_AZALEA_LEAVES, StateTypes.MANGROVE_LEAVES);
BlockTags.LEAVES.add(StateTypes.JUNGLE_LEAVES, StateTypes.OAK_LEAVES, StateTypes.SPRUCE_LEAVES, StateTypes.DARK_OAK_LEAVES, StateTypes.ACACIA_LEAVES, StateTypes.BIRCH_LEAVES, StateTypes.AZALEA_LEAVES, StateTypes.FLOWERING_AZALEA_LEAVES, StateTypes.MANGROVE_LEAVES, StateTypes.CHERRY_LEAVES);
BlockTags.IMPERMEABLE.add(StateTypes.GLASS, StateTypes.WHITE_STAINED_GLASS, StateTypes.ORANGE_STAINED_GLASS, StateTypes.MAGENTA_STAINED_GLASS, StateTypes.LIGHT_BLUE_STAINED_GLASS, StateTypes.YELLOW_STAINED_GLASS, StateTypes.LIME_STAINED_GLASS, StateTypes.PINK_STAINED_GLASS, StateTypes.GRAY_STAINED_GLASS, StateTypes.LIGHT_GRAY_STAINED_GLASS, StateTypes.CYAN_STAINED_GLASS, StateTypes.PURPLE_STAINED_GLASS, StateTypes.BLUE_STAINED_GLASS, StateTypes.BROWN_STAINED_GLASS, StateTypes.GREEN_STAINED_GLASS, StateTypes.RED_STAINED_GLASS, StateTypes.BLACK_STAINED_GLASS, StateTypes.TINTED_GLASS);
BlockTags.WOODEN_TRAPDOORS.add(StateTypes.ACACIA_TRAPDOOR, StateTypes.BIRCH_TRAPDOOR, StateTypes.DARK_OAK_TRAPDOOR, StateTypes.JUNGLE_TRAPDOOR, StateTypes.OAK_TRAPDOOR, StateTypes.SPRUCE_TRAPDOOR, StateTypes.CRIMSON_TRAPDOOR, StateTypes.WARPED_TRAPDOOR, StateTypes.MANGROVE_TRAPDOOR);
BlockTags.WOODEN_TRAPDOORS.add(StateTypes.ACACIA_TRAPDOOR, StateTypes.BIRCH_TRAPDOOR, StateTypes.DARK_OAK_TRAPDOOR, StateTypes.JUNGLE_TRAPDOOR, StateTypes.OAK_TRAPDOOR, StateTypes.SPRUCE_TRAPDOOR, StateTypes.CRIMSON_TRAPDOOR, StateTypes.WARPED_TRAPDOOR, StateTypes.MANGROVE_TRAPDOOR, StateTypes.BAMBOO_TRAPDOOR, StateTypes.CHERRY_TRAPDOOR);
BlockTags.TRAPDOORS.addTag(BlockTags.WOODEN_TRAPDOORS).add(StateTypes.IRON_TRAPDOOR);
BlockTags.UNDERWATER_BONEMEALS.add(StateTypes.SEAGRASS).addTag(BlockTags.CORALS).addTag(BlockTags.WALL_CORALS);
BlockTags.BAMBOO_PLANTABLE_ON.addTag(BlockTags.SAND).addTag(BlockTags.DIRT).add(StateTypes.BAMBOO, StateTypes.BAMBOO_SAPLING, StateTypes.GRAVEL);
BlockTags.STANDING_SIGNS.add(StateTypes.OAK_SIGN, StateTypes.SPRUCE_SIGN, StateTypes.BIRCH_SIGN, StateTypes.ACACIA_SIGN, StateTypes.JUNGLE_SIGN, StateTypes.DARK_OAK_SIGN, StateTypes.CRIMSON_SIGN, StateTypes.WARPED_SIGN, StateTypes.MANGROVE_SIGN);
BlockTags.WALL_SIGNS.add(StateTypes.OAK_WALL_SIGN, StateTypes.SPRUCE_WALL_SIGN, StateTypes.BIRCH_WALL_SIGN, StateTypes.ACACIA_WALL_SIGN, StateTypes.JUNGLE_WALL_SIGN, StateTypes.DARK_OAK_WALL_SIGN, StateTypes.CRIMSON_WALL_SIGN, StateTypes.WARPED_WALL_SIGN, StateTypes.MANGROVE_WALL_SIGN);
BlockTags.BAMBOO_PLANTABLE_ON.addTag(BlockTags.SAND).addTag(BlockTags.DIRT).add(StateTypes.BAMBOO, StateTypes.BAMBOO_SAPLING, StateTypes.GRAVEL, StateTypes.SUSPICIOUS_GRAVEL);
BlockTags.STANDING_SIGNS.add(StateTypes.OAK_SIGN, StateTypes.SPRUCE_SIGN, StateTypes.BIRCH_SIGN, StateTypes.ACACIA_SIGN, StateTypes.JUNGLE_SIGN, StateTypes.DARK_OAK_SIGN, StateTypes.CRIMSON_SIGN, StateTypes.WARPED_SIGN, StateTypes.MANGROVE_SIGN, StateTypes.BAMBOO_SIGN, StateTypes.CHERRY_SIGN);
BlockTags.WALL_SIGNS.add(StateTypes.OAK_WALL_SIGN, StateTypes.SPRUCE_WALL_SIGN, StateTypes.BIRCH_WALL_SIGN, StateTypes.ACACIA_WALL_SIGN, StateTypes.JUNGLE_WALL_SIGN, StateTypes.DARK_OAK_WALL_SIGN, StateTypes.CRIMSON_WALL_SIGN, StateTypes.WARPED_WALL_SIGN, StateTypes.MANGROVE_WALL_SIGN, StateTypes.BAMBOO_WALL_SIGN, StateTypes.CHERRY_WALL_SIGN);
BlockTags.SIGNS.addTag(BlockTags.STANDING_SIGNS).addTag(BlockTags.WALL_SIGNS);
BlockTags.CEILING_HANGING_SIGNS.add(StateTypes.OAK_HANGING_SIGN, StateTypes.SPRUCE_HANGING_SIGN, StateTypes.BIRCH_HANGING_SIGN, StateTypes.ACACIA_HANGING_SIGN, StateTypes.JUNGLE_HANGING_SIGN, StateTypes.DARK_OAK_HANGING_SIGN, StateTypes.CRIMSON_HANGING_SIGN, StateTypes.WARPED_HANGING_SIGN, StateTypes.MANGROVE_HANGING_SIGN, StateTypes.BAMBOO_HANGING_SIGN, StateTypes.CHERRY_HANGING_SIGN);
BlockTags.WALL_HANGING_SIGNS.add(StateTypes.OAK_WALL_HANGING_SIGN, StateTypes.SPRUCE_WALL_HANGING_SIGN, StateTypes.BIRCH_WALL_HANGING_SIGN, StateTypes.ACACIA_WALL_HANGING_SIGN, StateTypes.JUNGLE_WALL_HANGING_SIGN, StateTypes.DARK_OAK_WALL_HANGING_SIGN, StateTypes.MANGROVE_WALL_HANGING_SIGN, StateTypes.CRIMSON_WALL_HANGING_SIGN, StateTypes.WARPED_WALL_HANGING_SIGN, StateTypes.BAMBOO_WALL_HANGING_SIGN, StateTypes.CHERRY_WALL_HANGING_SIGN);
BlockTags.ALL_HANGING_SIGNS.addTag(BlockTags.CEILING_HANGING_SIGNS).addTag(BlockTags.WALL_HANGING_SIGNS);
BlockTags.ALL_SIGNS.addTag(BlockTags.SIGNS).addTag(BlockTags.ALL_HANGING_SIGNS);
BlockTags.BEDS.add(StateTypes.RED_BED, StateTypes.BLACK_BED, StateTypes.BLUE_BED, StateTypes.BROWN_BED, StateTypes.CYAN_BED, StateTypes.GRAY_BED, StateTypes.GREEN_BED, StateTypes.LIGHT_BLUE_BED, StateTypes.LIGHT_GRAY_BED, StateTypes.LIME_BED, StateTypes.MAGENTA_BED, StateTypes.ORANGE_BED, StateTypes.PINK_BED, StateTypes.PURPLE_BED, StateTypes.WHITE_BED, StateTypes.YELLOW_BED);
BlockTags.FENCES.addTag(BlockTags.WOODEN_FENCES).add(StateTypes.NETHER_BRICK_FENCE);
BlockTags.DRAGON_IMMUNE.add(StateTypes.BARRIER, StateTypes.BEDROCK, StateTypes.END_PORTAL, StateTypes.END_PORTAL_FRAME, StateTypes.END_GATEWAY, StateTypes.COMMAND_BLOCK, StateTypes.REPEATING_COMMAND_BLOCK, StateTypes.CHAIN_COMMAND_BLOCK, StateTypes.STRUCTURE_BLOCK, StateTypes.JIGSAW, StateTypes.MOVING_PISTON, StateTypes.OBSIDIAN, StateTypes.CRYING_OBSIDIAN, StateTypes.END_STONE, StateTypes.IRON_BARS, StateTypes.RESPAWN_ANCHOR, StateTypes.REINFORCED_DEEPSLATE);
// TODO: this.tag(BlockTags.DRAGON_TRANSPARENT).add(Blocks.LIGHT).addTag(BlockTags.FIRE);
BlockTags.WITHER_IMMUNE.add(StateTypes.BARRIER, StateTypes.BEDROCK, StateTypes.END_PORTAL, StateTypes.END_PORTAL_FRAME, StateTypes.END_GATEWAY, StateTypes.COMMAND_BLOCK, StateTypes.REPEATING_COMMAND_BLOCK, StateTypes.CHAIN_COMMAND_BLOCK, StateTypes.STRUCTURE_BLOCK, StateTypes.JIGSAW, StateTypes.MOVING_PISTON, StateTypes.LIGHT, StateTypes.REINFORCED_DEEPSLATE); // TODO: 1.17/1.18 doesn't have light (does it matter?)
BlockTags.DRAGON_TRANSPARENT.add(StateTypes.LIGHT).addTag(BlockTags.FIRE);
BlockTags.WITHER_IMMUNE.add(StateTypes.BARRIER, StateTypes.BEDROCK, StateTypes.END_PORTAL, StateTypes.END_PORTAL_FRAME, StateTypes.END_GATEWAY, StateTypes.COMMAND_BLOCK, StateTypes.REPEATING_COMMAND_BLOCK, StateTypes.CHAIN_COMMAND_BLOCK, StateTypes.STRUCTURE_BLOCK, StateTypes.JIGSAW, StateTypes.MOVING_PISTON, StateTypes.LIGHT, StateTypes.REINFORCED_DEEPSLATE);
BlockTags.WITHER_SUMMON_BASE_BLOCKS.add(StateTypes.SOUL_SAND, StateTypes.SOUL_SOIL);
BlockTags.TALL_FLOWERS.add(StateTypes.SUNFLOWER, StateTypes.LILAC, StateTypes.PEONY, StateTypes.ROSE_BUSH);
BlockTags.TALL_FLOWERS.add(StateTypes.SUNFLOWER, StateTypes.LILAC, StateTypes.PEONY, StateTypes.ROSE_BUSH, StateTypes.PITCHER_PLANT);
BlockTags.FLOWERS.addTag(BlockTags.SMALL_FLOWERS).addTag(BlockTags.TALL_FLOWERS).add(StateTypes.FLOWERING_AZALEA_LEAVES, StateTypes.FLOWERING_AZALEA, StateTypes.MANGROVE_PROPAGULE);
BlockTags.BEEHIVES.add(StateTypes.BEE_NEST, StateTypes.BEEHIVE);
BlockTags.CROPS.add(StateTypes.BEETROOTS, StateTypes.CARROTS, StateTypes.POTATOES, StateTypes.WHEAT, StateTypes.MELON_STEM, StateTypes.PUMPKIN_STEM);
BlockTags.CROPS.add(StateTypes.BEETROOTS, StateTypes.CARROTS, StateTypes.POTATOES, StateTypes.WHEAT, StateTypes.MELON_STEM, StateTypes.PUMPKIN_STEM, StateTypes.TORCHFLOWER_CROP, StateTypes.PITCHER_CROP);
BlockTags.BEE_GROWABLES.addTag(BlockTags.CROPS).add(StateTypes.SWEET_BERRY_BUSH).add(StateTypes.CAVE_VINES).add(StateTypes.CAVE_VINES_PLANT);
BlockTags.SHULKER_BOXES.add(StateTypes.SHULKER_BOX, StateTypes.BLACK_SHULKER_BOX, StateTypes.BLUE_SHULKER_BOX, StateTypes.BROWN_SHULKER_BOX, StateTypes.CYAN_SHULKER_BOX, StateTypes.GRAY_SHULKER_BOX, StateTypes.GREEN_SHULKER_BOX, StateTypes.LIGHT_BLUE_SHULKER_BOX, StateTypes.LIGHT_GRAY_SHULKER_BOX, StateTypes.LIME_SHULKER_BOX, StateTypes.MAGENTA_SHULKER_BOX, StateTypes.ORANGE_SHULKER_BOX, StateTypes.PINK_SHULKER_BOX, StateTypes.PURPLE_SHULKER_BOX, StateTypes.RED_SHULKER_BOX, StateTypes.WHITE_SHULKER_BOX, StateTypes.YELLOW_SHULKER_BOX);
BlockTags.PORTALS.add(StateTypes.NETHER_PORTAL, StateTypes.END_PORTAL, StateTypes.END_GATEWAY);
@@ -249,6 +297,7 @@ public class BlockTags {
BlockTags.SOUL_SPEED_BLOCKS.add(StateTypes.SOUL_SAND, StateTypes.SOUL_SOIL);
BlockTags.WALL_POST_OVERRIDE.add(StateTypes.TORCH, StateTypes.SOUL_TORCH, StateTypes.REDSTONE_TORCH, StateTypes.TRIPWIRE).addTag(BlockTags.SIGNS).addTag(BlockTags.BANNERS).addTag(BlockTags.PRESSURE_PLATES);
BlockTags.CLIMBABLE.add(StateTypes.LADDER, StateTypes.VINE, StateTypes.SCAFFOLDING, StateTypes.WEEPING_VINES, StateTypes.WEEPING_VINES_PLANT, StateTypes.TWISTING_VINES, StateTypes.TWISTING_VINES_PLANT, StateTypes.CAVE_VINES, StateTypes.CAVE_VINES_PLANT);
BlockTags.FALL_DAMAGE_RESETTING.addTag(BlockTags.CLIMBABLE).add(StateTypes.SWEET_BERRY_BUSH, StateTypes.COBWEB);
BlockTags.PIGLIN_REPELLENTS.add(StateTypes.SOUL_FIRE).add(StateTypes.SOUL_TORCH).add(StateTypes.SOUL_LANTERN).add(StateTypes.SOUL_WALL_TORCH).add(StateTypes.SOUL_CAMPFIRE);
BlockTags.HOGLIN_REPELLENTS.add(StateTypes.WARPED_FUNGUS).add(StateTypes.POTTED_WARPED_FUNGUS).add(StateTypes.NETHER_PORTAL).add(StateTypes.RESPAWN_ANCHOR);
BlockTags.GOLD_ORES.add(StateTypes.GOLD_ORE, StateTypes.NETHER_GOLD_ORE, StateTypes.DEEPSLATE_GOLD_ORE);
@@ -260,12 +309,11 @@ public class BlockTags {
BlockTags.COPPER_ORES.add(StateTypes.COPPER_ORE, StateTypes.DEEPSLATE_COPPER_ORE);
BlockTags.LAPIS_ORES.add(StateTypes.LAPIS_ORE, StateTypes.DEEPSLATE_LAPIS_ORE);
BlockTags.SOUL_FIRE_BASE_BLOCKS.add(StateTypes.SOUL_SAND, StateTypes.SOUL_SOIL);
BlockTags.NON_FLAMMABLE_WOOD.add(StateTypes.WARPED_STEM, StateTypes.STRIPPED_WARPED_STEM, StateTypes.WARPED_HYPHAE, StateTypes.STRIPPED_WARPED_HYPHAE, StateTypes.CRIMSON_STEM, StateTypes.STRIPPED_CRIMSON_STEM, StateTypes.CRIMSON_HYPHAE, StateTypes.STRIPPED_CRIMSON_HYPHAE, StateTypes.CRIMSON_PLANKS, StateTypes.WARPED_PLANKS, StateTypes.CRIMSON_SLAB, StateTypes.WARPED_SLAB, StateTypes.CRIMSON_PRESSURE_PLATE, StateTypes.WARPED_PRESSURE_PLATE, StateTypes.CRIMSON_FENCE, StateTypes.WARPED_FENCE, StateTypes.CRIMSON_TRAPDOOR, StateTypes.WARPED_TRAPDOOR, StateTypes.CRIMSON_FENCE_GATE, StateTypes.WARPED_FENCE_GATE, StateTypes.CRIMSON_STAIRS, StateTypes.WARPED_STAIRS, StateTypes.CRIMSON_BUTTON, StateTypes.WARPED_BUTTON, StateTypes.CRIMSON_DOOR, StateTypes.WARPED_DOOR, StateTypes.CRIMSON_SIGN, StateTypes.WARPED_SIGN, StateTypes.CRIMSON_WALL_SIGN, StateTypes.WARPED_WALL_SIGN);
BlockTags.STRIDER_WARM_BLOCKS.add(StateTypes.LAVA);
BlockTags.CAMPFIRES.add(StateTypes.CAMPFIRE, StateTypes.SOUL_CAMPFIRE);
BlockTags.GUARDED_BY_PIGLINS.add(StateTypes.GOLD_BLOCK, StateTypes.BARREL, StateTypes.CHEST, StateTypes.ENDER_CHEST, StateTypes.GILDED_BLACKSTONE, StateTypes.TRAPPED_CHEST, StateTypes.RAW_GOLD_BLOCK).addTag(BlockTags.SHULKER_BOXES).addTag(BlockTags.GOLD_ORES);
BlockTags.PREVENT_MOB_SPAWNING_INSIDE.addTag(BlockTags.RAILS);
BlockTags.FENCE_GATES.add(StateTypes.ACACIA_FENCE_GATE, StateTypes.BIRCH_FENCE_GATE, StateTypes.DARK_OAK_FENCE_GATE, StateTypes.JUNGLE_FENCE_GATE, StateTypes.OAK_FENCE_GATE, StateTypes.SPRUCE_FENCE_GATE, StateTypes.CRIMSON_FENCE_GATE, StateTypes.WARPED_FENCE_GATE, StateTypes.MANGROVE_FENCE_GATE);
BlockTags.FENCE_GATES.add(StateTypes.ACACIA_FENCE_GATE, StateTypes.BIRCH_FENCE_GATE, StateTypes.DARK_OAK_FENCE_GATE, StateTypes.JUNGLE_FENCE_GATE, StateTypes.OAK_FENCE_GATE, StateTypes.SPRUCE_FENCE_GATE, StateTypes.CRIMSON_FENCE_GATE, StateTypes.WARPED_FENCE_GATE, StateTypes.MANGROVE_FENCE_GATE, StateTypes.BAMBOO_FENCE_GATE, StateTypes.CHERRY_FENCE_GATE);
BlockTags.UNSTABLE_BOTTOM_CENTER.addTag(BlockTags.FENCE_GATES);
BlockTags.MUSHROOM_GROW_BLOCK.add(StateTypes.MYCELIUM).add(StateTypes.PODZOL).add(StateTypes.CRIMSON_NYLIUM).add(StateTypes.WARPED_NYLIUM);
BlockTags.INFINIBURN_OVERWORLD.add(StateTypes.NETHERRACK, StateTypes.MAGMA_BLOCK);
@@ -275,26 +323,29 @@ public class BlockTags {
BlockTags.DEEPSLATE_ORE_REPLACEABLES.add(StateTypes.DEEPSLATE).add(StateTypes.TUFF);
BlockTags.BASE_STONE_OVERWORLD.add(StateTypes.STONE).add(StateTypes.GRANITE).add(StateTypes.DIORITE).add(StateTypes.ANDESITE).add(StateTypes.TUFF).add(StateTypes.DEEPSLATE);
BlockTags.BASE_STONE_NETHER.add(StateTypes.NETHERRACK).add(StateTypes.BASALT).add(StateTypes.BLACKSTONE);
// TODO: this.tag(BlockTags.OVERWORLD_CARVER_REPLACEABLES).addTag(BlockTags.BASE_STONE_OVERWORLD).addTag(BlockTags.DIRT).addTag(BlockTags.SAND).addTag(BlockTags.TERRACOTTA).addTag(BlockTags.IRON_ORES).addTag(BlockTags.COPPER_ORES).add(Blocks.WATER, Blocks.GRAVEL, Blocks.SANDSTONE, Blocks.RED_SANDSTONE, Blocks.CALCITE, Blocks.SNOW, Blocks.PACKED_ICE, Blocks.RAW_IRON_BLOCK, Blocks.RAW_COPPER_BLOCK);
// this.tag(BlockTags.NETHER_CARVER_REPLACEABLES).addTag(BlockTags.BASE_STONE_OVERWORLD).addTag(BlockTags.BASE_STONE_NETHER).addTag(BlockTags.DIRT).addTag(BlockTags.NYLIUM).addTag(BlockTags.WART_BLOCKS).add(Blocks.SOUL_SAND, Blocks.SOUL_SOIL);
BlockTags.OVERWORLD_CARVER_REPLACEABLES.addTag(BlockTags.BASE_STONE_OVERWORLD).addTag(BlockTags.DIRT).addTag(BlockTags.SAND).addTag(BlockTags.TERRACOTTA).addTag(BlockTags.IRON_ORES).addTag(BlockTags.COPPER_ORES).add(StateTypes.WATER, StateTypes.GRAVEL, StateTypes.SUSPICIOUS_GRAVEL, StateTypes.SANDSTONE, StateTypes.RED_SANDSTONE, StateTypes.CALCITE, StateTypes.SNOW, StateTypes.PACKED_ICE, StateTypes.RAW_IRON_BLOCK, StateTypes.RAW_COPPER_BLOCK);
BlockTags.NETHER_CARVER_REPLACEABLES.addTag(BlockTags.BASE_STONE_OVERWORLD).addTag(BlockTags.BASE_STONE_NETHER).addTag(BlockTags.DIRT).addTag(BlockTags.NYLIUM).addTag(BlockTags.WART_BLOCKS).add(StateTypes.SOUL_SAND, StateTypes.SOUL_SOIL);
BlockTags.CANDLES.add(StateTypes.CANDLE, StateTypes.WHITE_CANDLE, StateTypes.ORANGE_CANDLE, StateTypes.MAGENTA_CANDLE, StateTypes.LIGHT_BLUE_CANDLE, StateTypes.YELLOW_CANDLE, StateTypes.LIME_CANDLE, StateTypes.PINK_CANDLE, StateTypes.GRAY_CANDLE, StateTypes.LIGHT_GRAY_CANDLE, StateTypes.CYAN_CANDLE, StateTypes.PURPLE_CANDLE, StateTypes.BLUE_CANDLE, StateTypes.BROWN_CANDLE, StateTypes.GREEN_CANDLE, StateTypes.RED_CANDLE, StateTypes.BLACK_CANDLE);
BlockTags.CANDLE_CAKES.add(StateTypes.CANDLE_CAKE, StateTypes.WHITE_CANDLE_CAKE, StateTypes.ORANGE_CANDLE_CAKE, StateTypes.MAGENTA_CANDLE_CAKE, StateTypes.LIGHT_BLUE_CANDLE_CAKE, StateTypes.YELLOW_CANDLE_CAKE, StateTypes.LIME_CANDLE_CAKE, StateTypes.PINK_CANDLE_CAKE, StateTypes.GRAY_CANDLE_CAKE, StateTypes.LIGHT_GRAY_CANDLE_CAKE, StateTypes.CYAN_CANDLE_CAKE, StateTypes.PURPLE_CANDLE_CAKE, StateTypes.BLUE_CANDLE_CAKE, StateTypes.BROWN_CANDLE_CAKE, StateTypes.GREEN_CANDLE_CAKE, StateTypes.RED_CANDLE_CAKE, StateTypes.BLACK_CANDLE_CAKE);
BlockTags.CRYSTAL_SOUND_BLOCKS.add(StateTypes.AMETHYST_BLOCK, StateTypes.BUDDING_AMETHYST);
BlockTags.CAULDRONS.add(StateTypes.CAULDRON, StateTypes.WATER_CAULDRON, StateTypes.LAVA_CAULDRON, StateTypes.POWDER_SNOW_CAULDRON);
BlockTags.INSIDE_STEP_SOUND_BLOCKS.add(StateTypes.SNOW, StateTypes.POWDER_SNOW, StateTypes.SCULK_VEIN);
BlockTags.DRIPSTONE_REPLACEABLE.addTag(BlockTags.BASE_STONE_OVERWORLD).add(StateTypes.DIRT);
BlockTags.INSIDE_STEP_SOUND_BLOCKS.add(StateTypes.POWDER_SNOW, StateTypes.SCULK_VEIN, StateTypes.GLOW_LICHEN, StateTypes.LILY_PAD, StateTypes.SMALL_AMETHYST_BUD, StateTypes.PINK_PETALS);
BlockTags.COMBINATION_STEP_SOUND_BLOCKS.addTag(BlockTags.WOOL_CARPETS).add(StateTypes.MOSS_CARPET, StateTypes.SNOW, StateTypes.NETHER_SPROUTS, StateTypes.WARPED_ROOTS, StateTypes.CRIMSON_ROOTS);
BlockTags.DRIPSTONE_REPLACEABLE.addTag(BlockTags.BASE_STONE_OVERWORLD);
BlockTags.CAVE_VINES.add(StateTypes.CAVE_VINES_PLANT).add(StateTypes.CAVE_VINES);
BlockTags.MOSS_REPLACEABLE.addTag(BlockTags.BASE_STONE_OVERWORLD).addTag(BlockTags.CAVE_VINES).addTag(BlockTags.DIRT);
BlockTags.LUSH_GROUND_REPLACEABLE.addTag(BlockTags.MOSS_REPLACEABLE).add(StateTypes.CLAY).add(StateTypes.GRAVEL).add(StateTypes.SAND);
BlockTags.AZALEA_ROOT_REPLACEABLE.addTag(BlockTags.LUSH_GROUND_REPLACEABLE).addTag(BlockTags.TERRACOTTA).add(StateTypes.RED_SAND);
BlockTags.AZALEA_ROOT_REPLACEABLE.addTag(BlockTags.BASE_STONE_OVERWORLD).addTag(BlockTags.DIRT).addTag(BlockTags.TERRACOTTA).add(StateTypes.RED_SAND).add(StateTypes.CLAY).add(StateTypes.GRAVEL).add(StateTypes.SAND).add(StateTypes.SNOW_BLOCK).add(StateTypes.POWDER_SNOW);
BlockTags.SMALL_DRIPLEAF_PLACEABLE.add(StateTypes.CLAY).add(StateTypes.MOSS_BLOCK);
BlockTags.BIG_DRIPLEAF_PLACEABLE.addTag(BlockTags.SMALL_DRIPLEAF_PLACEABLE).addTag(BlockTags.DIRT).add(StateTypes.FARMLAND);
BlockTags.OCCLUDES_VIBRATION_SIGNALS.addTag(BlockTags.WOOL);
BlockTags.DAMPENS_VIBRATIONS.addTag(BlockTags.WOOL).addTag(BlockTags.WOOL_CARPETS);
BlockTags.SNOW.add(StateTypes.SNOW, StateTypes.SNOW_BLOCK, StateTypes.POWDER_SNOW);
BlockTags.MINEABLE_WITH_AXE.add(StateTypes.NOTE_BLOCK, StateTypes.ATTACHED_MELON_STEM, StateTypes.ATTACHED_PUMPKIN_STEM, StateTypes.AZALEA, StateTypes.BAMBOO, StateTypes.BARREL, StateTypes.BEE_NEST, StateTypes.BEEHIVE, StateTypes.BEETROOTS, StateTypes.BIG_DRIPLEAF_STEM, StateTypes.BIG_DRIPLEAF, StateTypes.BOOKSHELF, StateTypes.BROWN_MUSHROOM_BLOCK, StateTypes.BROWN_MUSHROOM, StateTypes.CAMPFIRE, StateTypes.CARROTS, StateTypes.CARTOGRAPHY_TABLE, StateTypes.CARVED_PUMPKIN, StateTypes.CAVE_VINES_PLANT, StateTypes.CAVE_VINES, StateTypes.CHEST, StateTypes.CHORUS_FLOWER, StateTypes.CHORUS_PLANT, StateTypes.COCOA, StateTypes.COMPOSTER, StateTypes.CRAFTING_TABLE, StateTypes.CRIMSON_FUNGUS, StateTypes.DAYLIGHT_DETECTOR, StateTypes.DEAD_BUSH, StateTypes.FERN, StateTypes.FLETCHING_TABLE, StateTypes.GLOW_LICHEN, StateTypes.GRASS, StateTypes.HANGING_ROOTS, StateTypes.JACK_O_LANTERN, StateTypes.JUKEBOX, StateTypes.LADDER, StateTypes.LARGE_FERN, StateTypes.LECTERN, StateTypes.LILY_PAD, StateTypes.LOOM, StateTypes.MELON_STEM, StateTypes.MELON, StateTypes.MUSHROOM_STEM, StateTypes.NETHER_WART, StateTypes.POTATOES, StateTypes.PUMPKIN_STEM, StateTypes.PUMPKIN, StateTypes.RED_MUSHROOM_BLOCK, StateTypes.RED_MUSHROOM, StateTypes.SCAFFOLDING, StateTypes.SMALL_DRIPLEAF, StateTypes.SMITHING_TABLE, StateTypes.SOUL_CAMPFIRE, StateTypes.SPORE_BLOSSOM, StateTypes.SUGAR_CANE, StateTypes.SWEET_BERRY_BUSH, StateTypes.TALL_GRASS, StateTypes.TRAPPED_CHEST, StateTypes.TWISTING_VINES_PLANT, StateTypes.TWISTING_VINES, StateTypes.VINE, StateTypes.WARPED_FUNGUS, StateTypes.WEEPING_VINES_PLANT, StateTypes.WEEPING_VINES, StateTypes.WHEAT).addTag(BlockTags.BANNERS).addTag(BlockTags.FENCE_GATES).addTag(BlockTags.LOGS).addTag(BlockTags.PLANKS).addTag(BlockTags.SAPLINGS).addTag(BlockTags.SIGNS).addTag(BlockTags.WOODEN_BUTTONS).addTag(BlockTags.WOODEN_DOORS).addTag(BlockTags.WOODEN_FENCES).addTag(BlockTags.WOODEN_PRESSURE_PLATES).addTag(BlockTags.WOODEN_SLABS).addTag(BlockTags.WOODEN_STAIRS).addTag(BlockTags.WOODEN_TRAPDOORS).add(StateTypes.MANGROVE_ROOTS);
BlockTags.MINEABLE_WITH_HOE.add(StateTypes.NETHER_WART_BLOCK, StateTypes.WARPED_WART_BLOCK, StateTypes.HAY_BLOCK, StateTypes.DRIED_KELP_BLOCK, StateTypes.TARGET, StateTypes.SHROOMLIGHT, StateTypes.SPONGE, StateTypes.WET_SPONGE, StateTypes.JUNGLE_LEAVES, StateTypes.OAK_LEAVES, StateTypes.SPRUCE_LEAVES, StateTypes.DARK_OAK_LEAVES, StateTypes.ACACIA_LEAVES, StateTypes.BIRCH_LEAVES, StateTypes.AZALEA_LEAVES, StateTypes.FLOWERING_AZALEA_LEAVES, StateTypes.SCULK_SENSOR, StateTypes.MOSS_BLOCK, StateTypes.MOSS_CARPET, StateTypes.MANGROVE_LEAVES, StateTypes.SCULK, StateTypes.SCULK_CATALYST, StateTypes.SCULK_VEIN, StateTypes.SCULK_SHRIEKER);
BlockTags.MINEABLE_WITH_PICKAXE.add(StateTypes.STONE, StateTypes.GRANITE, StateTypes.POLISHED_GRANITE, StateTypes.DIORITE, StateTypes.POLISHED_DIORITE, StateTypes.ANDESITE, StateTypes.POLISHED_ANDESITE, StateTypes.COBBLESTONE, StateTypes.GOLD_ORE, StateTypes.DEEPSLATE_GOLD_ORE, StateTypes.IRON_ORE, StateTypes.DEEPSLATE_IRON_ORE, StateTypes.COAL_ORE, StateTypes.DEEPSLATE_COAL_ORE, StateTypes.NETHER_GOLD_ORE, StateTypes.LAPIS_ORE, StateTypes.DEEPSLATE_LAPIS_ORE, StateTypes.LAPIS_BLOCK, StateTypes.DISPENSER, StateTypes.SANDSTONE, StateTypes.CHISELED_SANDSTONE, StateTypes.CUT_SANDSTONE, StateTypes.GOLD_BLOCK, StateTypes.IRON_BLOCK, StateTypes.BRICKS, StateTypes.MOSSY_COBBLESTONE, StateTypes.OBSIDIAN, StateTypes.SPAWNER, StateTypes.DIAMOND_ORE, StateTypes.DEEPSLATE_DIAMOND_ORE, StateTypes.DIAMOND_BLOCK, StateTypes.FURNACE, StateTypes.COBBLESTONE_STAIRS, StateTypes.STONE_PRESSURE_PLATE, StateTypes.IRON_DOOR, StateTypes.REDSTONE_ORE, StateTypes.DEEPSLATE_REDSTONE_ORE, StateTypes.NETHERRACK, StateTypes.BASALT, StateTypes.POLISHED_BASALT, StateTypes.STONE_BRICKS, StateTypes.MOSSY_STONE_BRICKS, StateTypes.CRACKED_STONE_BRICKS, StateTypes.CHISELED_STONE_BRICKS, StateTypes.IRON_BARS, StateTypes.CHAIN, StateTypes.BRICK_STAIRS, StateTypes.STONE_BRICK_STAIRS, StateTypes.NETHER_BRICKS, StateTypes.NETHER_BRICK_FENCE, StateTypes.NETHER_BRICK_STAIRS, StateTypes.ENCHANTING_TABLE, StateTypes.BREWING_STAND, StateTypes.END_STONE, StateTypes.SANDSTONE_STAIRS, StateTypes.EMERALD_ORE, StateTypes.DEEPSLATE_EMERALD_ORE, StateTypes.ENDER_CHEST, StateTypes.EMERALD_BLOCK, StateTypes.LIGHT_WEIGHTED_PRESSURE_PLATE, StateTypes.HEAVY_WEIGHTED_PRESSURE_PLATE, StateTypes.REDSTONE_BLOCK, StateTypes.NETHER_QUARTZ_ORE, StateTypes.HOPPER, StateTypes.QUARTZ_BLOCK, StateTypes.CHISELED_QUARTZ_BLOCK, StateTypes.QUARTZ_PILLAR, StateTypes.QUARTZ_STAIRS, StateTypes.DROPPER, StateTypes.WHITE_TERRACOTTA, StateTypes.ORANGE_TERRACOTTA, StateTypes.MAGENTA_TERRACOTTA, StateTypes.LIGHT_BLUE_TERRACOTTA, StateTypes.YELLOW_TERRACOTTA, StateTypes.LIME_TERRACOTTA, StateTypes.PINK_TERRACOTTA, StateTypes.GRAY_TERRACOTTA, StateTypes.LIGHT_GRAY_TERRACOTTA, StateTypes.CYAN_TERRACOTTA, StateTypes.PURPLE_TERRACOTTA, StateTypes.BLUE_TERRACOTTA, StateTypes.BROWN_TERRACOTTA, StateTypes.GREEN_TERRACOTTA, StateTypes.RED_TERRACOTTA, StateTypes.BLACK_TERRACOTTA, StateTypes.IRON_TRAPDOOR, StateTypes.PRISMARINE, StateTypes.PRISMARINE_BRICKS, StateTypes.DARK_PRISMARINE, StateTypes.PRISMARINE_STAIRS, StateTypes.PRISMARINE_BRICK_STAIRS, StateTypes.DARK_PRISMARINE_STAIRS, StateTypes.PRISMARINE_SLAB, StateTypes.PRISMARINE_BRICK_SLAB, StateTypes.DARK_PRISMARINE_SLAB, StateTypes.TERRACOTTA, StateTypes.COAL_BLOCK, StateTypes.RED_SANDSTONE, StateTypes.CHISELED_RED_SANDSTONE, StateTypes.CUT_RED_SANDSTONE, StateTypes.RED_SANDSTONE_STAIRS, StateTypes.STONE_SLAB, StateTypes.SMOOTH_STONE_SLAB, StateTypes.SANDSTONE_SLAB, StateTypes.CUT_SANDSTONE_SLAB, StateTypes.PETRIFIED_OAK_SLAB, StateTypes.COBBLESTONE_SLAB, StateTypes.BRICK_SLAB, StateTypes.STONE_BRICK_SLAB, StateTypes.NETHER_BRICK_SLAB, StateTypes.QUARTZ_SLAB, StateTypes.RED_SANDSTONE_SLAB, StateTypes.CUT_RED_SANDSTONE_SLAB, StateTypes.PURPUR_SLAB, StateTypes.SMOOTH_STONE, StateTypes.SMOOTH_SANDSTONE, StateTypes.SMOOTH_QUARTZ, StateTypes.SMOOTH_RED_SANDSTONE, StateTypes.PURPUR_BLOCK, StateTypes.PURPUR_PILLAR, StateTypes.PURPUR_STAIRS, StateTypes.END_STONE_BRICKS, StateTypes.MAGMA_BLOCK, StateTypes.RED_NETHER_BRICKS, StateTypes.BONE_BLOCK, StateTypes.OBSERVER, StateTypes.WHITE_GLAZED_TERRACOTTA, StateTypes.ORANGE_GLAZED_TERRACOTTA, StateTypes.MAGENTA_GLAZED_TERRACOTTA, StateTypes.LIGHT_BLUE_GLAZED_TERRACOTTA, StateTypes.YELLOW_GLAZED_TERRACOTTA, StateTypes.LIME_GLAZED_TERRACOTTA, StateTypes.PINK_GLAZED_TERRACOTTA, StateTypes.GRAY_GLAZED_TERRACOTTA, StateTypes.LIGHT_GRAY_GLAZED_TERRACOTTA, StateTypes.CYAN_GLAZED_TERRACOTTA, StateTypes.PURPLE_GLAZED_TERRACOTTA, StateTypes.BLUE_GLAZED_TERRACOTTA, StateTypes.BROWN_GLAZED_TERRACOTTA, StateTypes.GREEN_GLAZED_TERRACOTTA, StateTypes.RED_GLAZED_TERRACOTTA, StateTypes.BLACK_GLAZED_TERRACOTTA, StateTypes.WHITE_CONCRETE, StateTypes.ORANGE_CONCRETE, StateTypes.MAGENTA_CONCRETE, StateTypes.LIGHT_BLUE_CONCRETE, StateTypes.YELLOW_CONCRETE, StateTypes.LIME_CONCRETE, StateTypes.PINK_CONCRETE, StateTypes.GRAY_CONCRETE, StateTypes.LIGHT_GRAY_CONCRETE, StateTypes.CYAN_CONCRETE, StateTypes.PURPLE_CONCRETE, StateTypes.BLUE_CONCRETE, StateTypes.BROWN_CONCRETE, StateTypes.GREEN_CONCRETE, StateTypes.RED_CONCRETE, StateTypes.BLACK_CONCRETE, StateTypes.DEAD_TUBE_CORAL_BLOCK, StateTypes.DEAD_BRAIN_CORAL_BLOCK, StateTypes.DEAD_BUBBLE_CORAL_BLOCK, StateTypes.DEAD_FIRE_CORAL_BLOCK, StateTypes.DEAD_HORN_CORAL_BLOCK, StateTypes.TUBE_CORAL_BLOCK, StateTypes.BRAIN_CORAL_BLOCK, StateTypes.BUBBLE_CORAL_BLOCK, StateTypes.FIRE_CORAL_BLOCK, StateTypes.HORN_CORAL_BLOCK, StateTypes.DEAD_TUBE_CORAL, StateTypes.DEAD_BRAIN_CORAL, StateTypes.DEAD_BUBBLE_CORAL, StateTypes.DEAD_FIRE_CORAL, StateTypes.DEAD_HORN_CORAL, StateTypes.DEADLine truncated
BlockTags.MINEABLE_WITH_SHOVEL.add(StateTypes.CLAY, StateTypes.DIRT, StateTypes.COARSE_DIRT, StateTypes.PODZOL, StateTypes.FARMLAND, StateTypes.GRASS_BLOCK, StateTypes.GRAVEL, StateTypes.MYCELIUM, StateTypes.SAND, StateTypes.RED_SAND, StateTypes.SNOW_BLOCK, StateTypes.SNOW, StateTypes.SOUL_SAND, StateTypes.DIRT_PATH, StateTypes.WHITE_CONCRETE_POWDER, StateTypes.ORANGE_CONCRETE_POWDER, StateTypes.MAGENTA_CONCRETE_POWDER, StateTypes.LIGHT_BLUE_CONCRETE_POWDER, StateTypes.YELLOW_CONCRETE_POWDER, StateTypes.LIME_CONCRETE_POWDER, StateTypes.PINK_CONCRETE_POWDER, StateTypes.GRAY_CONCRETE_POWDER, StateTypes.LIGHT_GRAY_CONCRETE_POWDER, StateTypes.CYAN_CONCRETE_POWDER, StateTypes.PURPLE_CONCRETE_POWDER, StateTypes.BLUE_CONCRETE_POWDER, StateTypes.BROWN_CONCRETE_POWDER, StateTypes.GREEN_CONCRETE_POWDER, StateTypes.RED_CONCRETE_POWDER, StateTypes.BLACK_CONCRETE_POWDER, StateTypes.SOUL_SOIL, StateTypes.ROOTED_DIRT, StateTypes.MUDDY_MANGROVE_ROOTS, StateTypes.MUD);
BlockTags.MINEABLE_WITH_AXE.add(StateTypes.NOTE_BLOCK, StateTypes.ATTACHED_MELON_STEM, StateTypes.ATTACHED_PUMPKIN_STEM, StateTypes.AZALEA, StateTypes.BAMBOO, StateTypes.BARREL, StateTypes.BEE_NEST, StateTypes.BEEHIVE, StateTypes.BEETROOTS, StateTypes.BIG_DRIPLEAF_STEM, StateTypes.BIG_DRIPLEAF, StateTypes.BOOKSHELF, StateTypes.BROWN_MUSHROOM_BLOCK, StateTypes.BROWN_MUSHROOM, StateTypes.CAMPFIRE, StateTypes.CARROTS, StateTypes.CARTOGRAPHY_TABLE, StateTypes.CARVED_PUMPKIN, StateTypes.CAVE_VINES_PLANT, StateTypes.CAVE_VINES, StateTypes.CHEST, StateTypes.CHORUS_FLOWER, StateTypes.CHORUS_PLANT, StateTypes.COCOA, StateTypes.COMPOSTER, StateTypes.CRAFTING_TABLE, StateTypes.CRIMSON_FUNGUS, StateTypes.DAYLIGHT_DETECTOR, StateTypes.DEAD_BUSH, StateTypes.FERN, StateTypes.FLETCHING_TABLE, StateTypes.GLOW_LICHEN, StateTypes.GRASS, StateTypes.HANGING_ROOTS, StateTypes.JACK_O_LANTERN, StateTypes.JUKEBOX, StateTypes.LADDER, StateTypes.LARGE_FERN, StateTypes.LECTERN, StateTypes.LILY_PAD, StateTypes.LOOM, StateTypes.MELON_STEM, StateTypes.MELON, StateTypes.MUSHROOM_STEM, StateTypes.NETHER_WART, StateTypes.POTATOES, StateTypes.PUMPKIN_STEM, StateTypes.PUMPKIN, StateTypes.RED_MUSHROOM_BLOCK, StateTypes.RED_MUSHROOM, StateTypes.SCAFFOLDING, StateTypes.SMALL_DRIPLEAF, StateTypes.SMITHING_TABLE, StateTypes.SOUL_CAMPFIRE, StateTypes.SPORE_BLOSSOM, StateTypes.SUGAR_CANE, StateTypes.SWEET_BERRY_BUSH, StateTypes.TALL_GRASS, StateTypes.TRAPPED_CHEST, StateTypes.TWISTING_VINES_PLANT, StateTypes.TWISTING_VINES, StateTypes.VINE, StateTypes.WARPED_FUNGUS, StateTypes.WEEPING_VINES_PLANT, StateTypes.WEEPING_VINES, StateTypes.WHEAT).addTag(BlockTags.BANNERS).addTag(BlockTags.FENCE_GATES).addTag(BlockTags.LOGS).addTag(BlockTags.PLANKS).addTag(BlockTags.SAPLINGS).addTag(BlockTags.SIGNS).addTag(BlockTags.WOODEN_BUTTONS).addTag(BlockTags.WOODEN_DOORS).addTag(BlockTags.WOODEN_FENCES).addTag(BlockTags.WOODEN_PRESSURE_PLATES).addTag(BlockTags.WOODEN_SLABS).addTag(BlockTags.WOODEN_STAIRS).addTag(BlockTags.WOODEN_TRAPDOORS).add(StateTypes.MANGROVE_ROOTS).addTag(ALL_HANGING_SIGNS).add(StateTypes.BAMBOO_MOSAIC, StateTypes.BAMBOO_MOSAIC_SLAB, StateTypes.BAMBOO_MOSAIC_STAIRS).addTag(BAMBOO_BLOCKS).add(StateTypes.CHISELED_BOOKSHELF);
BlockTags.MINEABLE_WITH_HOE.add(StateTypes.NETHER_WART_BLOCK, StateTypes.WARPED_WART_BLOCK, StateTypes.HAY_BLOCK, StateTypes.DRIED_KELP_BLOCK, StateTypes.TARGET, StateTypes.SHROOMLIGHT, StateTypes.SPONGE, StateTypes.WET_SPONGE, StateTypes.JUNGLE_LEAVES, StateTypes.OAK_LEAVES, StateTypes.SPRUCE_LEAVES, StateTypes.DARK_OAK_LEAVES, StateTypes.ACACIA_LEAVES, StateTypes.BIRCH_LEAVES, StateTypes.AZALEA_LEAVES, StateTypes.FLOWERING_AZALEA_LEAVES, StateTypes.MANGROVE_LEAVES, StateTypes.SCULK_SENSOR, StateTypes.MOSS_BLOCK, StateTypes.MOSS_CARPET, StateTypes.SCULK, StateTypes.SCULK_CATALYST, StateTypes.SCULK_VEIN, StateTypes.SCULK_SHRIEKER, StateTypes.PINK_PETALS, StateTypes.CHERRY_LEAVES);
BlockTags.MINEABLE_WITH_PICKAXE.add(StateTypes.STONE, StateTypes.GRANITE, StateTypes.POLISHED_GRANITE, StateTypes.DIORITE, StateTypes.POLISHED_DIORITE, StateTypes.ANDESITE, StateTypes.POLISHED_ANDESITE, StateTypes.COBBLESTONE, StateTypes.GOLD_ORE, StateTypes.DEEPSLATE_GOLD_ORE, StateTypes.IRON_ORE, StateTypes.DEEPSLATE_IRON_ORE, StateTypes.COAL_ORE, StateTypes.DEEPSLATE_COAL_ORE, StateTypes.NETHER_GOLD_ORE, StateTypes.LAPIS_ORE, StateTypes.DEEPSLATE_LAPIS_ORE, StateTypes.LAPIS_BLOCK, StateTypes.DISPENSER, StateTypes.SANDSTONE, StateTypes.CHISELED_SANDSTONE, StateTypes.CUT_SANDSTONE, StateTypes.GOLD_BLOCK, StateTypes.IRON_BLOCK, StateTypes.BRICKS, StateTypes.MOSSY_COBBLESTONE, StateTypes.OBSIDIAN, StateTypes.SPAWNER, StateTypes.DIAMOND_ORE, StateTypes.DEEPSLATE_DIAMOND_ORE, StateTypes.DIAMOND_BLOCK, StateTypes.FURNACE, StateTypes.COBBLESTONE_STAIRS, StateTypes.STONE_PRESSURE_PLATE, StateTypes.IRON_DOOR, StateTypes.REDSTONE_ORE, StateTypes.DEEPSLATE_REDSTONE_ORE, StateTypes.NETHERRACK, StateTypes.BASALT, StateTypes.POLISHED_BASALT, StateTypes.STONE_BRICKS, StateTypes.MOSSY_STONE_BRICKS, StateTypes.CRACKED_STONE_BRICKS, StateTypes.CHISELED_STONE_BRICKS, StateTypes.IRON_BARS, StateTypes.CHAIN, StateTypes.BRICK_STAIRS, StateTypes.STONE_BRICK_STAIRS, StateTypes.NETHER_BRICKS, StateTypes.NETHER_BRICK_FENCE, StateTypes.NETHER_BRICK_STAIRS, StateTypes.ENCHANTING_TABLE, StateTypes.BREWING_STAND, StateTypes.END_STONE, StateTypes.SANDSTONE_STAIRS, StateTypes.EMERALD_ORE, StateTypes.DEEPSLATE_EMERALD_ORE, StateTypes.ENDER_CHEST, StateTypes.EMERALD_BLOCK, StateTypes.LIGHT_WEIGHTED_PRESSURE_PLATE, StateTypes.HEAVY_WEIGHTED_PRESSURE_PLATE, StateTypes.REDSTONE_BLOCK, StateTypes.NETHER_QUARTZ_ORE, StateTypes.HOPPER, StateTypes.QUARTZ_BLOCK, StateTypes.CHISELED_QUARTZ_BLOCK, StateTypes.QUARTZ_PILLAR, StateTypes.QUARTZ_STAIRS, StateTypes.DROPPER, StateTypes.WHITE_TERRACOTTA, StateTypes.ORANGE_TERRACOTTA, StateTypes.MAGENTA_TERRACOTTA, StateTypes.LIGHT_BLUE_TERRACOTTA, StateTypes.YELLOW_TERRACOTTA, StateTypes.LIME_TERRACOTTA, StateTypes.PINK_TERRACOTTA, StateTypes.GRAY_TERRACOTTA, StateTypes.LIGHT_GRAY_TERRACOTTA, StateTypes.CYAN_TERRACOTTA, StateTypes.PURPLE_TERRACOTTA, StateTypes.BLUE_TERRACOTTA, StateTypes.BROWN_TERRACOTTA, StateTypes.GREEN_TERRACOTTA, StateTypes.RED_TERRACOTTA, StateTypes.BLACK_TERRACOTTA, StateTypes.IRON_TRAPDOOR, StateTypes.PRISMARINE, StateTypes.PRISMARINE_BRICKS, StateTypes.DARK_PRISMARINE, StateTypes.PRISMARINE_STAIRS, StateTypes.PRISMARINE_BRICK_STAIRS, StateTypes.DARK_PRISMARINE_STAIRS, StateTypes.PRISMARINE_SLAB, StateTypes.PRISMARINE_BRICK_SLAB, StateTypes.DARK_PRISMARINE_SLAB, StateTypes.TERRACOTTA, StateTypes.COAL_BLOCK, StateTypes.RED_SANDSTONE, StateTypes.CHISELED_RED_SANDSTONE, StateTypes.CUT_RED_SANDSTONE, StateTypes.RED_SANDSTONE_STAIRS, StateTypes.STONE_SLAB, StateTypes.SMOOTH_STONE_SLAB, StateTypes.SANDSTONE_SLAB, StateTypes.CUT_SANDSTONE_SLAB, StateTypes.PETRIFIED_OAK_SLAB, StateTypes.COBBLESTONE_SLAB, StateTypes.BRICK_SLAB, StateTypes.STONE_BRICK_SLAB, StateTypes.NETHER_BRICK_SLAB, StateTypes.QUARTZ_SLAB, StateTypes.RED_SANDSTONE_SLAB, StateTypes.CUT_RED_SANDSTONE_SLAB, StateTypes.PURPUR_SLAB, StateTypes.SMOOTH_STONE, StateTypes.SMOOTH_SANDSTONE, StateTypes.SMOOTH_QUARTZ, StateTypes.SMOOTH_RED_SANDSTONE, StateTypes.PURPUR_BLOCK, StateTypes.PURPUR_PILLAR, StateTypes.PURPUR_STAIRS, StateTypes.END_STONE_BRICKS, StateTypes.MAGMA_BLOCK, StateTypes.RED_NETHER_BRICKS, StateTypes.BONE_BLOCK, StateTypes.OBSERVER, StateTypes.WHITE_GLAZED_TERRACOTTA, StateTypes.ORANGE_GLAZED_TERRACOTTA, StateTypes.MAGENTA_GLAZED_TERRACOTTA, StateTypes.LIGHT_BLUE_GLAZED_TERRACOTTA, StateTypes.YELLOW_GLAZED_TERRACOTTA, StateTypes.LIME_GLAZED_TERRACOTTA, StateTypes.PINK_GLAZED_TERRACOTTA, StateTypes.GRAY_GLAZED_TERRACOTTA, StateTypes.LIGHT_GRAY_GLAZED_TERRACOTTA, StateTypes.CYAN_GLAZED_TERRACOTTA, StateTypes.PURPLE_GLAZED_TERRACOTTA, StateTypes.BLUE_GLAZED_TERRACOTTA, StateTypes.BROWN_GLAZED_TERRACOTTA, StateTypes.GREEN_GLAZED_TERRACOTTA, StateTypes.RED_GLAZED_TERRACOTTA, StateTypes.BLACK_GLAZED_TERRACOTTA, StateTypes.WHITE_CONCRETE, StateTypes.ORANGE_CONCRETE, StateTypes.MAGENTA_CONCRETE, StateTypes.LIGHT_BLUE_CONCRETE, StateTypes.YELLOW_CONCRETE, StateTypes.LIME_CONCRETE, StateTypes.PINK_CONCRETE, StateTypes.GRAY_CONCRETE, StateTypes.LIGHT_GRAY_CONCRETE, StateTypes.CYAN_CONCRETE, StateTypes.PURPLE_CONCRETE, StateTypes.BLUE_CONCRETE, StateTypes.BROWN_CONCRETE, StateTypes.GREEN_CONCRETE, StateTypes.RED_CONCRETE, StateTypes.BLACK_CONCRETE, StateTypes.DEAD_TUBE_CORAL_BLOCK, StateTypes.DEAD_BRAIN_CORAL_BLOCK, StateTypes.DEAD_BUBBLE_CORAL_BLOCK, StateTypes.DEAD_FIRE_CORAL_BLOCK, StateTypes.DEAD_HORN_CORAL_BLOCK, StateTypes.TUBE_CORAL_BLOCK, StateTypes.BRAIN_CORAL_BLOCK, StateTypes.BUBBLE_CORAL_BLOCK, StateTypes.FIRE_CORAL_BLOCK, StateTypes.HORN_CORAL_BLOCK, StateTypes.DEAD_TUBE_CORAL, StateTypes.DEAD_BRAIN_CORAL, StateTypes.DEAD_BUBBLE_CORAL, StateTypes.DEAD_FIRE_CORAL, StateTypes.DEAD_HORN_CORAL, StateTypes.DEADLine truncated
BlockTags.MINEABLE_WITH_SHOVEL.add(StateTypes.CLAY, StateTypes.DIRT, StateTypes.COARSE_DIRT, StateTypes.PODZOL, StateTypes.FARMLAND, StateTypes.GRASS_BLOCK, StateTypes.GRAVEL, StateTypes.MYCELIUM, StateTypes.SAND, StateTypes.RED_SAND, StateTypes.SNOW_BLOCK, StateTypes.SNOW, StateTypes.SOUL_SAND, StateTypes.DIRT_PATH, StateTypes.WHITE_CONCRETE_POWDER, StateTypes.ORANGE_CONCRETE_POWDER, StateTypes.MAGENTA_CONCRETE_POWDER, StateTypes.LIGHT_BLUE_CONCRETE_POWDER, StateTypes.YELLOW_CONCRETE_POWDER, StateTypes.LIME_CONCRETE_POWDER, StateTypes.PINK_CONCRETE_POWDER, StateTypes.GRAY_CONCRETE_POWDER, StateTypes.LIGHT_GRAY_CONCRETE_POWDER, StateTypes.CYAN_CONCRETE_POWDER, StateTypes.PURPLE_CONCRETE_POWDER, StateTypes.BLUE_CONCRETE_POWDER, StateTypes.BROWN_CONCRETE_POWDER, StateTypes.GREEN_CONCRETE_POWDER, StateTypes.RED_CONCRETE_POWDER, StateTypes.BLACK_CONCRETE_POWDER, StateTypes.SOUL_SOIL, StateTypes.ROOTED_DIRT, StateTypes.MUDDY_MANGROVE_ROOTS, StateTypes.MUD, StateTypes.SUSPICIOUS_SAND, StateTypes.SUSPICIOUS_GRAVEL);
BlockTags.SWORD_EFFICIENT.addTag(BlockTags.LEAVES).addTag(BlockTags.SAPLINGS).addTag(BlockTags.SMALL_FLOWERS).addTag(BlockTags.CROPS).add(StateTypes.GRASS, StateTypes.FERN, StateTypes.DEAD_BUSH, StateTypes.VINE, StateTypes.GLOW_LICHEN, StateTypes.SUNFLOWER, StateTypes.LILAC, StateTypes.ROSE_BUSH, StateTypes.PEONY, StateTypes.TALL_GRASS, StateTypes.LARGE_FERN, StateTypes.HANGING_ROOTS, StateTypes.PITCHER_PLANT, StateTypes.BROWN_MUSHROOM, StateTypes.RED_MUSHROOM, StateTypes.SUGAR_CANE, StateTypes.PUMPKIN, StateTypes.CARVED_PUMPKIN, StateTypes.JACK_O_LANTERN, StateTypes.MELON, StateTypes.ATTACHED_PUMPKIN_STEM, StateTypes.ATTACHED_MELON_STEM, StateTypes.LILY_PAD, StateTypes.COCOA, StateTypes.PITCHER_CROP, StateTypes.SWEET_BERRY_BUSH, StateTypes.CAVE_VINES, StateTypes.CAVE_VINES_PLANT, StateTypes.SPORE_BLOSSOM, StateTypes.MOSS_CARPET, StateTypes.PINK_PETALS, StateTypes.BIG_DRIPLEAF, StateTypes.BIG_DRIPLEAF_STEM, StateTypes.SMALL_DRIPLEAF, StateTypes.NETHER_WART, StateTypes.WARPED_FUNGUS, StateTypes.WARPED_ROOTS, StateTypes.NETHER_SPROUTS, StateTypes.CRIMSON_FUNGUS, StateTypes.WEEPING_VINES, StateTypes.WEEPING_VINES_PLANT, StateTypes.TWISTING_VINES, StateTypes.TWISTING_VINES_PLANT, StateTypes.CRIMSON_ROOTS, StateTypes.CHORUS_PLANT, StateTypes.CHORUS_FLOWER);
BlockTags.NEEDS_DIAMOND_TOOL.add(StateTypes.OBSIDIAN, StateTypes.CRYING_OBSIDIAN, StateTypes.NETHERITE_BLOCK, StateTypes.RESPAWN_ANCHOR, StateTypes.ANCIENT_DEBRIS);
BlockTags.NEEDS_IRON_TOOL.add(StateTypes.DIAMOND_BLOCK, StateTypes.DIAMOND_ORE, StateTypes.DEEPSLATE_DIAMOND_ORE, StateTypes.EMERALD_ORE, StateTypes.DEEPSLATE_EMERALD_ORE, StateTypes.EMERALD_BLOCK, StateTypes.GOLD_BLOCK, StateTypes.RAW_GOLD_BLOCK, StateTypes.GOLD_ORE, StateTypes.DEEPSLATE_GOLD_ORE, StateTypes.REDSTONE_ORE, StateTypes.DEEPSLATE_REDSTONE_ORE);
BlockTags.NEEDS_STONE_TOOL.add(StateTypes.IRON_BLOCK, StateTypes.RAW_IRON_BLOCK, StateTypes.IRON_ORE, StateTypes.DEEPSLATE_IRON_ORE, StateTypes.LAPIS_BLOCK, StateTypes.LAPIS_ORE, StateTypes.DEEPSLATE_LAPIS_ORE, StateTypes.COPPER_BLOCK, StateTypes.RAW_COPPER_BLOCK, StateTypes.COPPER_ORE, StateTypes.DEEPSLATE_COPPER_ORE, StateTypes.CUT_COPPER_SLAB, StateTypes.CUT_COPPER_STAIRS, StateTypes.CUT_COPPER, StateTypes.WEATHERED_COPPER, StateTypes.WEATHERED_CUT_COPPER_SLAB, StateTypes.WEATHERED_CUT_COPPER_STAIRS, StateTypes.WEATHERED_CUT_COPPER, StateTypes.OXIDIZED_COPPER, StateTypes.OXIDIZED_CUT_COPPER_SLAB, StateTypes.OXIDIZED_CUT_COPPER_STAIRS, StateTypes.OXIDIZED_CUT_COPPER, StateTypes.EXPOSED_COPPER, StateTypes.EXPOSED_CUT_COPPER_SLAB, StateTypes.EXPOSED_CUT_COPPER_STAIRS, StateTypes.EXPOSED_CUT_COPPER, StateTypes.WAXED_COPPER_BLOCK, StateTypes.WAXED_CUT_COPPER_SLAB, StateTypes.WAXED_CUT_COPPER_STAIRS, StateTypes.WAXED_CUT_COPPER, StateTypes.WAXED_WEATHERED_COPPER, StateTypes.WAXED_WEATHERED_CUT_COPPER_SLAB, StateTypes.WAXED_WEATHERED_CUT_COPPER_STAIRS, StateTypes.WAXED_WEATHERED_CUT_COPPER, StateTypes.WAXED_EXPOSED_COPPER, StateTypes.WAXED_EXPOSED_CUT_COPPER_SLAB, StateTypes.WAXED_EXPOSED_CUT_COPPER_STAIRS, StateTypes.WAXED_EXPOSED_CUT_COPPER, StateTypes.WAXED_OXIDIZED_COPPER, StateTypes.WAXED_OXIDIZED_CUT_COPPER_SLAB, StateTypes.WAXED_OXIDIZED_CUT_COPPER_STAIRS, StateTypes.WAXED_OXIDIZED_CUT_COPPER, StateTypes.LIGHTNING_ROD);
@@ -303,30 +354,40 @@ public class BlockTags {
BlockTags.GEODE_INVALID_BLOCKS.add(StateTypes.BEDROCK, StateTypes.WATER, StateTypes.LAVA, StateTypes.ICE, StateTypes.PACKED_ICE, StateTypes.BLUE_ICE);
BlockTags.ANIMALS_SPAWNABLE_ON.add(StateTypes.GRASS_BLOCK);
BlockTags.AXOLOTLS_SPAWNABLE_ON.add(StateTypes.CLAY);
BlockTags.GOATS_SPAWNABLE_ON.add(StateTypes.STONE, StateTypes.SNOW, StateTypes.POWDER_SNOW, StateTypes.SNOW_BLOCK, StateTypes.PACKED_ICE, StateTypes.GRAVEL);
BlockTags.GOATS_SPAWNABLE_ON.addTag(BlockTags.ANIMALS_SPAWNABLE_ON).add(StateTypes.STONE, StateTypes.SNOW, StateTypes.SNOW_BLOCK, StateTypes.PACKED_ICE, StateTypes.GRAVEL);
BlockTags.MOOSHROOMS_SPAWNABLE_ON.add(StateTypes.MYCELIUM);
BlockTags.PARROTS_SPAWNABLE_ON.add(StateTypes.GRASS_BLOCK, StateTypes.AIR).addTag(BlockTags.LEAVES).addTag(BlockTags.LOGS);
BlockTags.POLAR_BEARS_SPAWNABLE_ON_IN_FROZEN_OCEAN.add(StateTypes.ICE);
BlockTags.POLAR_BEARS_SPAWNABLE_ON_ALTERNATE.add(StateTypes.ICE);
BlockTags.RABBITS_SPAWNABLE_ON.add(StateTypes.GRASS_BLOCK, StateTypes.SNOW, StateTypes.SNOW_BLOCK, StateTypes.SAND);
BlockTags.FOXES_SPAWNABLE_ON.add(StateTypes.GRASS_BLOCK, StateTypes.SNOW, StateTypes.SNOW_BLOCK, StateTypes.PODZOL, StateTypes.COARSE_DIRT);
BlockTags.WOLVES_SPAWNABLE_ON.add(StateTypes.GRASS_BLOCK, StateTypes.SNOW, StateTypes.SNOW_BLOCK);
// TODO: this.tag(BlockTags.FROGS_SPAWNABLE_ON).add(Blocks.GRASS_BLOCK, Blocks.MUD, Blocks.MANGROVE_ROOTS, Blocks.MUDDY_MANGROVE_ROOTS);
BlockTags.FROGS_SPAWNABLE_ON.add(StateTypes.GRASS_BLOCK, StateTypes.MUD, StateTypes.MANGROVE_ROOTS, StateTypes.MUDDY_MANGROVE_ROOTS);
BlockTags.TERRACOTTA.add(StateTypes.TERRACOTTA, StateTypes.WHITE_TERRACOTTA, StateTypes.ORANGE_TERRACOTTA, StateTypes.MAGENTA_TERRACOTTA, StateTypes.LIGHT_BLUE_TERRACOTTA, StateTypes.YELLOW_TERRACOTTA, StateTypes.LIME_TERRACOTTA, StateTypes.PINK_TERRACOTTA, StateTypes.GRAY_TERRACOTTA, StateTypes.LIGHT_GRAY_TERRACOTTA, StateTypes.CYAN_TERRACOTTA, StateTypes.PURPLE_TERRACOTTA, StateTypes.BLUE_TERRACOTTA, StateTypes.BROWN_TERRACOTTA, StateTypes.GREEN_TERRACOTTA, StateTypes.RED_TERRACOTTA, StateTypes.BLACK_TERRACOTTA);
BlockTags.AZALEA_GROWS_ON.addTag(BlockTags.DIRT).addTag(BlockTags.SAND).addTag(BlockTags.TERRACOTTA).add(StateTypes.SNOW_BLOCK).add(StateTypes.POWDER_SNOW);
BlockTags.REPLACEABLE_PLANTS.add(StateTypes.GRASS, StateTypes.FERN, StateTypes.DEAD_BUSH, StateTypes.VINE, StateTypes.GLOW_LICHEN, StateTypes.SUNFLOWER, StateTypes.LILAC, StateTypes.ROSE_BUSH, StateTypes.PEONY, StateTypes.TALL_GRASS, StateTypes.LARGE_FERN, StateTypes.HANGING_ROOTS);
// TODO:
// this.tag(BlockTags.FROG_PREFER_JUMP_TO).add(Blocks.LILY_PAD, Blocks.BIG_DRIPLEAF);
// this.tag(BlockTags.SCULK_REPLACEABLE).addTag(BlockTags.BASE_STONE_OVERWORLD).addTag(BlockTags.DIRT).addTag(BlockTags.TERRACOTTA).addTag(BlockTags.NYLIUM).addTag(BlockTags.BASE_STONE_NETHER).addTag(BlockTags.SAND).add(Blocks.GRAVEL).add(Blocks.SOUL_SAND).add(Blocks.SOUL_SOIL).add(Blocks.CALCITE).add(Blocks.SMOOTH_BASALT).add(Blocks.CLAY).add(Blocks.DRIPSTONE_BLOCK).add(Blocks.END_STONE).add(Blocks.RED_SANDSTONE).add(Blocks.SANDSTONE);
// this.tag(BlockTags.SCULK_REPLACEABLE_WORLD_GEN).addTag(BlockTags.SCULK_REPLACEABLE).add(Blocks.DEEPSLATE_BRICKS).add(Blocks.DEEPSLATE_TILES).add(Blocks.COBBLED_DEEPSLATE).add(Blocks.CRACKED_DEEPSLATE_BRICKS).add(Blocks.CRACKED_DEEPSLATE_TILES).add(Blocks.POLISHED_DEEPSLATE);
// this.tag(BlockTags.CONVERTABLE_TO_MUD).add(Blocks.DIRT, Blocks.COARSE_DIRT, Blocks.ROOTED_DIRT);
// this.tag(BlockTags.ANCIENT_CITY_REPLACEABLE).add(Blocks.DEEPSLATE).add(Blocks.DEEPSLATE_BRICKS).add(Blocks.DEEPSLATE_TILES).add(Blocks.DEEPSLATE_BRICK_SLAB).add(Blocks.DEEPSLATE_TILE_SLAB).add(Blocks.DEEPSLATE_BRICK_STAIRS).add(Blocks.DEEPSLATE_TILE_WALL).add(Blocks.DEEPSLATE_BRICK_WALL).add(Blocks.COBBLED_DEEPSLATE).add(Blocks.CRACKED_DEEPSLATE_BRICKS).add(Blocks.CRACKED_DEEPSLATE_TILES).add(Blocks.GRAY_WOOL);
// this.tag(BlockTags.MANGROVE_LOGS_CAN_GROW_THROUGH).add(Blocks.MUD, Blocks.MUDDY_MANGROVE_ROOTS, Blocks.MANGROVE_ROOTS, Blocks.MANGROVE_LEAVES, Blocks.MANGROVE_LOG, Blocks.MANGROVE_PROPAGULE, Blocks.MOSS_CARPET, Blocks.VINE);
// this.tag(BlockTags.MANGROVE_ROOTS_CAN_GROW_THROUGH).add(Blocks.MUD, Blocks.MUDDY_MANGROVE_ROOTS, Blocks.MANGROVE_ROOTS, Blocks.MOSS_CARPET, Blocks.VINE, Blocks.MANGROVE_PROPAGULE, Blocks.SNOW);
// this.tag(BlockTags.DEAD_BUSH_MAY_PLACE_ON).addTag(BlockTags.SAND).addTag(BlockTags.TERRACOTTA).addTag(BlockTags.DIRT);
// this.tag(BlockTags.SNOW_LAYER_CANNOT_SURVIVE_ON).add(Blocks.ICE).add(Blocks.PACKED_ICE).add(Blocks.BARRIER);
// this.tag(BlockTags.SNOW_LAYER_CAN_SURVIVE_ON).add(Blocks.HONEY_BLOCK).add(Blocks.SOUL_SAND).add(Blocks.MUD);
// this.tag(BlockTags.COMPLETES_FIND_TREE_TUTORIAL).addTag(BlockTags.LOGS).addTag(BlockTags.LEAVES).addTag(BlockTags.WART_BLOCKS);
// this.tag(BlockTags.SNAPS_GOAT_HORN).addTag(BlockTags.OVERWORLD_NATURAL_LOGS).add(Blocks.STONE).add(Blocks.PACKED_ICE).add(Blocks.IRON_ORE).add(Blocks.COAL_ORE).add(Blocks.COPPER_ORE).add(Blocks.EMERALD_ORE);
BlockTags.REPLACEABLE_PLANTS.add(StateTypes.GRASS, StateTypes.FERN, StateTypes.DEAD_BUSH, StateTypes.VINE, StateTypes.GLOW_LICHEN, StateTypes.SUNFLOWER, StateTypes.LILAC, StateTypes.ROSE_BUSH, StateTypes.PEONY, StateTypes.TALL_GRASS, StateTypes.LARGE_FERN, StateTypes.HANGING_ROOTS, StateTypes.PITCHER_PLANT);
BlockTags.FROG_PREFER_JUMP_TO.add(StateTypes.LILY_PAD, StateTypes.BIG_DRIPLEAF);
BlockTags.SCULK_REPLACEABLE.addTag(BlockTags.BASE_STONE_OVERWORLD).addTag(BlockTags.DIRT).addTag(BlockTags.TERRACOTTA).addTag(BlockTags.NYLIUM).addTag(BlockTags.BASE_STONE_NETHER).addTag(BlockTags.SAND).add(StateTypes.GRAVEL).add(StateTypes.SOUL_SAND).add(StateTypes.SOUL_SOIL).add(StateTypes.CALCITE).add(StateTypes.SMOOTH_BASALT).add(StateTypes.CLAY).add(StateTypes.DRIPSTONE_BLOCK).add(StateTypes.END_STONE).add(StateTypes.RED_SANDSTONE).add(StateTypes.SANDSTONE);
BlockTags.SCULK_REPLACEABLE_WORLD_GEN.addTag(BlockTags.SCULK_REPLACEABLE).add(StateTypes.DEEPSLATE_BRICKS).add(StateTypes.DEEPSLATE_TILES).add(StateTypes.COBBLED_DEEPSLATE).add(StateTypes.CRACKED_DEEPSLATE_BRICKS).add(StateTypes.CRACKED_DEEPSLATE_TILES).add(StateTypes.POLISHED_DEEPSLATE);
BlockTags.VIBRATION_RESONATORS.add(StateTypes.AMETHYST_BLOCK);
BlockTags.CONVERTABLE_TO_MUD.add(StateTypes.DIRT, StateTypes.COARSE_DIRT, StateTypes.ROOTED_DIRT);
BlockTags.ANCIENT_CITY_REPLACEABLE.add(StateTypes.DEEPSLATE).add(StateTypes.DEEPSLATE_BRICKS).add(StateTypes.DEEPSLATE_TILES).add(StateTypes.DEEPSLATE_BRICK_SLAB).add(StateTypes.DEEPSLATE_TILE_SLAB).add(StateTypes.DEEPSLATE_BRICK_STAIRS).add(StateTypes.DEEPSLATE_TILE_WALL).add(StateTypes.DEEPSLATE_BRICK_WALL).add(StateTypes.COBBLED_DEEPSLATE).add(StateTypes.CRACKED_DEEPSLATE_BRICKS).add(StateTypes.CRACKED_DEEPSLATE_TILES).add(StateTypes.GRAY_WOOL);
BlockTags.MANGROVE_LOGS_CAN_GROW_THROUGH.add(StateTypes.MUD, StateTypes.MUDDY_MANGROVE_ROOTS, StateTypes.MANGROVE_ROOTS, StateTypes.MANGROVE_LEAVES, StateTypes.MANGROVE_LOG, StateTypes.MANGROVE_PROPAGULE, StateTypes.MOSS_CARPET, StateTypes.VINE);
BlockTags.MANGROVE_ROOTS_CAN_GROW_THROUGH.add(StateTypes.MUD, StateTypes.MUDDY_MANGROVE_ROOTS, StateTypes.MANGROVE_ROOTS, StateTypes.MOSS_CARPET, StateTypes.VINE, StateTypes.MANGROVE_PROPAGULE, StateTypes.SNOW);
BlockTags.DEAD_BUSH_MAY_PLACE_ON.addTag(BlockTags.SAND).addTag(BlockTags.TERRACOTTA).addTag(BlockTags.DIRT);
BlockTags.SNOW_LAYER_CANNOT_SURVIVE_ON.add(StateTypes.ICE).add(StateTypes.PACKED_ICE).add(StateTypes.BARRIER);
BlockTags.SNOW_LAYER_CAN_SURVIVE_ON.add(StateTypes.HONEY_BLOCK).add(StateTypes.SOUL_SAND).add(StateTypes.MUD);
BlockTags.COMPLETES_FIND_TREE_TUTORIAL.addTag(BlockTags.LOGS).addTag(BlockTags.LEAVES).addTag(BlockTags.WART_BLOCKS);
BlockTags.SNAPS_GOAT_HORN.addTag(BlockTags.OVERWORLD_NATURAL_LOGS).add(StateTypes.STONE).add(StateTypes.PACKED_ICE).add(StateTypes.IRON_ORE).add(StateTypes.COAL_ORE).add(StateTypes.COPPER_ORE).add(StateTypes.EMERALD_ORE);
BlockTags.INVALID_SPAWN_INSIDE.add(StateTypes.END_PORTAL, StateTypes.END_GATEWAY);
BlockTags.TRAIL_RUINS_REPLACEABLE.add(StateTypes.GRAVEL);
BlockTags.SNIFFER_DIGGABLE_BLOCK.add(StateTypes.DIRT, StateTypes.GRASS_BLOCK, StateTypes.PODZOL, StateTypes.COARSE_DIRT, StateTypes.ROOTED_DIRT, StateTypes.MOSS_BLOCK, StateTypes.MUD, StateTypes.MUDDY_MANGROVE_ROOTS);
BlockTags.SNIFFER_EGG_HATCH_BOOST.add(StateTypes.MOSS_BLOCK);
for (StateType value : StateTypes.values()) {
if (value.isReplaceable()) BlockTags.REPLACEABLE.add(value);
}
BlockTags.ENCHANTMENT_POWER_PROVIDER.add(StateTypes.BOOKSHELF);
BlockTags.ENCHANTMENT_POWER_TRANSMITTER.addTag(BlockTags.REPLACEABLE);
BlockTags.MAINTAINS_FARMLAND.add(StateTypes.PUMPKIN_STEM, StateTypes.ATTACHED_PUMPKIN_STEM, StateTypes.MELON_STEM, StateTypes.ATTACHED_MELON_STEM, StateTypes.BEETROOTS, StateTypes.CARROTS, StateTypes.POTATOES, StateTypes.TORCHFLOWER_CROP, StateTypes.TORCHFLOWER, StateTypes.PITCHER_CROP, StateTypes.WHEAT);
// Unofficial blocks to help packetevents users
BlockTags.GLASS_BLOCKS.add(StateTypes.GLASS, StateTypes.WHITE_STAINED_GLASS, StateTypes.ORANGE_STAINED_GLASS, StateTypes.MAGENTA_STAINED_GLASS, StateTypes.LIGHT_BLUE_STAINED_GLASS, StateTypes.YELLOW_STAINED_GLASS, StateTypes.LIME_STAINED_GLASS, StateTypes.PINK_STAINED_GLASS, StateTypes.GRAY_STAINED_GLASS, StateTypes.LIGHT_GRAY_STAINED_GLASS, StateTypes.CYAN_STAINED_GLASS, StateTypes.PURPLE_STAINED_GLASS, StateTypes.BLUE_STAINED_GLASS, StateTypes.BROWN_STAINED_GLASS, StateTypes.GREEN_STAINED_GLASS, StateTypes.RED_STAINED_GLASS, StateTypes.BLACK_STAINED_GLASS, StateTypes.TINTED_GLASS);
BlockTags.GLASS_PANES.add(StateTypes.GLASS_PANE, StateTypes.WHITE_STAINED_GLASS_PANE, StateTypes.ORANGE_STAINED_GLASS_PANE, StateTypes.MAGENTA_STAINED_GLASS_PANE, StateTypes.LIGHT_BLUE_STAINED_GLASS_PANE, StateTypes.YELLOW_STAINED_GLASS_PANE, StateTypes.LIME_STAINED_GLASS_PANE, StateTypes.PINK_STAINED_GLASS_PANE, StateTypes.GRAY_STAINED_GLASS_PANE, StateTypes.LIGHT_GRAY_STAINED_GLASS_PANE, StateTypes.CYAN_STAINED_GLASS_PANE, StateTypes.PURPLE_STAINED_GLASS_PANE, StateTypes.BLUE_STAINED_GLASS_PANE, StateTypes.BROWN_STAINED_GLASS_PANE, StateTypes.GREEN_STAINED_GLASS_PANE, StateTypes.RED_STAINED_GLASS_PANE, StateTypes.BLACK_STAINED_GLASS_PANE);
@@ -34,12 +34,14 @@ public class ItemTags {
public static final ItemTags PLANKS = bind("planks");
public static final ItemTags STONE_BRICKS = bind("stone_bricks");
public static final ItemTags WOODEN_BUTTONS = bind("wooden_buttons");
public static final ItemTags STONE_BUTTONS = bind("stone_buttons");
public static final ItemTags BUTTONS = bind("buttons");
public static final ItemTags CARPETS = bind("carpets");
public static final ItemTags WOOL_CARPETS = bind("carpets");
public static final ItemTags WOODEN_DOORS = bind("wooden_doors");
public static final ItemTags WOODEN_STAIRS = bind("wooden_stairs");
public static final ItemTags WOODEN_SLABS = bind("wooden_slabs");
public static final ItemTags WOODEN_FENCES = bind("wooden_fences");
public static final ItemTags FENCE_GATES = bind("fence_gates");
public static final ItemTags WOODEN_PRESSURE_PLATES = bind("wooden_pressure_plates");
public static final ItemTags WOODEN_TRAPDOORS = bind("wooden_trapdoors");
public static final ItemTags DOORS = bind("doors");
@@ -50,12 +52,17 @@ public class ItemTags {
public static final ItemTags OAK_LOGS = bind("oak_logs");
public static final ItemTags BIRCH_LOGS = bind("birch_logs");
public static final ItemTags ACACIA_LOGS = bind("acacia_logs");
public static final ItemTags CHERRY_LOGS = bind("cherry_logs");
public static final ItemTags JUNGLE_LOGS = bind("jungle_logs");
public static final ItemTags SPRUCE_LOGS = bind("spruce_logs");
public static final ItemTags MANGROVE_LOGS = bind("mangrove_logs");
public static final ItemTags CRIMSON_STEMS = bind("crimson_stems");
public static final ItemTags WARPED_STEMS = bind("warped_stems");
public static final ItemTags BAMBOO_BLOCKS = bind("bamboo_blocks");
public static final ItemTags WART_BLOCKS = bind("wart_blocks");
public static final ItemTags BANNERS = bind("banners");
public static final ItemTags SAND = bind("sand");
public static final ItemTags SMELTS_TO_GLASS = bind("smelts_to_glass");
public static final ItemTags STAIRS = bind("stairs");
public static final ItemTags SLABS = bind("slabs");
public static final ItemTags WALLS = bind("walls");
@@ -84,7 +91,11 @@ public class ItemTags {
public static final ItemTags NON_FLAMMABLE_WOOD = bind("non_flammable_wood");
public static final ItemTags SOUL_FIRE_BASE_BLOCKS = bind("soul_fire_base_blocks");
public static final ItemTags CANDLES = bind("candles");
public static final ItemTags DIRT = bind("dirt");
public static final ItemTags TERRACOTTA = bind("terracotta");
public static final ItemTags COMPLETES_FIND_TREE_TUTORIAL = bind("completes_find_tree_tutorial");
public static final ItemTags BOATS = bind("boats");
public static final ItemTags CHEST_BOATS = bind("chest_boats");
public static final ItemTags FISHES = bind("fishes");
public static final ItemTags SIGNS = bind("signs");
public static final ItemTags MUSIC_DISCS = bind("music_discs");
@@ -92,39 +103,65 @@ public class ItemTags {
public static final ItemTags COALS = bind("coals");
public static final ItemTags ARROWS = bind("arrows");
public static final ItemTags LECTERN_BOOKS = bind("lectern_books");
public static final ItemTags BOOKSHELF_BOOKS = bind("bookshelf_books");
public static final ItemTags BEACON_PAYMENT_ITEMS = bind("beacon_payment_items");
public static final ItemTags STONE_TOOL_MATERIALS = bind("stone_tool_materials");
public static final ItemTags STONE_CRAFTING_MATERIALS = bind("stone_crafting_materials");
public static final ItemTags FREEZE_IMMUNE_WEARABLES = bind("freeze_immune_wearables");
public static final ItemTags AXOLOTL_TEMPT_ITEMS = bind("axolotl_tempt_items");
public static final ItemTags OCCLUDES_VIBRATION_SIGNALS = bind("occludes_vibration_signals");
public static final ItemTags DAMPENS_VIBRATIONS = bind("dampens_vibrations");
public static final ItemTags CLUSTER_MAX_HARVESTABLES = bind("cluster_max_harvestables");
public static final ItemTags COMPASSES = bind("compasses");
public static final ItemTags HANGING_SIGNS = bind("hanging_signs");
public static final ItemTags CREEPER_IGNITERS = bind("creeper_igniters");
public static final ItemTags NOTEBLOCK_TOP_INSTRUMENTS = bind("noteblock_top_instruments");
public static final ItemTags TRIMMABLE_ARMOR = bind("trimmable_armor");
public static final ItemTags TRIM_MATERIALS = bind("trim_materials");
public static final ItemTags TRIM_TEMPLATES = bind("trim_templates");
public static final ItemTags SNIFFER_FOOD = bind("sniffer_food");
public static final ItemTags DECORATED_POT_SHERDS = bind("decorated_pot_sherds");
public static final ItemTags DECORATED_POT_INGREDIENTS = bind("decorated_pot_ingredients");
public static final ItemTags SWORDS = bind("swords");
public static final ItemTags AXES = bind("axes");
public static final ItemTags HOES = bind("hoes");
public static final ItemTags PICKAXES = bind("pickaxes");
public static final ItemTags SHOVELS = bind("shovels");
public static final ItemTags TOOLS = bind("tools");
public static final ItemTags BREAKS_DECORATED_POTS = bind("breaks_decorated_pots");
public static final ItemTags VILLAGER_PLANTABLE_SEEDS = bind("villager_plantable_seeds");
static {
copy(BlockTags.WOOL, ItemTags.WOOL);
copy(BlockTags.PLANKS, ItemTags.PLANKS);
copy(BlockTags.STONE_BRICKS, ItemTags.STONE_BRICKS);
copy(BlockTags.WOODEN_BUTTONS, ItemTags.WOODEN_BUTTONS);
copy(BlockTags.STONE_BUTTONS, ItemTags.STONE_BUTTONS);
copy(BlockTags.BUTTONS, ItemTags.BUTTONS);
copy(BlockTags.CARPETS, ItemTags.CARPETS);
copy(BlockTags.WOOL_CARPETS, ItemTags.WOOL_CARPETS);
copy(BlockTags.WOODEN_DOORS, ItemTags.WOODEN_DOORS);
copy(BlockTags.WOODEN_STAIRS, ItemTags.WOODEN_STAIRS);
copy(BlockTags.WOODEN_SLABS, ItemTags.WOODEN_SLABS);
copy(BlockTags.WOODEN_FENCES, ItemTags.WOODEN_FENCES);
copy(BlockTags.FENCE_GATES, ItemTags.FENCE_GATES);
copy(BlockTags.WOODEN_PRESSURE_PLATES, ItemTags.WOODEN_PRESSURE_PLATES);
copy(BlockTags.DOORS, ItemTags.DOORS);
copy(BlockTags.SAPLINGS, ItemTags.SAPLINGS);
copy(BlockTags.BAMBOO_BLOCKS, ItemTags.BAMBOO_BLOCKS);
copy(BlockTags.OAK_LOGS, ItemTags.OAK_LOGS);
copy(BlockTags.DARK_OAK_LOGS, ItemTags.DARK_OAK_LOGS);
copy(BlockTags.BIRCH_LOGS, ItemTags.BIRCH_LOGS);
copy(BlockTags.ACACIA_LOGS, ItemTags.ACACIA_LOGS);
copy(BlockTags.SPRUCE_LOGS, ItemTags.SPRUCE_LOGS);
copy(BlockTags.MANGROVE_LOGS, ItemTags.MANGROVE_LOGS);
copy(BlockTags.JUNGLE_LOGS, ItemTags.JUNGLE_LOGS);
copy(BlockTags.CHERRY_LOGS, ItemTags.CHERRY_LOGS);
copy(BlockTags.CRIMSON_STEMS, ItemTags.CRIMSON_STEMS);
copy(BlockTags.WARPED_STEMS, ItemTags.WARPED_STEMS);
copy(BlockTags.WART_BLOCKS, ItemTags.WART_BLOCKS);
copy(BlockTags.LOGS_THAT_BURN, ItemTags.LOGS_THAT_BURN);
copy(BlockTags.LOGS, ItemTags.LOGS);
copy(BlockTags.SAND, ItemTags.SAND);
copy(BlockTags.SMELTS_TO_GLASS, ItemTags.SMELTS_TO_GLASS);
copy(BlockTags.SLABS, ItemTags.SLABS);
copy(BlockTags.WALLS, ItemTags.WALLS);
copy(BlockTags.STAIRS, ItemTags.STAIRS);
@@ -140,7 +177,7 @@ public class ItemTags {
copy(BlockTags.FLOWERS, ItemTags.FLOWERS);
copy(BlockTags.SOUL_FIRE_BASE_BLOCKS, ItemTags.SOUL_FIRE_BASE_BLOCKS);
copy(BlockTags.CANDLES, ItemTags.CANDLES);
copy(BlockTags.OCCLUDES_VIBRATION_SIGNALS, ItemTags.OCCLUDES_VIBRATION_SIGNALS);
copy(BlockTags.DAMPENS_VIBRATIONS, ItemTags.DAMPENS_VIBRATIONS);
copy(BlockTags.GOLD_ORES, ItemTags.GOLD_ORES);
copy(BlockTags.IRON_ORES, ItemTags.IRON_ORES);
copy(BlockTags.DIAMOND_ORES, ItemTags.DIAMOND_ORES);
@@ -149,27 +186,50 @@ public class ItemTags {
copy(BlockTags.COAL_ORES, ItemTags.COAL_ORES);
copy(BlockTags.EMERALD_ORES, ItemTags.EMERALD_ORES);
copy(BlockTags.COPPER_ORES, ItemTags.COPPER_ORES);
copy(BlockTags.DIRT, ItemTags.DIRT);
copy(BlockTags.TERRACOTTA, ItemTags.TERRACOTTA);
copy(BlockTags.COMPLETES_FIND_TREE_TUTORIAL, ItemTags.COMPLETES_FIND_TREE_TUTORIAL);
ItemTags.BANNERS.add(ItemTypes.WHITE_BANNER, ItemTypes.ORANGE_BANNER, ItemTypes.MAGENTA_BANNER, ItemTypes.LIGHT_BLUE_BANNER, ItemTypes.YELLOW_BANNER, ItemTypes.LIME_BANNER, ItemTypes.PINK_BANNER, ItemTypes.GRAY_BANNER, ItemTypes.LIGHT_GRAY_BANNER, ItemTypes.CYAN_BANNER, ItemTypes.PURPLE_BANNER, ItemTypes.BLUE_BANNER, ItemTypes.BROWN_BANNER, ItemTypes.GREEN_BANNER, ItemTypes.RED_BANNER, ItemTypes.BLACK_BANNER);
ItemTags.BOATS.add(ItemTypes.OAK_BOAT, ItemTypes.SPRUCE_BOAT, ItemTypes.BIRCH_BOAT, ItemTypes.JUNGLE_BOAT, ItemTypes.ACACIA_BOAT, ItemTypes.DARK_OAK_BOAT);
ItemTags.BOATS.add(ItemTypes.OAK_BOAT, ItemTypes.SPRUCE_BOAT, ItemTypes.BIRCH_BOAT, ItemTypes.JUNGLE_BOAT, ItemTypes.ACACIA_BOAT, ItemTypes.DARK_OAK_BOAT, ItemTypes.MANGROVE_BOAT, ItemTypes.BAMBOO_RAFT, ItemTypes.CHERRY_BOAT).addTag(ItemTags.CHEST_BOATS);
ItemTags.CHEST_BOATS.add(ItemTypes.OAK_CHEST_BOAT, ItemTypes.SPRUCE_CHEST_BOAT, ItemTypes.BIRCH_CHEST_BOAT, ItemTypes.JUNGLE_CHEST_BOAT, ItemTypes.ACACIA_CHEST_BOAT, ItemTypes.DARK_OAK_CHEST_BOAT, ItemTypes.MANGROVE_CHEST_BOAT, ItemTypes.BAMBOO_CHEST_RAFT, ItemTypes.CHERRY_CHEST_BOAT);
ItemTags.FISHES.add(ItemTypes.COD, ItemTypes.COOKED_COD, ItemTypes.SALMON, ItemTypes.COOKED_SALMON, ItemTypes.PUFFERFISH, ItemTypes.TROPICAL_FISH);
copy(BlockTags.STANDING_SIGNS, ItemTags.SIGNS);
copy(BlockTags.CEILING_HANGING_SIGNS, ItemTags.HANGING_SIGNS);
ItemTags.CREEPER_DROP_MUSIC_DISCS.add(ItemTypes.MUSIC_DISC_13, ItemTypes.MUSIC_DISC_CAT, ItemTypes.MUSIC_DISC_BLOCKS, ItemTypes.MUSIC_DISC_CHIRP, ItemTypes.MUSIC_DISC_FAR, ItemTypes.MUSIC_DISC_MALL, ItemTypes.MUSIC_DISC_MELLOHI, ItemTypes.MUSIC_DISC_STAL, ItemTypes.MUSIC_DISC_STRAD, ItemTypes.MUSIC_DISC_WARD, ItemTypes.MUSIC_DISC_11, ItemTypes.MUSIC_DISC_WAIT);
ItemTags.MUSIC_DISCS.addTag(ItemTags.CREEPER_DROP_MUSIC_DISCS).add(ItemTypes.MUSIC_DISC_PIGSTEP);
ItemTags.MUSIC_DISCS.addTag(ItemTags.CREEPER_DROP_MUSIC_DISCS).add(ItemTypes.MUSIC_DISC_PIGSTEP, ItemTypes.MUSIC_DISC_OTHERSIDE, ItemTypes.MUSIC_DISC_5, ItemTypes.MUSIC_DISC_RELIC);
ItemTags.COALS.add(ItemTypes.COAL, ItemTypes.CHARCOAL);
ItemTags.ARROWS.add(ItemTypes.ARROW, ItemTypes.TIPPED_ARROW, ItemTypes.SPECTRAL_ARROW);
ItemTags.LECTERN_BOOKS.add(ItemTypes.WRITTEN_BOOK, ItemTypes.WRITABLE_BOOK);
ItemTags.BEACON_PAYMENT_ITEMS.add(ItemTypes.NETHERITE_INGOT, ItemTypes.EMERALD, ItemTypes.DIAMOND, ItemTypes.GOLD_INGOT, ItemTypes.IRON_INGOT);
ItemTags.PIGLIN_REPELLENTS.add(ItemTypes.SOUL_TORCH).add(ItemTypes.SOUL_LANTERN).add(ItemTypes.SOUL_CAMPFIRE);
ItemTags.PIGLIN_REPELLENTS.add(ItemTypes.SOUL_TORCH, ItemTypes.SOUL_LANTERN, ItemTypes.SOUL_CAMPFIRE);
ItemTags.PIGLIN_LOVED.addTag(ItemTags.GOLD_ORES).add(ItemTypes.GOLD_BLOCK, ItemTypes.GILDED_BLACKSTONE, ItemTypes.LIGHT_WEIGHTED_PRESSURE_PLATE, ItemTypes.GOLD_INGOT, ItemTypes.BELL, ItemTypes.CLOCK, ItemTypes.GOLDEN_CARROT, ItemTypes.GLISTERING_MELON_SLICE, ItemTypes.GOLDEN_APPLE, ItemTypes.ENCHANTED_GOLDEN_APPLE, ItemTypes.GOLDEN_HELMET, ItemTypes.GOLDEN_CHESTPLATE, ItemTypes.GOLDEN_LEGGINGS, ItemTypes.GOLDEN_BOOTS, ItemTypes.GOLDEN_HORSE_ARMOR, ItemTypes.GOLDEN_SWORD, ItemTypes.GOLDEN_PICKAXE, ItemTypes.GOLDEN_SHOVEL, ItemTypes.GOLDEN_AXE, ItemTypes.GOLDEN_HOE, ItemTypes.RAW_GOLD, ItemTypes.RAW_GOLD_BLOCK);
ItemTags.IGNORED_BY_PIGLIN_BABIES.add(ItemTypes.LEATHER);
ItemTags.PIGLIN_FOOD.add(ItemTypes.PORKCHOP, ItemTypes.COOKED_PORKCHOP);
ItemTags.FOX_FOOD.add(ItemTypes.SWEET_BERRIES, ItemTypes.GLOW_BERRIES);
ItemTags.NON_FLAMMABLE_WOOD.add(ItemTypes.WARPED_STEM, ItemTypes.STRIPPED_WARPED_STEM, ItemTypes.WARPED_HYPHAE, ItemTypes.STRIPPED_WARPED_HYPHAE, ItemTypes.CRIMSON_STEM, ItemTypes.STRIPPED_CRIMSON_STEM, ItemTypes.CRIMSON_HYPHAE, ItemTypes.STRIPPED_CRIMSON_HYPHAE, ItemTypes.CRIMSON_PLANKS, ItemTypes.WARPED_PLANKS, ItemTypes.CRIMSON_SLAB, ItemTypes.WARPED_SLAB, ItemTypes.CRIMSON_PRESSURE_PLATE, ItemTypes.WARPED_PRESSURE_PLATE, ItemTypes.CRIMSON_FENCE, ItemTypes.WARPED_FENCE, ItemTypes.CRIMSON_TRAPDOOR, ItemTypes.WARPED_TRAPDOOR, ItemTypes.CRIMSON_FENCE_GATE, ItemTypes.WARPED_FENCE_GATE, ItemTypes.CRIMSON_STAIRS, ItemTypes.WARPED_STAIRS, ItemTypes.CRIMSON_BUTTON, ItemTypes.WARPED_BUTTON, ItemTypes.CRIMSON_DOOR, ItemTypes.WARPED_DOOR, ItemTypes.CRIMSON_SIGN, ItemTypes.WARPED_SIGN);
ItemTags.NON_FLAMMABLE_WOOD.add(ItemTypes.WARPED_STEM, ItemTypes.STRIPPED_WARPED_STEM, ItemTypes.WARPED_HYPHAE, ItemTypes.STRIPPED_WARPED_HYPHAE, ItemTypes.CRIMSON_STEM, ItemTypes.STRIPPED_CRIMSON_STEM, ItemTypes.CRIMSON_HYPHAE, ItemTypes.STRIPPED_CRIMSON_HYPHAE, ItemTypes.CRIMSON_PLANKS, ItemTypes.WARPED_PLANKS, ItemTypes.CRIMSON_SLAB, ItemTypes.WARPED_SLAB, ItemTypes.CRIMSON_PRESSURE_PLATE, ItemTypes.WARPED_PRESSURE_PLATE, ItemTypes.CRIMSON_FENCE, ItemTypes.WARPED_FENCE, ItemTypes.CRIMSON_TRAPDOOR, ItemTypes.WARPED_TRAPDOOR, ItemTypes.CRIMSON_FENCE_GATE, ItemTypes.WARPED_FENCE_GATE, ItemTypes.CRIMSON_STAIRS, ItemTypes.WARPED_STAIRS, ItemTypes.CRIMSON_BUTTON, ItemTypes.WARPED_BUTTON, ItemTypes.CRIMSON_DOOR, ItemTypes.WARPED_DOOR, ItemTypes.CRIMSON_SIGN, ItemTypes.WARPED_SIGN, ItemTypes.WARPED_HANGING_SIGN, ItemTypes.CRIMSON_HANGING_SIGN);
ItemTags.STONE_TOOL_MATERIALS.add(ItemTypes.COBBLESTONE, ItemTypes.BLACKSTONE, ItemTypes.COBBLED_DEEPSLATE);
ItemTags.STONE_CRAFTING_MATERIALS.add(ItemTypes.COBBLESTONE, ItemTypes.BLACKSTONE, ItemTypes.COBBLED_DEEPSLATE);
ItemTags.FREEZE_IMMUNE_WEARABLES.add(ItemTypes.LEATHER_BOOTS, ItemTypes.LEATHER_LEGGINGS, ItemTypes.LEATHER_CHESTPLATE, ItemTypes.LEATHER_HELMET, ItemTypes.LEATHER_HORSE_ARMOR);
ItemTags.AXOLOTL_TEMPT_ITEMS.add(ItemTypes.TROPICAL_FISH_BUCKET);
ItemTags.CLUSTER_MAX_HARVESTABLES.add(ItemTypes.DIAMOND_PICKAXE, ItemTypes.GOLDEN_PICKAXE, ItemTypes.IRON_PICKAXE, ItemTypes.NETHERITE_PICKAXE, ItemTypes.STONE_PICKAXE, ItemTypes.WOODEN_PICKAXE);
ItemTags.COMPASSES.add(ItemTypes.COMPASS, ItemTypes.RECOVERY_COMPASS);
ItemTags.CREEPER_IGNITERS.add(ItemTypes.FLINT_AND_STEEL, ItemTypes.FIRE_CHARGE);
ItemTags.SWORDS.add(ItemTypes.DIAMOND_SWORD, ItemTypes.STONE_SWORD, ItemTypes.GOLDEN_SWORD, ItemTypes.NETHERITE_SWORD, ItemTypes.WOODEN_SWORD, ItemTypes.IRON_SWORD);
ItemTags.AXES.add(ItemTypes.DIAMOND_AXE, ItemTypes.STONE_AXE, ItemTypes.GOLDEN_AXE, ItemTypes.NETHERITE_AXE, ItemTypes.WOODEN_AXE, ItemTypes.IRON_AXE);
ItemTags.PICKAXES.add(ItemTypes.DIAMOND_PICKAXE, ItemTypes.STONE_PICKAXE, ItemTypes.GOLDEN_PICKAXE, ItemTypes.NETHERITE_PICKAXE, ItemTypes.WOODEN_PICKAXE, ItemTypes.IRON_PICKAXE);
ItemTags.SHOVELS.add(ItemTypes.DIAMOND_SHOVEL, ItemTypes.STONE_SHOVEL, ItemTypes.GOLDEN_SHOVEL, ItemTypes.NETHERITE_SHOVEL, ItemTypes.WOODEN_SHOVEL, ItemTypes.IRON_SHOVEL);
ItemTags.HOES.add(ItemTypes.DIAMOND_HOE, ItemTypes.STONE_HOE, ItemTypes.GOLDEN_HOE, ItemTypes.NETHERITE_HOE, ItemTypes.WOODEN_HOE, ItemTypes.IRON_HOE);
ItemTags.TOOLS.addTag(ItemTags.SWORDS).addTag(ItemTags.AXES).addTag(ItemTags.PICKAXES).addTag(ItemTags.SHOVELS).addTag(ItemTags.HOES).add(ItemTypes.TRIDENT);
ItemTags.BREAKS_DECORATED_POTS.addTag(ItemTags.TOOLS);
ItemTags.DECORATED_POT_SHERDS.add(ItemTypes.ANGLER_POTTERY_SHERD, ItemTypes.ARCHER_POTTERY_SHERD, ItemTypes.ARMS_UP_POTTERY_SHERD, ItemTypes.BLADE_POTTERY_SHERD, ItemTypes.BREWER_POTTERY_SHERD, ItemTypes.BURN_POTTERY_SHERD, ItemTypes.DANGER_POTTERY_SHERD, ItemTypes.EXPLORER_POTTERY_SHERD, ItemTypes.FRIEND_POTTERY_SHERD, ItemTypes.HEART_POTTERY_SHERD, ItemTypes.HEARTBREAK_POTTERY_SHERD, ItemTypes.HOWL_POTTERY_SHERD, ItemTypes.MINER_POTTERY_SHERD, ItemTypes.MOURNER_POTTERY_SHERD, ItemTypes.PLENTY_POTTERY_SHERD, ItemTypes.PRIZE_POTTERY_SHERD, ItemTypes.SHEAF_POTTERY_SHERD, ItemTypes.SHELTER_POTTERY_SHERD, ItemTypes.SKULL_POTTERY_SHERD, ItemTypes.SNORT_POTTERY_SHERD);
ItemTags.DECORATED_POT_INGREDIENTS.add(ItemTypes.BRICK).addTag(ItemTags.DECORATED_POT_SHERDS);
ItemTags.TRIMMABLE_ARMOR.add(ItemTypes.NETHERITE_HELMET, ItemTypes.NETHERITE_CHESTPLATE, ItemTypes.NETHERITE_LEGGINGS, ItemTypes.NETHERITE_BOOTS, ItemTypes.DIAMOND_HELMET, ItemTypes.DIAMOND_CHESTPLATE, ItemTypes.DIAMOND_LEGGINGS, ItemTypes.DIAMOND_BOOTS, ItemTypes.GOLDEN_HELMET, ItemTypes.GOLDEN_CHESTPLATE, ItemTypes.GOLDEN_LEGGINGS, ItemTypes.GOLDEN_BOOTS, ItemTypes.IRON_HELMET, ItemTypes.IRON_CHESTPLATE, ItemTypes.IRON_LEGGINGS, ItemTypes.IRON_BOOTS, ItemTypes.CHAINMAIL_HELMET, ItemTypes.CHAINMAIL_CHESTPLATE, ItemTypes.CHAINMAIL_LEGGINGS, ItemTypes.CHAINMAIL_BOOTS, ItemTypes.LEATHER_HELMET, ItemTypes.LEATHER_CHESTPLATE, ItemTypes.LEATHER_LEGGINGS, ItemTypes.LEATHER_BOOTS, ItemTypes.TURTLE_HELMET);
ItemTags.TRIM_MATERIALS.add(ItemTypes.IRON_INGOT, ItemTypes.COPPER_INGOT, ItemTypes.GOLD_INGOT, ItemTypes.LAPIS_LAZULI, ItemTypes.EMERALD, ItemTypes.DIAMOND, ItemTypes.NETHERITE_INGOT, ItemTypes.REDSTONE, ItemTypes.QUARTZ, ItemTypes.AMETHYST_SHARD);
ItemTags.TRIM_TEMPLATES.add(ItemTypes.WARD_ARMOR_TRIM_SMITHING_TEMPLATE, ItemTypes.SPIRE_ARMOR_TRIM_SMITHING_TEMPLATE, ItemTypes.COAST_ARMOR_TRIM_SMITHING_TEMPLATE, ItemTypes.EYE_ARMOR_TRIM_SMITHING_TEMPLATE, ItemTypes.DUNE_ARMOR_TRIM_SMITHING_TEMPLATE, ItemTypes.WILD_ARMOR_TRIM_SMITHING_TEMPLATE, ItemTypes.RIB_ARMOR_TRIM_SMITHING_TEMPLATE, ItemTypes.TIDE_ARMOR_TRIM_SMITHING_TEMPLATE, ItemTypes.SENTRY_ARMOR_TRIM_SMITHING_TEMPLATE, ItemTypes.VEX_ARMOR_TRIM_SMITHING_TEMPLATE, ItemTypes.SNOUT_ARMOR_TRIM_SMITHING_TEMPLATE, ItemTypes.WAYFINDER_ARMOR_TRIM_SMITHING_TEMPLATE, ItemTypes.SHAPER_ARMOR_TRIM_SMITHING_TEMPLATE, ItemTypes.SILENCE_ARMOR_TRIM_SMITHING_TEMPLATE, ItemTypes.RAISER_ARMOR_TRIM_SMITHING_TEMPLATE, ItemTypes.HOST_ARMOR_TRIM_SMITHING_TEMPLATE);
ItemTags.BOOKSHELF_BOOKS.add(ItemTypes.BOOK, ItemTypes.WRITTEN_BOOK, ItemTypes.ENCHANTED_BOOK, ItemTypes.WRITABLE_BOOK, ItemTypes.KNOWLEDGE_BOOK);
ItemTags.NOTEBLOCK_TOP_INSTRUMENTS.add(ItemTypes.ZOMBIE_HEAD, ItemTypes.SKELETON_SKULL, ItemTypes.CREEPER_HEAD, ItemTypes.DRAGON_HEAD, ItemTypes.WITHER_SKELETON_SKULL, ItemTypes.PIGLIN_HEAD, ItemTypes.PLAYER_HEAD);
ItemTags.SNIFFER_FOOD.add(ItemTypes.TORCHFLOWER_SEEDS);
ItemTags.VILLAGER_PLANTABLE_SEEDS.add(ItemTypes.WHEAT_SEEDS, ItemTypes.POTATO, ItemTypes.CARROT, ItemTypes.BEETROOT_SEEDS, ItemTypes.TORCHFLOWER_SEEDS, ItemTypes.PITCHER_POD);
}
String name;
@@ -34,5 +34,12 @@ public enum Instrument {
IRON_XYLOPHONE,
PLING,
SNARE,
XYLOPHONE
XYLOPHONE,
ZOMBIE,
SKELETON,
CREEPER,
DRAGON,
WITHER_SKELETON,
PIGLIN,
CUSTOM_HEAD
}
@@ -18,56 +18,38 @@
package com.github.retrooper.packetevents.protocol.world.states.type;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.protocol.world.MaterialType;
import com.github.retrooper.packetevents.protocol.world.PushReaction;
import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
public class StateType {
private final String name;
private final float blastResistance;
private final float hardness;
private final float slipperiness;
private final float friction;
private final float speed;
private final boolean hasGravity;
private final boolean isAir;
private final boolean isBurnable;
private final boolean isFlammable;
private final boolean isOccluding;
private final boolean isSolid;
private final boolean isLiquid;
private final boolean isBlocking;
private final boolean isAir;
private final boolean requiresCorrectTool;
private final boolean isReplaceable;
private final boolean exceedsCube;
private final PushReaction pushReaction;
private final MaterialType materialType;
public StateType(String name, float blastResistance, float hardness, float slipperiness, float friction, float speed, boolean hasGravity,
boolean isAir, boolean isBurnable, boolean isFlammable, boolean isOccluding, boolean isSolid, boolean isLiquid,
boolean isBlocking, boolean requiresCorrectTool, boolean isReplaceable, boolean exceedsCube, PushReaction pushReaction, MaterialType materialType) {
public StateType(String name, float blastResistance, float hardness, boolean isSolid, boolean isBlocking, boolean isAir, boolean requiresCorrectTool, boolean isShapeExceedsCube, MaterialType materialType) {
this.name = name;
this.blastResistance = blastResistance;
this.hardness = hardness;
this.slipperiness = slipperiness;
this.friction = friction;
this.speed = speed;
this.hasGravity = hasGravity;
this.isAir = isAir;
this.isBurnable = isBurnable;
this.isFlammable = isFlammable;
this.isOccluding = isOccluding;
this.isSolid = isSolid;
this.isLiquid = isLiquid;
this.isBlocking = isBlocking;
this.isAir = isAir;
this.requiresCorrectTool = requiresCorrectTool;
this.isReplaceable = isReplaceable;
this.exceedsCube = exceedsCube;
this.pushReaction = pushReaction;
this.exceedsCube = isShapeExceedsCube;
this.materialType = materialType;
}
public WrappedBlockState createBlockState() {
return WrappedBlockState.getDefaultState(PacketEvents.getAPI().getServerManager().getVersion().toClientVersion(), this);
}
public WrappedBlockState createBlockState(ClientVersion version) {
return WrappedBlockState.getDefaultState(version, this);
}
@@ -84,67 +66,50 @@ public class StateType {
return hardness;
}
public float getSlipperiness() {
return slipperiness;
}
public float getFriction() {
return friction;
}
public float getSpeed() {
return speed;
}
public boolean isHasGravity() {
return hasGravity;
}
public boolean isAir() {
return isAir;
}
public boolean isBurnable() {
return isBurnable;
}
public boolean isFlammable() {
return isFlammable;
}
public boolean isOccluding() {
return isOccluding;
}
public boolean isSolid() {
return isSolid;
}
public boolean isLiquid() {
return isLiquid;
}
public boolean isBlocking() {
return isBlocking;
}
public boolean isAir() {
return isAir;
}
public boolean isRequiresCorrectTool() {
return requiresCorrectTool;
}
public boolean isReplaceable() {
return isReplaceable;
switch (getMaterialType()) {
case AIR:
case STRUCTURAL_AIR:
case REPLACEABLE_PLANT:
case REPLACEABLE_FIREPROOF_PLANT:
case REPLACEABLE_WATER_PLANT:
case WATER:
case BUBBLE_COLUMN:
case LAVA:
case TOP_SNOW:
case FIRE:
return true;
default:
return false;
}
}
public boolean exceedsCube() {
return exceedsCube;
}
public PushReaction getPushReaction() {
return pushReaction;
}
public MaterialType getMaterialType() {
return materialType;
}
@Override
public String toString() {
return name;
}
}
@@ -42,6 +42,7 @@ public enum StateValue {
DISTANCE("distance", Integer::parseInt),
DOWN("down", Boolean::parseBoolean),
DRAG("drag", Boolean::parseBoolean),
DUSTED("dusted", Integer::parseInt),
EAST("east", East::valueOf),
EGGS("eggs", Integer::parseInt),
ENABLED("enabled", Boolean::parseBoolean),
@@ -49,6 +50,7 @@ public enum StateValue {
EYE("eye", Boolean::parseBoolean),
FACE("face", Face::valueOf),
FACING("facing", BlockFace::valueOf),
FLOWER_AMOUNT("flower_amount", Integer::parseInt),
HALF("half", Half::valueOf),
HANGING("hanging", Boolean::parseBoolean),
HAS_BOOK("has_book", Boolean::parseBoolean),
@@ -85,6 +87,12 @@ public enum StateValue {
SHORT("short", Boolean::parseBoolean),
SHRIEKING("shrieking", Boolean::parseBoolean),
SIGNAL_FIRE("signal_fire", Boolean::parseBoolean),
SLOT_0_OCCUPIED("slot_0_occupied", Boolean::parseBoolean),
SLOT_1_OCCUPIED("slot_1_occupied", Boolean::parseBoolean),
SLOT_2_OCCUPIED("slot_2_occupied", Boolean::parseBoolean),
SLOT_3_OCCUPIED("slot_3_occupied", Boolean::parseBoolean),
SLOT_4_OCCUPIED("slot_4_occupied", Boolean::parseBoolean),
SLOT_5_OCCUPIED("slot_5_occupied", Boolean::parseBoolean),
SNOWY("snowy", Boolean::parseBoolean),
STAGE("stage", Integer::parseInt),
SOUTH("south", South::valueOf),
@@ -96,7 +104,8 @@ public enum StateValue {
UP("up", Boolean::parseBoolean),
VERTICAL_DIRECTION("vertical_direction", VerticalDirection::valueOf),
WATERLOGGED("waterlogged", Boolean::parseBoolean),
WEST("west", West::valueOf);
WEST("west", West::valueOf),
CRACKED("cracked", Boolean::parseBoolean);
private final String name;
private final Function<String, Object> parser;
@@ -32,8 +32,9 @@ import java.util.function.Function;
public class PacketEventsSettings {
private TimeStampMode timestampMode = TimeStampMode.MILLIS;
private boolean readOnlyListeners = false;
private boolean defaultReencode = true; // true for backwards compat and more idiot-proof
private boolean checkForUpdates = true;
private boolean downsampleColors = true;
private boolean bStatsEnabled = true;
private boolean debugEnabled = false;
private Function<String, InputStream> resourceProvider = path -> PacketEventsSettings.class
@@ -59,12 +60,12 @@ public class PacketEventsSettings {
}
/**
* Are the packet listeners all read only?
* @param readOnlyListeners Value
* Do we re-encode all packets by default?
* @param reEncodeByDefault Value
* @return Settings instance
*/
public PacketEventsSettings readOnlyListeners(boolean readOnlyListeners) {
this.readOnlyListeners = readOnlyListeners;
public PacketEventsSettings reEncodeByDefault(boolean reEncodeByDefault) {
this.defaultReencode = reEncodeByDefault;
return this;
}
@@ -79,6 +80,17 @@ public class PacketEventsSettings {
return this;
}
/**
* This decides if PacketEvents should downsample RGB colors on pre-1.16 servers.
*
* @param downsampleColors Value
* @return Settings instance.
*/
public PacketEventsSettings downsampleColors(boolean downsampleColors) {
this.downsampleColors = downsampleColors;
return this;
}
/**
* This decides if PacketEvents should collect data anonymously and report to bStats.
*
@@ -115,10 +127,10 @@ public class PacketEventsSettings {
/**
* Should the packet listeners be read only?
* @return Getter for {@link #readOnlyListeners}
* @return Getter for {@link #defaultReencode}
*/
public boolean shouldListenersReadOnly() {
return readOnlyListeners;
public boolean reEncodeByDefault() {
return defaultReencode;
}
/**
@@ -130,6 +142,15 @@ public class PacketEventsSettings {
return checkForUpdates;
}
/**
* Should we downsample RGB colors on pre-1.16 servers?
*
* @return Getter for {@link #downsampleColors}
*/
public boolean shouldDownsampleColors() {
return downsampleColors;
}
/**
* Should we collect server data anonymously and report to bStats?
@@ -27,7 +27,7 @@ import com.github.retrooper.packetevents.protocol.player.User;
public class EventCreationUtil {
public static PacketReceiveEvent createReceiveEvent(Object channel, User user, Object player, Object buffer,
boolean autoProtocolTranslation) throws PacketProcessException {
switch (user.getConnectionState()) {
switch (user.getDecoderState()) {
case HANDSHAKING:
return new PacketHandshakeReceiveEvent(channel, user, player, buffer, autoProtocolTranslation);
case STATUS:
@@ -36,14 +36,15 @@ public class EventCreationUtil {
return new PacketLoginReceiveEvent(channel, user, player, buffer, autoProtocolTranslation);
case PLAY:
return new PacketPlayReceiveEvent(channel, user, player, buffer, autoProtocolTranslation);
default:
return null;
case CONFIGURATION:
return new PacketConfigReceiveEvent(channel, user, player, buffer, autoProtocolTranslation);
}
throw new RuntimeException("Unknown connection state " + user.getDecoderState() + "!");
}
public static PacketSendEvent createSendEvent(Object channel, User user, Object player, Object buffer,
boolean autoProtocolTranslation) throws PacketProcessException{
switch (user.getConnectionState()) {
switch (user.getEncoderState()) {
case HANDSHAKING:
return new PacketHandshakeSendEvent(channel, user, player, buffer, autoProtocolTranslation);
case STATUS:
@@ -52,8 +53,9 @@ public class EventCreationUtil {
return new PacketLoginSendEvent(channel, user, player, buffer, autoProtocolTranslation);
case PLAY:
return new PacketPlaySendEvent(channel, user, player, buffer, autoProtocolTranslation);
default:
return null;
case CONFIGURATION:
return new PacketConfigSendEvent(channel, user, player, buffer, autoProtocolTranslation);
}
throw new RuntimeException("Unknown connection state " + user.getEncoderState() + "!");
}
}
@@ -22,9 +22,8 @@ import java.util.Set;
public class ExceptionUtil {
public static boolean isException(Throwable t, Class<?> clazz) {
Class<?> throwableClass = t.getClass();
while (t != null) {
if (clazz.isAssignableFrom(throwableClass)) {
if (clazz.isAssignableFrom(t.getClass())) {
return true;
}
@@ -1,6 +1,6 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 retrooper and contributors
* 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
@@ -16,15 +16,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.util.reflection;
package com.github.retrooper.packetevents.util;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class ClassUtil {
private static final Map<Class<?>, String> CLASS_SIMPLE_NAME_CACHE = new ConcurrentHashMap<>();
public static String getClassSimpleName(Class<?> cls) {
return CLASS_SIMPLE_NAME_CACHE.computeIfAbsent(cls, k -> cls.getSimpleName());
public class FakeChannelUtil {
public static boolean isFakeChannel(Object channel) {
if (channel.getClass().getSimpleName().equals("FakeChannel")
|| channel.getClass().getSimpleName().equals("SpoofedChannel")) {
return true;
}
return false;
}
}
@@ -0,0 +1,20 @@
package com.github.retrooper.packetevents.util;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
public final class LegacyFormat {
private LegacyFormat() {
}
public static String trimLegacyFormat(String text, int length) {
if (text.length() <= length) {
return text;
}
if (text.charAt(length - 1) == LegacyComponentSerializer.SECTION_CHAR) {
return text.substring(0, length - 1);
}
return text.substring(0, length);
}
}
@@ -19,6 +19,7 @@
package com.github.retrooper.packetevents.util;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.util.adventure.AdventureSerializer;
import com.google.gson.JsonObject;
import java.io.BufferedReader;
@@ -19,6 +19,7 @@
package com.github.retrooper.packetevents.util;
import com.github.retrooper.packetevents.protocol.player.TextureProperty;
import com.github.retrooper.packetevents.util.adventure.AdventureSerializer;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
@@ -25,44 +25,48 @@ import com.github.retrooper.packetevents.event.UserDisconnectEvent;
import com.github.retrooper.packetevents.manager.protocol.ProtocolManager;
import com.github.retrooper.packetevents.netty.buffer.ByteBufHelper;
import com.github.retrooper.packetevents.protocol.player.User;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import org.jetbrains.annotations.Nullable;
import java.util.UUID;
public class PacketEventsImplHelper {
public static PacketSendEvent handleClientBoundPacket(Object channel, User user, Object player,
Object buffer, boolean autoProtocolTranslation,
boolean runPostTasks) throws Exception {
public static PacketSendEvent handleClientBoundPacket(Object channel,
User user,
Object player,
Object buffer,
boolean autoProtocolTranslation) throws Exception {
if (!ByteBufHelper.isReadable(buffer)) return null;
int preProcessIndex = ByteBufHelper.readerIndex(buffer);
PacketSendEvent packetSendEvent = EventCreationUtil.createSendEvent(channel, user, player, buffer,
autoProtocolTranslation);
PacketSendEvent packetSendEvent = EventCreationUtil.createSendEvent(channel, user, player, buffer, autoProtocolTranslation);
int processIndex = ByteBufHelper.readerIndex(buffer);
PacketEvents.getAPI().getEventManager().callEvent(packetSendEvent, () -> {
ByteBufHelper.readerIndex(buffer, processIndex);
});
if (!packetSendEvent.isCancelled()) {
PacketWrapper<?> wrapper = packetSendEvent.getLastUsedWrapper();
if (wrapper != null) {
//Did they ever use a wrapper?
if (packetSendEvent.getLastUsedWrapper() != null) {
//Rewrite the buffer
ByteBufHelper.clear(buffer);
int packetId = packetSendEvent.getPacketId();
packetSendEvent.getLastUsedWrapper().writeVarInt(packetId);
packetSendEvent.getLastUsedWrapper().writeVarInt(packetSendEvent.getPacketId());
packetSendEvent.getLastUsedWrapper().write();
} else {
//If no wrappers were used, just pass on the original buffer.
//Correct the reader index, basically what the next handler is expecting.
ByteBufHelper.readerIndex(buffer, preProcessIndex);
}
ByteBufHelper.readerIndex(buffer, preProcessIndex);
} else {
//Make the buffer unreadable for the next handlers
ByteBufHelper.clear(buffer);
}
if (runPostTasks) {
if (packetSendEvent.hasPostTasks()) {
for (Runnable task : packetSendEvent.getPostTasks()) {
task.run();
}
if (packetSendEvent.hasPostTasks()) {
for (Runnable task : packetSendEvent.getPostTasks()) {
task.run();
}
}
return packetSendEvent;
}
@@ -70,9 +74,10 @@ public class PacketEventsImplHelper {
Object player,
Object buffer,
boolean autoProtocolTranslation) throws Exception {
if (!ByteBufHelper.isReadable(buffer)) return null;
int preProcessIndex = ByteBufHelper.readerIndex(buffer);
PacketReceiveEvent packetReceiveEvent = EventCreationUtil.createReceiveEvent(channel, user, player, buffer,
autoProtocolTranslation);
PacketReceiveEvent packetReceiveEvent = EventCreationUtil.createReceiveEvent(channel, user, player, buffer, autoProtocolTranslation);
int processIndex = ByteBufHelper.readerIndex(buffer);
PacketEvents.getAPI().getEventManager().callEvent(packetReceiveEvent, () -> {
ByteBufHelper.readerIndex(buffer, processIndex);
@@ -84,11 +89,11 @@ public class PacketEventsImplHelper {
ByteBufHelper.clear(buffer);
packetReceiveEvent.getLastUsedWrapper().writeVarInt(packetReceiveEvent.getPacketId());
packetReceiveEvent.getLastUsedWrapper().write();
} else {
//If no wrappers were used, just pass on the original buffer.
//Correct the reader index, basically what the next handler is expecting.
ByteBufHelper.readerIndex(buffer, preProcessIndex);
}
//If no wrappers were used, just pass on the original buffer.
//Correct the reader index, basically what the next handler is expecting.
ByteBufHelper.readerIndex(buffer, preProcessIndex);
} else {
//Cancelling the packet, lets clear the buffer
ByteBufHelper.clear(buffer);
@@ -103,12 +108,12 @@ public class PacketEventsImplHelper {
public static void handleDisconnection(Object channel, @Nullable UUID uuid) {
synchronized (channel) {
User user = ProtocolManager.USERS.get(channel);
User user = PacketEvents.getAPI().getProtocolManager().getUser(channel);
if (user != null) {
UserDisconnectEvent disconnectEvent = new UserDisconnectEvent(user);
PacketEvents.getAPI().getEventManager().callEvent(disconnectEvent);
ProtocolManager.USERS.remove(user.getChannel());
PacketEvents.getAPI().getProtocolManager().removeUser(user.getChannel());
}
if (uuid == null) {
@@ -0,0 +1,69 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 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.util;
//PacketEvents is not a math library, we don't plan to have all quaternion functions in here.
// We just store the 4 float components for you.
public class Quaternion4f {
private float x;
private float y;
private float z;
private float w;
public Quaternion4f(float x, float y, float z, float w) {
this.x = x;
this.y = y;
this.z = z;
this.w = w;
}
public float getX() {
return x;
}
public void setX(float x) {
this.x = x;
}
public float getY() {
return y;
}
public void setY(float y) {
this.y = y;
}
public float getZ() {
return z;
}
public void setZ(float z) {
this.z = z;
}
public float getW() {
return w;
}
public void setW(float w) {
this.w = w;
}
}
@@ -0,0 +1,128 @@
package com.github.retrooper.packetevents.util.adventure;
import com.github.retrooper.packetevents.util.reflection.Reflection;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import net.kyori.adventure.key.Key;
import net.kyori.adventure.text.BlockNBTComponent;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.format.TextDecoration;
import net.kyori.adventure.util.Index;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.function.Function;
public class AdventureReflectionUtil {
static TypeAdapter<Key> KEY_SERIALIZER_INSTANCE;
static Function<Gson, Object> COMPONENT_SERIALIZER_CREATE;
static TypeAdapter<ClickEvent.Action> CLICK_EVENT_ACTION_SERIALIZER_INSTANCE;
static TypeAdapter<HoverEvent.Action<?>> HOVER_EVENT_ACTION_SERIALIZER_INSTANCE;
static Function<Gson, Object> SHOW_ITEM_SERIALIZER_CREATE;
static Function<Gson, Object> SHOW_ENTITY_SERIALIZER_CREATE;
static TypeAdapter<TextColor> TEXT_COLOR_SERIALIZER_INSTANCE;
static TypeAdapter<TextColor> TEXT_COLOR_SERIALIZER_DOWNSAMPLE_COLOR_INSTANCE;
static TypeAdapter<TextDecoration> TEXT_DECORATION_SERIALIZER_INSTANCE;
static TypeAdapter<BlockNBTComponent.Pos> BLOCK_NBT_POS_SERIALIZER_INSTANCE;
static {
Class<?> KEY_SERIALIZER = Reflection.getClassByNameWithoutException("net.kyori.adventure.text.serializer.gson.KeySerializer");
Field KEY_SERIALIZER_INSTANCE_FIELD = Reflection.getField(KEY_SERIALIZER, "INSTANCE");
KEY_SERIALIZER_INSTANCE = (TypeAdapter<Key>) getSafe(KEY_SERIALIZER_INSTANCE_FIELD);
Class<?> COMPONENT_SERIALIZER = Reflection.getClassByNameWithoutException("net.kyori.adventure.text.serializer.gson.ComponentSerializerImpl");
Class<?> SHOW_ITEM_SERIALIZER = Reflection.getClassByNameWithoutException("net.kyori.adventure.text.serializer.gson.ShowItemSerializer");
Class<?> SHOW_ENTITY_SERIALIZER = Reflection.getClassByNameWithoutException("net.kyori.adventure.text.serializer.gson.ShowEntitySerializer");
if (GsonComponentSerializerExtended.LEGACY_ADVENTURE) {
Constructor<?> COMPONENT_SERIALIZER_CONSTRUCTOR = Reflection.getConstructor(COMPONENT_SERIALIZER, 0);
COMPONENT_SERIALIZER_CREATE = gson -> invokeSafe(COMPONENT_SERIALIZER_CONSTRUCTOR);
Class<?> INDEXED_SERIALIZER_CLASS = Reflection.getClassByNameWithoutException("net.kyori.adventure.text.serializer.gson.IndexedSerializer");
Method INDEXED_SERIALIZER_CREATE_METHOD = Reflection.getMethod(INDEXED_SERIALIZER_CLASS, "of", String.class, Index.class);
CLICK_EVENT_ACTION_SERIALIZER_INSTANCE = (TypeAdapter<ClickEvent.Action>) invokeSafe(INDEXED_SERIALIZER_CREATE_METHOD, "click action", ClickEvent.Action.NAMES);
HOVER_EVENT_ACTION_SERIALIZER_INSTANCE = (TypeAdapter<HoverEvent.Action<?>>) invokeSafe(INDEXED_SERIALIZER_CREATE_METHOD, "hover action", HoverEvent.Action.NAMES);
TEXT_DECORATION_SERIALIZER_INSTANCE = (TypeAdapter<TextDecoration>) invokeSafe(INDEXED_SERIALIZER_CREATE_METHOD, "text decoration", TextDecoration.NAMES);
Constructor<?> SHOW_ITEM_SERIALIZER_CONSTRUCTOR = Reflection.getConstructor(SHOW_ITEM_SERIALIZER, 0);
SHOW_ITEM_SERIALIZER_CREATE = gson -> invokeSafe(SHOW_ITEM_SERIALIZER_CONSTRUCTOR);
Constructor<?> SHOW_ENTITY_SERIALIZER_CONSTRUCTOR = Reflection.getConstructor(SHOW_ENTITY_SERIALIZER, 0);
SHOW_ENTITY_SERIALIZER_CREATE = gson -> invokeSafe(SHOW_ENTITY_SERIALIZER_CONSTRUCTOR);
} else {
Method COMPONENT_SERIALIZER_CREATE_METHOD = Reflection.getMethod(COMPONENT_SERIALIZER, "create", Gson.class);
COMPONENT_SERIALIZER_CREATE = gson -> invokeSafe(COMPONENT_SERIALIZER_CREATE_METHOD, gson);
Class<?> CLICK_EVENT_ACTION_SERIALIZER = Reflection.getClassByNameWithoutException("net.kyori.adventure.text.serializer.gson.ClickEventActionSerializer");
Field CLICK_EVENT_ACTION_SERIALIZER_INSTANCE_FIELD = Reflection.getField(CLICK_EVENT_ACTION_SERIALIZER, "INSTANCE");
CLICK_EVENT_ACTION_SERIALIZER_INSTANCE = (TypeAdapter<ClickEvent.Action>) getSafe(CLICK_EVENT_ACTION_SERIALIZER_INSTANCE_FIELD);
Class<?> HOVER_EVENT_ACTION_SERIALIZER = Reflection.getClassByNameWithoutException("net.kyori.adventure.text.serializer.gson.HoverEventActionSerializer");
Field HOVER_EVENT_ACTION_SERIALIZER_INSTANCE_FIELD = Reflection.getField(HOVER_EVENT_ACTION_SERIALIZER, "INSTANCE");
HOVER_EVENT_ACTION_SERIALIZER_INSTANCE = (TypeAdapter<HoverEvent.Action<?>>) getSafe(HOVER_EVENT_ACTION_SERIALIZER_INSTANCE_FIELD);
Class<?> TEXT_DECORATION_SERIALIZER = Reflection.getClassByNameWithoutException("net.kyori.adventure.text.serializer.gson.TextDecorationSerializer");
Field TEXT_DECORATION_SERIALIZER_INSTANCE_FIELD = Reflection.getField(TEXT_DECORATION_SERIALIZER, "INSTANCE");
TEXT_DECORATION_SERIALIZER_INSTANCE = (TypeAdapter<TextDecoration>) getSafe(TEXT_DECORATION_SERIALIZER_INSTANCE_FIELD);
Method SHOW_ITEM_SERIALIZER_CREATE_METHOD = Reflection.getMethod(SHOW_ITEM_SERIALIZER, "create", Gson.class);
SHOW_ITEM_SERIALIZER_CREATE = gson -> invokeSafe(SHOW_ITEM_SERIALIZER_CREATE_METHOD, gson);
Method SHOW_ENTITY_SERIALIZER_CREATE_METHOD = Reflection.getMethod(SHOW_ENTITY_SERIALIZER, "create", Gson.class);
SHOW_ENTITY_SERIALIZER_CREATE = gson -> invokeSafe(SHOW_ENTITY_SERIALIZER_CREATE_METHOD, gson);
}
Class<?> TEXT_COLOR_SERIALIZER = Reflection.getClassByNameWithoutException("net.kyori.adventure.text.serializer.gson.TextColorSerializer");
Field TEXT_COLOR_SERIALIZER_INSTANCE_FIELD = Reflection.getField(TEXT_COLOR_SERIALIZER, "INSTANCE");
TEXT_COLOR_SERIALIZER_INSTANCE = (TypeAdapter<TextColor>) getSafe(TEXT_COLOR_SERIALIZER_INSTANCE_FIELD);
Field TEXT_COLOR_SERIALIZER_DOWNSAMPLE_COLOR_INSTANCE_FIELD = Reflection.getField(TEXT_COLOR_SERIALIZER, "DOWNSAMPLE_COLOR");
TEXT_COLOR_SERIALIZER_DOWNSAMPLE_COLOR_INSTANCE = (TypeAdapter<TextColor>) getSafe(TEXT_COLOR_SERIALIZER_DOWNSAMPLE_COLOR_INSTANCE_FIELD);
Class<?> BLOCK_NBT_COMPONENT_POS_SERIALIZER = Reflection.getClassByNameWithoutException("net.kyori.adventure.text.serializer.gson.BlockNBTComponentPosSerializer");
Field BLOCK_NBT_COMPONENT_POS_SERIALIZER_INSTANCE_FIELD = Reflection.getField(BLOCK_NBT_COMPONENT_POS_SERIALIZER, "INSTANCE");
BLOCK_NBT_POS_SERIALIZER_INSTANCE = (TypeAdapter<BlockNBTComponent.Pos>) getSafe(BLOCK_NBT_COMPONENT_POS_SERIALIZER_INSTANCE_FIELD);
}
static Object getSafe(Field field) {
return getSafe(field, null);
}
static Object getSafe(Field field, Object instance) {
if (field == null) return null;
try {
return field.get(instance);
} catch (Exception e) {
return null;
}
}
static Object invokeSafe(Method method, Object... params) {
return invokeSafe(null, method, params);
}
static Object invokeSafe(Object instance, Method method, Object... params) {
if (method == null) return null;
try {
return method.invoke(instance, params);
} catch (Exception e) {
return null;
}
}
static Object invokeSafe(Constructor<?> constructor, Object... params) {
if (constructor == null) return null;
try {
return constructor.newInstance(params);
} catch (Exception e) {
return null;
}
}
}
@@ -16,11 +16,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.retrooper.packetevents.util;
package com.github.retrooper.packetevents.util.adventure;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.util.adventure.GsonComponentSerializerExtended;
import com.google.gson.JsonElement;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
@@ -29,29 +28,37 @@ import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
public class AdventureSerializer {
private static GsonComponentSerializer GSON;
private static final LegacyComponentSerializer LEGACY = LegacyComponentSerializer.builder().build();
public static String asVanilla(Component component) {
return LEGACY.serialize(component);
}
public static Component fromLegacyFormat(String legacyMessage) {
return LEGACY.deserialize(legacyMessage);
}
private static LegacyComponentSerializer LEGACY;
public static GsonComponentSerializer getGsonSerializer() {
if (GSON == null) {
ServerVersion version = PacketEvents.getAPI().getServerManager().getVersion();
GSON = new GsonComponentSerializerExtended(version.isOlderThan(ServerVersion.V_1_16),
version.isOlderThanOrEquals(ServerVersion.V_1_12_2));
GSON = new GsonComponentSerializerExtended(
version.isOlderThan(ServerVersion.V_1_16) && PacketEvents.getAPI().getSettings().shouldDownsampleColors(),
version.isOlderThanOrEquals(ServerVersion.V_1_12_2)
);
}
return GSON;
}
public static LegacyComponentSerializer getLegacyGsonSerializer() {
if (LEGACY == null) {
LegacyComponentSerializer.Builder builder = LegacyComponentSerializer.builder();
if (!PacketEvents.getAPI().getSettings().shouldDownsampleColors() || PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_16))
builder = builder.hexColors();
LEGACY = builder.build();
}
return LEGACY;
}
public static String asVanilla(Component component) {
return getLegacyGsonSerializer().serialize(component);
}
public static Component fromLegacyFormat(String legacyMessage) {
return getLegacyGsonSerializer().deserialize(legacyMessage);
}
public static Component parseComponent(String json) {
return getGsonSerializer().deserialize(json);
}
@@ -18,12 +18,20 @@
package com.github.retrooper.packetevents.util.adventure;
import com.github.retrooper.packetevents.util.reflection.Reflection;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import net.kyori.adventure.key.Key;
import net.kyori.adventure.text.BlockNBTComponent;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.gson.*;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.format.Style;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.format.TextDecoration;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -34,18 +42,33 @@ import java.util.function.UnaryOperator;
*/
public class GsonComponentSerializerExtended implements GsonComponentSerializer {
static boolean LEGACY_ADVENTURE = Reflection.getClassByNameWithoutException("net.kyori.adventure.text.serializer.gson.SerializerFactory") == null;
private final Gson serializer;
private final UnaryOperator<GsonBuilder> populator;
private final boolean downsampleColor;
private final boolean emitLegacyHover;
public GsonComponentSerializerExtended(final boolean downsampleColor, final boolean emitLegacyHover) {
this.downsampleColor = downsampleColor;
this.emitLegacyHover = emitLegacyHover;
this.populator = builder -> {
builder.registerTypeAdapterFactory(new SerializerFactory(downsampleColor, emitLegacyHover));
return builder;
};
if (LEGACY_ADVENTURE) {
this.populator = builder -> {
builder.registerTypeHierarchyAdapter(Key.class, AdventureReflectionUtil.KEY_SERIALIZER_INSTANCE);
builder.registerTypeHierarchyAdapter(Component.class, AdventureReflectionUtil.COMPONENT_SERIALIZER_CREATE.apply(null));
builder.registerTypeHierarchyAdapter(Style.class, new Legacy_StyleSerializerExtended(emitLegacyHover));
builder.registerTypeAdapter(ClickEvent.Action.class, AdventureReflectionUtil.CLICK_EVENT_ACTION_SERIALIZER_INSTANCE);
builder.registerTypeAdapter(HoverEvent.Action.class, AdventureReflectionUtil.HOVER_EVENT_ACTION_SERIALIZER_INSTANCE);
builder.registerTypeAdapter(HoverEvent.ShowItem.class, AdventureReflectionUtil.SHOW_ITEM_SERIALIZER_CREATE.apply(null));
builder.registerTypeAdapter(HoverEvent.ShowEntity.class, AdventureReflectionUtil.SHOW_ENTITY_SERIALIZER_CREATE.apply(null));
builder.registerTypeAdapter(TextColorWrapper.class, TextColorWrapper.Serializer.INSTANCE);
builder.registerTypeHierarchyAdapter(TextColor.class, downsampleColor ? AdventureReflectionUtil.TEXT_COLOR_SERIALIZER_DOWNSAMPLE_COLOR_INSTANCE : AdventureReflectionUtil.TEXT_COLOR_SERIALIZER_INSTANCE);
builder.registerTypeAdapter(TextDecoration.class, AdventureReflectionUtil.TEXT_DECORATION_SERIALIZER_INSTANCE);
builder.registerTypeHierarchyAdapter(BlockNBTComponent.Pos.class, AdventureReflectionUtil.BLOCK_NBT_POS_SERIALIZER_INSTANCE);
return builder;
};
} else {
this.populator = builder -> {
builder.registerTypeAdapterFactory(new SerializerFactory(downsampleColor, emitLegacyHover));
return builder;
};
}
this.serializer = this.populator.apply(new GsonBuilder()).create();
}
@@ -93,7 +116,7 @@ public class GsonComponentSerializerExtended implements GsonComponentSerializer
@Override
public @NotNull Builder toBuilder() {
return null; // We don't need to support this
throw new UnsupportedOperationException("Builder pattern is not supported."); // We don't need to support this
}
}
@@ -31,6 +31,8 @@ import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.util.Codec;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.Range;
import java.io.IOException;
import java.util.Locale;
@@ -42,7 +44,7 @@ import java.util.regex.Pattern;
public class HoverSerializer {
private static final TagStringIO SNBT_IO = TagStringIO.get();
private static final Codec<CompoundBinaryTag, String, IOException, IOException> SNBT_CODEC = Codec.codec(SNBT_IO::asCompound, SNBT_IO::asString);
private static final Codec<CompoundBinaryTag, String, IOException, IOException> SNBT_CODEC = createCodec(SNBT_IO::asCompound, SNBT_IO::asString);
static final String ITEM_TYPE = "id";
static final String ITEM_COUNT = "Count";
@@ -53,54 +55,48 @@ public class HoverSerializer {
static final String ENTITY_ID = "id";
static final Pattern LEGACY_NAME_PATTERN = Pattern.compile("([A-Z][a-z]+)([A-Z][a-z]+)?");
private final Gson gson;
public HoverSerializer(Gson gson) {
this.gson = gson;
}
public HoverEvent.ShowItem deserializeShowItem(final JsonElement input, boolean legacy) throws IOException {
public HoverEvent.ShowItem deserializeShowItem(final GsonLike gson, final JsonElement input, boolean legacy) throws IOException {
if (legacy) {
Component component = this.gson.fromJson(input, Component.class);
final Component component = gson.fromJson(input, Component.class);
assertTextComponent(component);
final CompoundBinaryTag contents = SNBT_CODEC.decode(((TextComponent) component).content());
final CompoundBinaryTag tag = contents.getCompound(ITEM_TAG);
return HoverEvent.ShowItem.of(
return createShowItem(
Key.key(contents.getString(ITEM_TYPE)),
contents.getByte(ITEM_COUNT, (byte) 1),
tag == CompoundBinaryTag.empty() ? null : BinaryTagHolder.encode(tag, SNBT_CODEC)
);
} else {
return this.gson.fromJson(input, HoverEvent.ShowItem.class);
return gson.fromJson(input, HoverEvent.ShowItem.class);
}
}
public HoverEvent.ShowEntity deserializeShowEntity(final JsonElement input, final Codec.Decoder<Component, String, ? extends RuntimeException> componentCodec, boolean legacy) throws IOException {
public HoverEvent.ShowEntity deserializeShowEntity(final GsonLike gson, final JsonElement input, final Codec.Decoder<Component, String, ? extends RuntimeException> componentCodec, boolean legacy) throws IOException {
if (legacy) {
Component component = this.gson.fromJson(input, Component.class);
final Component component = gson.fromJson(input, Component.class);
assertTextComponent(component);
final CompoundBinaryTag contents = SNBT_CODEC.decode(((TextComponent) component).content());
String type = contents.getString(ENTITY_TYPE);
Matcher matcher = LEGACY_NAME_PATTERN.matcher(type);
final Matcher matcher = LEGACY_NAME_PATTERN.matcher(type);
if (matcher.matches()) {
StringJoiner joiner = new StringJoiner("_");
final StringJoiner joiner = new StringJoiner("_");
joiner.add(matcher.group(1));
if (matcher.group(2) != null) {
joiner.add(matcher.group(2));
}
type = joiner.toString().toLowerCase(Locale.ROOT);
}
return HoverEvent.ShowEntity.of(
return createShowEntity(
Key.key(type),
UUID.fromString(contents.getString(ENTITY_ID)),
componentCodec.decode(contents.getString(ENTITY_NAME))
);
} else {
return this.gson.fromJson(input, HoverEvent.ShowEntity.class);
return gson.fromJson(input, HoverEvent.ShowEntity.class);
}
}
public Component deserializeShowAchievement(final JsonElement input) throws IOException {
public Component deserializeShowAchievement(final JsonElement input) {
assertStringValue(input);
return Statistics.getById(input.getAsString()).display();
}
@@ -139,4 +135,39 @@ public class HoverSerializer {
return Component.text(SNBT_CODEC.encode(builder.build()));
}
public interface GsonLike {
static GsonLike fromGson(final Gson gson) {
return gson::fromJson;
}
<T> T fromJson(final @Nullable JsonElement json, final Class<T> classOfT);
}
// Backward Compatibility
private static HoverEvent.ShowItem createShowItem(final @NotNull Key item, final @Range(from = 0, to = Integer.MAX_VALUE) int count, final @Nullable BinaryTagHolder nbt) {
try {
return HoverEvent.ShowItem.showItem(item, count, nbt);
} catch (final NoSuchMethodError ignored) {
return HoverEvent.ShowItem.of(item, count, nbt);
}
}
private static HoverEvent.ShowEntity createShowEntity(final @NotNull Key type, final @NotNull UUID id, final @Nullable Component name) {
try {
return HoverEvent.ShowEntity.showEntity(type, id, name);
} catch (final NoSuchMethodError ignored) {
return HoverEvent.ShowEntity.of(type, id, name);
}
}
private static <D, E, DX extends Throwable, EX extends Throwable> @NotNull Codec<D, E, DX, EX> createCodec(final @NotNull Codec.Decoder<D, E, DX> decoder, final @NotNull Codec.Encoder<D, E, EX> encoder) {
try {
return Codec.codec(decoder, encoder);
} catch (final NoSuchMethodError ignored) {
return Codec.of(decoder, encoder);
}
}
}
Loaded 100 of 239 files, more files were not shown because too many files have changed in this diff. Show more